diff --git a/BIOP_Clustering.m b/BIOP_Clustering.m index 5ed429b..8e535c4 100644 --- a/BIOP_Clustering.m +++ b/BIOP_Clustering.m @@ -1,758 +1,758 @@ function BIOP_Clustering %Start EasyXT addpath('EasyXT'); addpath('functions'); global X; X = EasyXT(); -f = figure('Name', 'BIOP - Clustering WingJ', ... +f = figure('Name', 'BIOP - Clustering', ... 'NumberTitle', 'off', 'Visible', 'off', 'Position', [0 0 700 512], ... 'Tag', 'clustetring_main_f', ... 'DockControls', 'off', 'ToolBar', 'none', 'MenuBar', 'none'); % Move the window to the center of the screen. movegui(f,'center'); % Make the window visible. f.Visible = 'on'; % Add 1 panel on the left and one on the right settingsp = uipanel(f,'Title','Settings', 'Tag', 'p_settings',... 'Position',[.05 .05 .65 .9]); commandsp = uipanel(f,'Title','Actions', 'Tag', 'p_commands',... 'Position',[.70 .05 .25 .9]); % Settings Tab uitabgroup('Parent', settingsp, 'Tag', 'tab_channels'); % Add buttons for refreshing data, and batch h = .1; w = .9; l = .05; uicontrol(commandsp,'Style','pushbutton','String','Refresh',... 'Units','normalized', 'Tag', 'btn_refresh', ... 'Position',[l .90 w h],... 'Callback', @btn_refresh_callback); uicontrol(commandsp,'Style','pushbutton','String','Get Sum Channel',... 'Units','normalized', 'Tag', 'btn_sum', ... 'Position',[l .8 w h],... 'Callback', @btn_sum_callback); uicontrol(commandsp,'Style','pushbutton','String','Clear Outside Sum Channel',... 'Units','normalized', 'Tag', 'btn_clear_outside', ... 'Position',[l .7 w h],... 'Callback', @btn_clear_outside_callback); uicontrol(commandsp,'Style','pushbutton','String','Detect Spots',... 'Units','normalized', 'Tag', 'btn_detect_spots', ... 'Position',[l .6 w h],... 'Callback', @btn_detect_spots_callback); uicontrol(commandsp,'Style','pushbutton','String','Cluster Spots',... 'Units','normalized', 'Tag', 'btn_cluster_spots', ... 'Position',[l .5 w h],... 'Callback', @btn_cluster_spots_callback); uicontrol(commandsp,'Style','pushbutton','String','Reassign Spots',... 'Units','normalized', 'Tag', 'btn_reassign_spots', ... 'Position',[l .4 w h],... 'Callback', @btn_reassign_spots_callback); % Load WingJ uicontrol(commandsp,'Style','pushbutton','String','Load WingJ Data',... 'Units','normalized', 'Tag', 'btn_wingj', ... 'Position',[l .3 w h],... 'Callback', @btn_wingj_callback); uicontrol(commandsp,'Style','pushbutton','String','Export To CSV',... 'Units','normalized', 'Tag', 'btn_export', ... 'Position',[l .2 w h],... 'Callback', @btn_export_callback); uicontrol(commandsp,'Style','text',... 'String','Settings',... 'Units','Normalized', ... 'HorizontalAlignment', 'center', ... 'Position',[l .10 w 0.05]); uicontrol(commandsp,'Style','pushbutton','String','Save',... 'Units','normalized', 'Tag', 'btn_save', ... 'Position',[l .05 w/2 h/2],... 'Callback', @savebtn_callback); uicontrol(commandsp,'Style','pushbutton','String','load',... 'Units','normalized', 'Tag', 'btn_load', ... 'Position',[l+w/2 .05 w/2 h/2],... 'Callback', @loadbtn_callback); % Make all the settings % Settings Tab tgroup = uitabgroup('Parent', settingsp, 'Tag', 'tab_channels'); makeChanSumTab(tgroup); makeCleanChanTab(tgroup); makeSpotDetectionTab(tgroup); makeClusteringTab(tgroup); makeReassignTab(tgroup); makeWingJTab(tgroup) %makeExportTab(tgroup); end function makeChanSumTab(parent) global X; tabTag = 'tab_chan_sum'; tabName = 'Sum Channels'; thisTab = findobj('Tag',tabTag); if isempty(thisTab) thisTab = uitab('Parent', parent, 'Title', tabName, ... 'Tag', tabTag); % Add all the controls %Control settings %Channels of interest as checkboxes sp = 0.05; nChan = X.GetSize('C'); uicontrol(thisTab,'Style','text',... 'String','Channels to Sum',... 'Units','Normalized', ... 'HorizontalAlignment', 'left', ... 'Position',[.05 0.9 .3 sp]); for k=1:nChan; cbh(k) = uicontrol(thisTab, 'Style','checkbox','String',sprintf('Channel %d',k), ... 'Tag', sprintf('is_sum_chan_%d',k), ... 'Value',1, ... 'Units', 'Normalized', ... 'Position',[.05 .9-sp*k .3 sp]); end % Ask if we perform normalization uicontrol(thisTab, 'Style','checkbox','String','Normalize Channels Before Sum', ... 'Tag', 'is_chan_norm', ... 'Value',1, ... 'Units', 'Normalized', ... 'Position',[.05 0.9-sp*(nChan+3) .5 sp]); end end function makeCleanChanTab(parent) tabTag = 'tab_clean'; tabName = 'Clean Channel'; thisTab = findobj('Tag',tabTag); if isempty(thisTab) thisTab = uitab('Parent', parent, 'Title', tabName, ... 'Tag', tabTag); % Add all the controls %Control position sp = 0.05; py = 0.89; % Channel for surface creation uicontrol(thisTab,'Style','text',... 'String','Surface Channel',... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py .3 sp]); uicontrol(thisTab,'Style','edit',... 'String','',... 'Units','Normalized', ... 'Tag', 'txt_channel_surface', ... 'Position',[.36 py+.01 .1 sp]); % Smoothing Factor for Surface uicontrol(thisTab,'Style','text',... 'String','Surface Smoothing',... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py-sp .3 sp]); uicontrol(thisTab,'Style','edit',... 'String','5.0',... 'Units','Normalized', ... 'Tag', 'txt_surface_smooth', ... 'Position',[.36 py+.01-sp .1 sp]); % Surface Intensity Threshold uicontrol(thisTab,'Style','text',... 'String','Intensity Threshold',... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py-2*sp .3 sp]); uicontrol(thisTab,'Style','edit',... 'String','15',... 'Units','Normalized', ... 'Tag', 'txt_surface_intensity_threshold', ... 'Position',[.36 py+.01-2*sp .1 sp]); end end function makeSpotDetectionTab(parent) tabTag = 'tab_detect'; tabName = 'Detect Spots'; thisTab = findobj('Tag',tabTag); if isempty(thisTab) thisTab = uitab('Parent', parent, 'Title', tabName, ... 'Tag', tabTag); % Add all the controls %Control position sp = 0.05; py = 0.89; % Spot Detection Channel uicontrol(thisTab,'Style','text',... 'String','Spot Channel',... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py .3 sp]); uicontrol(thisTab,'Style','edit',... 'String','',... 'Units','Normalized', ... 'Tag', 'txt_channel_spot', ... 'Position',[.36 py+.01 .1 sp]); % Spot Spot Sizes uicontrol(thisTab,'Style','text',... 'String','Spot Size [um]',... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py-sp .3 sp]); % XY uicontrol(thisTab,'Style','edit',... 'String','2.8',... 'Units','Normalized', ... 'Tag', 'txt_spot_size_xy', ... 'Position',[.36 py+.01-sp .1 sp]); % Z (Optional) uicontrol(thisTab,'Style','edit',... 'String','2.8',... 'Units','Normalized', ... 'Tag', 'txt_spot_size_z', ... 'Position',[.47 py+.01-sp .1 sp]); % Spot Quality Threshold uicontrol(thisTab,'Style','text',... 'String','Spot Quality Threshold',... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py-2*sp .30 sp]); uicontrol(thisTab,'Style','edit',... 'String','15',... 'Units','Normalized', ... 'Tag', 'txt_spot_quality_threshold', ... 'Position',[.36 py+.01-2*sp .1 sp]); % Remove Spots Closer than uicontrol(thisTab,'Style','checkbox',... 'String','Remove Spots if closer than',... 'Tag', 'is_remove_spots', ... 'Units','Normalized', ... 'Position',[.05 py-3*sp .40 sp]); uicontrol(thisTab,'Style','edit',... 'String','1.0',... 'Units','Normalized', ... 'Tag', 'txt_spot_proximity_threshold', ... 'Position',[.45 py-3*sp .07 sp]); uicontrol(thisTab,'Style','text',... 'String','um to image edge',... 'Units','Normalized', ... 'HorizontalAlignment', 'left', ... 'Position',[.53 py-3*sp-.01 .30 sp]); end end function makeClusteringTab(parent) tabTag = 'tab_cluster'; tabName = 'Cluster'; thisTab = findobj('Tag',tabTag); if isempty(thisTab) thisTab = uitab('Parent', parent, 'Title', tabName, ... 'Tag', tabTag); % Add all the controls % Need 3 tabs: Manual Clustering, Brute Force and KMeans clusMode = uitabgroup('Parent', thisTab, 'Tag', 'tab_cluster_modes'); %Settings for clustering tab makeSettingsClusterTab(clusMode); % Manual Tab makeManualClusterTab(clusMode); % Brute Force makeBruteClusterTab(clusMode); % KMeans Tab makeKMeansClusterTab(clusMode); end end function makeManualClusterTab(parent) tabTag = 'tab_cluster_manual'; tabName = 'Manual'; thisTab = findobj('Tag',tabTag); sp = .05; py = .89; if isempty(thisTab) thisTab = uitab('Parent', parent, 'Title', tabName, ... 'Tag', tabTag); uicontrol(thisTab,'Style','checkbox',... 'String','Use Manual Clustering',... 'Tag', 'is_do_manual', ... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py+sp .4 sp]); uicontrol(thisTab,'Style','text',... 'String','Number of Categories',... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py-sp .3 sp]); uicontrol(thisTab,'Style','edit',... 'String','2',... 'Units','Normalized', ... 'Tag', 'txt_manual_cat_num', ... 'Position',[.36 py+.01-sp .1 sp], ... 'Callback', @txt_manual_cat_num_callback); end updateManualTab(thisTab); end function txt_manual_cat_num_callback(hObject, eventdata, handles) parent = findobj('Tag', 'tab_cluster_manual'); updateManualTab(parent); end function updateManualTab(parent) global X; % Add all the controls % Grab all the channels that we need to build the settings for chanIdx = getChannelIndexes(); nChan = X.GetSize('C'); numcat = str2num(get(findobj('Tag', 'txt_manual_cat_num'), 'String')); py = 0.89; sp = 0.05; % Make the labels for the columns but only if they do not exist already... if isempty(findobj('Tag', 'txt_bg')) uicontrol(parent,'Style','text',... 'String','BG',... 'Units','Normalized', ... 'Tag', sprintf('txt_bg') , ... 'HorizontalAlignment', 'center', ... 'Position',[.26 py-2*sp .1 sp]); end for n=1:(numcat-1) l = findobj('Tag', sprintf('txt_thr_%d', n)); if isempty(l) thrtxt(n) = uicontrol(parent,'Style','text',... 'String',sprintf('Thr %d', n),... 'Tag',sprintf('txt_thr_%d', n), ... 'Units','Normalized', ... 'HorizontalAlignment', 'center', ... 'Position',[.26+n*.1 py-2*sp .1 sp], ... 'Visible', 'on'); else thrtxt(n) = l; end set(thrtxt(n),'Visible', 'on'); end for k=1:nChan if (any(chanIdx==k)) isEnabled = 'on'; else isEnabled = 'off'; end l = findobj('Tag', sprintf('txt_chan_%d', k)); if isempty(l) txt(k) = uicontrol(parent,'Style','text',... 'String',sprintf('Channel %d', k),... 'Units','Normalized', ... 'Tag', sprintf('txt_chan_%d',k) , ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py-sp*(k+2) .2 sp]); else txt(k) = l; end set(txt(k),'Enable', isEnabled); l= findobj('Tag', sprintf('txt_manual_bg_ch_%d',k)); if isempty(l) edt(k) = uicontrol(parent,'Style','edit',... 'String','',... 'Units','Normalized', ... 'Tag', sprintf('txt_manual_bg_ch_%d',k) , ... 'Position',[.26 py-sp*(k+2) .1 sp]); else edt(k) = l; end set(edt(k),'Enable', isEnabled); for n=1:(numcat-1) l = findobj('Tag', sprintf('txt_manual_cat_%d_ch_%d',n,k)); if isempty(l) thr((k-1)*(numcat-1)+n) = uicontrol(parent,'Style','edit',... 'String','',... 'Units','Normalized', ... 'Tag', sprintf('txt_manual_cat_%d_ch_%d',n,k) , ... 'Position',[.26+n*.1 py-sp*(k+2) .1 sp], ... 'Visible', 'on'); else thr((k-1)*(numcat-1)+n)= l; end set(thr((k-1)*(numcat-1)+n),'Enable', isEnabled); set(thr((k-1)*(numcat-1)+n),'Visible', 'on'); end % Delete any columns that are no longer useful for n=(numcat):10 obj = findobj('Tag', sprintf('txt_manual_cat_%d_ch_%d',n,k)); if ~isempty(obj) delete(obj); end obj = findobj('Tag', sprintf('txt_thr_%d', n)); if ~isempty(obj) delete(obj); end end % Add button for manual measurement uicontrol(parent,'Style','pushbutton','String','Fill values from spots',... 'Units','normalized', 'Tag', 'btn_calculate_values', ... 'Position',[.2 py-sp*(nChan+6) .4 sp*3], ... 'Callback', @btn_calculate_values_callback); end end function makeBruteClusterTab(parent) tabTag = 'tab_cluster_brute_force'; tabName = 'Brute Force'; thisTab = findobj('Tag',tabTag); sp = .05; py = .89; if isempty(thisTab) thisTab = uitab('Parent', parent, 'Title', tabName, ... 'Tag', tabTag); uicontrol(thisTab,'Style','checkbox',... 'String','Use Brute Force Clustering',... 'Tag', 'is_do_brute', ... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py+sp .4 sp]); % Number of categories uicontrol(thisTab,'Style','text',... 'String','Number of Categories',... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py-sp .3 sp]); uicontrol(thisTab,'Style','edit',... 'String','2',... 'Units','Normalized', ... 'Tag', 'txt_brute_cat_num', ... 'Position',[.36 py+.01-sp .1 sp]); end end function makeKMeansClusterTab(parent) tabTag = 'tab_cluster_kmeans'; tabName = 'K-Means'; thisTab = findobj('Tag',tabTag); sp = .05; py = .89; if isempty(thisTab) thisTab = uitab('Parent', parent, 'Title', tabName, ... 'Tag', tabTag); uicontrol(thisTab,'Style','checkbox',... 'String','Use K-Means clustering',... 'Tag', 'is_do_kmeans', ... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py+sp .4 sp]); uicontrol(thisTab,'Style','text',... 'String','Number of clusters',... 'Tag', 'txt_norm_kmeans', ... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py-sp .3 sp]); uicontrol(thisTab,'Style','edit',... 'String','15',... 'Units','Normalized', ... 'Tag', 'txt_kmeans_cluster_num', ... 'Position',[.36 py+.01-sp .1 sp]); uicontrol(thisTab,'Style','checkbox',... 'String','Separate K-Means per channel',... 'Tag', 'is_sep_kmeans', ... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py-3*sp .5 sp], ... 'Callback', @is_sep_kmeans_callback); uicontrol(thisTab,'Style','text',... 'String','Clusters per channel',... 'Tag', 'txt_sep_kmeans', ... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py-4*sp-.01 .3 sp]); uicontrol(thisTab,'Style','edit',... 'String','2',... 'Units','Normalized', ... 'Tag', 'txt_kmeans_sep_cluster_num', ... 'Position',[.36 py-4*sp .1 sp]); end end function is_sep_kmeans_callback(hObject, eventdata, handles) %Get object to enable or not sep(1) = findobj('Tag','txt_sep_kmeans'); sep(2) = findobj('Tag','txt_kmeans_sep_cluster_num'); knorm(1) = findobj('Tag','txt_norm_kmeans'); knorm(2) = findobj('Tag','txt_kmeans_cluster_num'); if get(hObject,'Value') %Disable normal KMeans Values knorm(1).Enable = 'off'; knorm(2).Enable = 'off'; %Enable independent KMeans Values sep(1).Enable = 'on'; sep(2).Enable = 'on'; else %Disable normal KMeans Values knorm(1).Enable = 'on'; knorm(2).Enable = 'on'; %Disable independent KMeans Values sep(1).Enable = 'off'; sep(2).Enable = 'off'; end end function makeSettingsClusterTab(parent) tabTag = 'tab_cluster_settings'; tabName = 'Settings'; thisTab = findobj('Tag',tabTag); sp = .05; py = .89; if isempty(thisTab) thisTab = uitab('Parent', parent, 'Title', tabName, ... 'Tag', tabTag); % Allow empty clusters? uicontrol(thisTab,'Style','checkbox',... 'String','No Empty Custers',... 'Tag', 'is_no_empty_clusters', ... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py+sp .4 sp]); % Grouping distance uicontrol(thisTab,'Style','text',... 'HorizontalAlignment', 'right', ... 'String',sprintf('%s\n%s','Groups spots','if closer than [um]'),... 'Units','Normalized', ... 'Position',[.05 py-sp .3 sp+0.02]); uicontrol(thisTab,'Style','edit',... 'String','8.5',... 'Units','Normalized', ... 'Tag', 'txt_grouping_distance', ... 'Position',[.36 py+.01-sp .1 sp]); % Z Compensation uicontrol(thisTab,'Style','text',... 'String','Z Compensation factor',... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py-2*sp .3 sp]); uicontrol(thisTab,'Style','edit',... 'String','3',... 'Units','Normalized', ... 'Tag', 'txt_z_compensation_factor', ... 'Position',[.36 py+.01-2*sp .1 sp]); end end function makeReassignTab(parent) tabTag = 'tab_reassign'; tabName = 'Reassign'; thisTab = findobj('Tag',tabTag); sp = .05; h= 0.05; py = .89; if isempty(thisTab) thisTab = uitab('Parent', parent, 'Title', tabName, ... 'Tag', tabTag); % Make one spot per cluster, spot number is cluster size? uicontrol(thisTab,'Style','checkbox',... 'String','Make 1 Spot / Subcluster',... 'Tag', 'is_reassign_single_spot', ... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py+sp .4 h]); % Grouping distance uicontrol(thisTab,'Style','text',... 'HorizontalAlignment', 'right', ... 'String','Maximum distance for reassignment [um]',... 'Units','Normalized', ... 'Position',[.05 py-sp .5 h]); uicontrol(thisTab,'Style','edit',... 'String','8.5',... 'Units','Normalized', ... 'Tag', 'txt_reassign_max_distance', ... 'Position',[.56 py-sp .1 h]); % Z Compensation uicontrol(thisTab,'Style','text',... 'String','Maximum intensity distance [AU]',... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py-2*sp .5 h]); uicontrol(thisTab,'Style','edit',... 'String','120',... 'Units','Normalized', ... 'Tag', 'txt_reassign_max_intensity', ... 'Position',[.56 py-2*sp .1 h]); % Z Compensation uicontrol(thisTab,'Style','text',... 'String','Reassign if smaller than',... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py-3*sp .5 h]); uicontrol(thisTab,'Style','edit',... 'String','10',... 'Units','Normalized', ... 'Tag', 'txt_reassign_cluster_min', ... 'Position',[.56 py-3*sp .1 h]); end end function makeWingJTab(parent) tabTag = 'tab_wing_j'; tabName = 'WingJ'; thisTab = findobj('Tag',tabTag); sp = .05; py = .89; h = .05; if isempty(thisTab) thisTab = uitab('Parent', parent, 'Title', tabName, ... 'Tag', tabTag); % Make one spot per cluster, spot number is cluster size? uicontrol(thisTab,'Style','checkbox',... 'String','Remove Offset',... 'Tag', 'is_wingj_remove_offset', ... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py .4 h]); uicontrol(thisTab,'Style','checkbox',... 'String','Flip Y Coordinate',... 'Tag', 'is_wingj_flip_y', ... 'Units','Normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[.05 py-sp .4 h]); end end %% Callbacks for all buttons function btn_refresh_callback(hObject, eventdata, handles) end function btn_sum_callback(hObject, eventdata, handles) sumChannels(); end function btn_clear_outside_callback(hObject, eventdata, handles) clearOutside(); end function btn_detect_spots_callback(hObject, eventdata, handles) detectSpots(); end function btn_cluster_spots_callback(hObject, eventdata, handles) clusterSpots(); end function btn_reassign_spots_callback(hObject, eventdata, handles) reassignSpots(); end function btn_export_callback(hObject, eventdata, handles) exportToCSV(); end function savebtn_callback(hObject, eventdata, handles) saveSettings(); end function loadbtn_callback(hObject, eventdata, handles) +% Make sure this function is generic enough loadSettings(); - end function btn_calculate_values_callback(hObject, eventdata, handles) manualAverageInterface(); end function btn_wingj_callback(hObject, eventdata, handles) loadWingJData(); end