diff --git a/BIOP_Clustering.m b/BIOP_Clustering.m index 8e535c4..178d1b7 100644 --- a/BIOP_Clustering.m +++ b/BIOP_Clustering.m @@ -1,758 +1,784 @@ function BIOP_Clustering %Start EasyXT addpath('EasyXT'); addpath('functions'); global X; X = EasyXT(); 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]); + + % BG Value + uicontrol(thisTab,'Style','text',... + 'String','Background',... + 'Units','Normalized', ... + 'HorizontalAlignment', 'right', ... + 'Position',[.05 py-2*sp .3 sp]); + + uicontrol(thisTab,'Style','edit',... + 'String','5',... + 'Units','Normalized', ... + 'Tag', 'txt_brute_bg', ... + 'Position',[.36 py+.01-2*sp .1 sp]); + + % Max Value + uicontrol(thisTab,'Style','text',... + 'String','Max Threshold',... + 'Units','Normalized', ... + 'HorizontalAlignment', 'right', ... + 'Position',[.05 py-3*sp .3 sp]); + + uicontrol(thisTab,'Style','edit',... + 'String','160',... + 'Units','Normalized', ... + 'Tag', 'txt_brute_max', ... + 'Position',[.36 py+.01-3*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 diff --git a/functions/clusterDistances.m b/functions/clusterDistances.m index 5616767..50b35da 100644 --- a/functions/clusterDistances.m +++ b/functions/clusterDistances.m @@ -1,45 +1,44 @@ function clusterDistances( spotData, clusterIndexes, zComp, minDist, parent ) global X; - color = createLUT(max(clusterIndexes), 255); for clus = 1:max(clusterIndexes) % Get indices of spots belonging to cluster clus clusInd = find(clusterIndexes == clus); nSpots(clus) = numel(clusInd); spotPositions = spotData.posXYZ(clusInd,:); % Cluster could be empty if ~isempty(spotPositions) clusterSpotsFolder = X.CreateGroup(sprintf('Cluster %d', clus)); X.AddToScene(clusterSpotsFolder, 'Parent', parent); % compensate Z spotPositions(:,3) = spotPositions(:,3) / zComp; % Easy to get subclusters by distance if size(spotPositions, 1) > 1 T = clusterdata(spotPositions,'criterion', 'distance', 'distance', 'euclidean', 'cutoff', minDist); else T = 1; end % Get the IDs for each cluster and make a spot subclusIds = unique(T); for subClus = subclusIds' idx = find(T==subClus); tempSpot = X.CreateSpots(spotData.posXYZ(clusInd(idx),:), spotData.radii(clusInd(idx),1)', 'Name', sprintf('Subcluster %d', subClus)); X.SetColor(tempSpot, color(clus,:)); X.AddToScene(tempSpot, 'Parent',clusterSpotsFolder); end ns=length(subclusIds); disp(sprintf(' Cluster %d: %d Subclusters: %d Spots', clus, ns, nSpots(clus))); end end end diff --git a/functions/clusterSpots.m b/functions/clusterSpots.m index 2e2e89c..9156750 100644 --- a/functions/clusterSpots.m +++ b/functions/clusterSpots.m @@ -1,160 +1,163 @@ function clusterSpots() global X; % Get the kind of clustering we will be doing is_do_manual = getFromTag('is_do_manual'); is_do_brute = getFromTag('is_do_brute'); is_do_kmeans = getFromTag('is_do_kmeans'); % Grab the Spot Object in the Scene nS = X.GetNumberOf('Spots'); if nS > 1 [~, nS] = X.SelectDialog('Spots'); end spots = X.GetObject('Type', 'Spots', 'Number', nS); % Grab the channels we will be using chanIdx = getChannelIndexes(); % Grab the stats we need, namely Intensity Mean spotsData = X.GetSelectedStatistics(spots, 'Intensity Mean'); % To cluster, we need an nx2 array with % col1: spotID % col2: Value of selected statistic % Get the indices of the chosen statistic % Build what we need selectedIds = spotsData.ids+1; selectedChannels = cell2mat(spotsData.factors(:,2)); selectedValues = spotsData.values; % for all the Ids and all Channels, will fill all values from the chosen statistic for i = 1:length(selectedValues) fullSpotsDataForCluster(selectedIds(i),str2num(selectedChannels(i))) = selectedValues(i); end % Finished data for clustering spotsClusterData = fullSpotsDataForCluster(:,chanIdx); % Clear some memory fullSpotsDataForCluster = []; %Spot Grouping spotGrouping = getFromTag('txt_grouping_distance', 'Number'); % Z compensation zComp = getFromTag('txt_z_compensation_factor', 'Number'); % Grouping Distance for after clustering minDist = getFromTag('txt_grouping_distance', 'Number'); if is_do_manual % Just grab all the channels and all the values and then use the % equivalent of the brute-force to get the results % How many categories per channel nCat = getFromTag('txt_manual_cat_num', 'Number'); % Make an array of edges for each channel edges = zeros(numel(chanIdx), nCat+2); % +2 to include 0 and Infinity edges(:,end) = Inf; % Everything in double loop, first channels for c=1:numel(chanIdx) %get BG edges(c,2) = getFromTag(sprintf('txt_manual_bg_ch_%d',chanIdx(c)), 'Number'); % Now for each category for n=1:(nCat-1) edges(c,2+n) = getFromTag(sprintf('txt_manual_cat_%d_ch_%d',n,chanIdx(c)), 'Number'); end end [edges, clusterIndexes ] = sortManual(spotsClusterData, edges); % create a Parent folder with the Cluster Number manualFolder = X.CreateGroup(sprintf('Manual Clustering %d categories per channel, Z Compensation [%d]', nCat, zComp )); X.AddToScene(manualFolder); clusterDistances(spotsData, clusterIndexes, zComp, minDist, manualFolder); disp('Manual Clustering DONE'); edges end if is_do_brute % Here we use a very simple method to cluster them : % Check on each channel for the intensities and categorise them. a % binning into N categories for each channel. nCat = getFromTag('txt_brute_cat_num', 'Number'); - [centroids, clusterIndexes ] = sortBrute(spotsClusterData, nCat, 160, 10); + max = getFromTag('txt_brute_max', 'Number'); + bg = getFromTag('txt_brute_bg', 'Number'); + +[centroids, clusterIndexes ] = sortBrute(spotsClusterData, nCat, max, bg); % create a Parent folder with the Cluster Number - bruteFolder = XT.CreateGroup(sprintf('Brute Force Clustering %d categories per channel, Z Compensation [%d]', nCat, zComp )); - XT.AddToScene(bruteFolder); + bruteFolder = X.CreateGroup(sprintf('Brute Force Clustering %d categories per channel, Z Compensation [%d]', nCat, zComp )); + X.AddToScene(bruteFolder); clusterDistances(spotsData, clusterIndexes, zComp, minDist, bruteFolder); disp('Brute Force Clustering DONE'); centroids end if is_do_kmeans % Use separate clusterings per channel? is_sep_kmeans = getFromTag('is_sep_kmeans'); if is_sep_kmeans nClusterPerChannel = getFromTag('txt_kmeans_sep_cluster_num', 'Number'); opts = statset('Display','final'); str = ''; for i=1:numel(chanIdx) [clusterIndexes(:,i), centroids(:,i)] = kmeans(spotsClusterData(:,i),nClusterPerChannel,... 'start','plus',... 'replicates',50,... 'emptyaction','drop',... 'Options',opts); str = [str '%d']; end [C ia ic] = unique(clusterIndexes, 'rows'); % for the indexes, make a new array from 1 to to numger of unique % rows newIdx = 1:size(C,1); % Get the centroids cent = []; for c=1:numel(chanIdx) cent = [cent centroids(C(:,c),c)]; end centroids = cent % create a Parent folder with the Cluster Number sepkMeansFolder = X.CreateGroup(sprintf('Separate K-Means With %d Clusters per Channel, Z Compensation [%d]', nClusterPerChannel, zComp )); X.AddToScene(sepkMeansFolder); clusterDistances(spotsData, newIdx(ic), zComp, minDist, sepkMeansFolder); else nClusters = getFromTag('txt_kmeans_cluster_num', 'Number'); opts = statset('Display','final'); [clusterIndexes, centroids] = kmeans(spotsClusterData,nClusters,... 'start','plus',... 'replicates',50,... 'emptyaction','drop',... 'Options',opts); % create a Parent folder with the Cluster Number kMeansFolder = X.CreateGroup(sprintf('K-Means With %d Clusters, Z Compensation [%d]', nClusters, zComp )); X.AddToScene(kMeansFolder); clusterDistances(spotsData, clusterIndexes, zComp, minDist, kMeansFolder); disp('K-Means Clustering DONE'); end centroids end end diff --git a/functions/manualAverageInterface.m b/functions/manualAverageInterface.m index b3ec6c6..120e1c5 100644 --- a/functions/manualAverageInterface.m +++ b/functions/manualAverageInterface.m @@ -1,114 +1,129 @@ function manualAverageInterface global X; global intensities; +global res; + +% Get all the spots first +sCh = getFromTag('txt_channel_spot', 'Number'); +spots = X.GetObject('Name', sprintf('Detected Spots from Channel %d', sCh)); +stats = X.GetSelectedStatistics(spots, 'Intensity Mean'); + +selectedChannels = cell2mat(stats.factors(:,2)) +intensities = []; +% for all the Ids and all Channels, will fill all values from the chosen statistic +for i = 1:length(stats.values) + intensities(stats.ids(i)+1, str2num(selectedChannels(i))) = stats.values(i); +end + f = figure('Name', 'BIOP - Spots Stats', ... 'NumberTitle', 'off', 'Visible', 'off', 'Position', [0 0 500 200], ... 'Tag', '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'; l = .05; w = .4; h = .1; s = 0.1; % Refresh button uicontrol(f,'Style','pushbutton','String','Calculate',... 'Units','normalized', 'Tag', 'btn_stats_refresh', ... 'Position',[0.10 .75 0.8 h*2],... 'Callback', @btn_stats_refresh_callback); % Info text uicontrol(f,'Style','text','String','Spots Selected: ',... 'Units','normalized', ... 'HorizontalAlignment', 'right', ... 'Position',[l .60 0.32 h]); uicontrol(f,'Style','text','String','',... 'Units','normalized', 'Tag', 'txt_spot_name', ... 'HorizontalAlignment', 'left', ... 'Position',[l+0.33 .60 0.5 h]); uicontrol(f,'Style','text','String','',... 'Units','normalized', 'Tag', 'txt_spot_stats', ... 'FontWeight', 'bold', ... 'HorizontalAlignment', 'left', ... 'Position',[0.26 .44 0.9 h]); % 'Add to' popup list options = {}; chan={}; nChan = getChannelIndexes(); manCat = getFromTag('txt_manual_cat_num', 'Number'); for i=nChan chan{end+1} = sprintf('Channel %d', i); options{end+1} = sprintf('Channel %d BG',i); for j=1:(manCat-1) options{end+1} = sprintf('Channel %d Thr %d',i,j); end end %Choose Channel uicontrol(f, 'Style', 'popup',... 'Units','normalized', 'Tag', 'popup_chan', ... 'String', chan,... 'Position',[l .45 0.2 h]); uicontrol(f, 'Style', 'popup',... 'Units','normalized', 'Tag', 'popup_add_to', ... 'String', options,... 'Position',[l .15 0.5 h]); % Add to button uicontrol(f,'Style','pushbutton','String','Add',... 'Units','normalized', 'Tag', 'btn_add', ... 'Position',[l+0.55 .15 0.2 .1],... 'Callback', @btn_add_callback); end function btn_stats_refresh_callback(hObject, eventdata, handles) global X; global intensities; +global res; + choices = get(findobj('Tag', 'popup_chan'),'String'); -choice = choices{getFromTag('popup_chan')} +choice = choices{getFromTag('popup_chan')}; expression = 'Channel (?\d+)'; tokenNames = regexp(choice,expression,'names'); - +ch = str2num(tokenNames.channel(1)); spots = X.GetObject(); - -idx = spots.GetSelectedIndices(); -stats = X.GetSelectedStatistics(spots, 'Intensity Mean', 'Channel', str2num(tokenNames.channel(1))) -intensities = stats.values(idx+1); +idx = spots.GetSelectedIndices()+1; +size(intensities); +res = intensities(idx,ch); setFromTag('txt_spot_name', X.GetName(spots)); -setFromTag('txt_spot_stats', sprintf('%d Spots, Average Intensity %.1f', numel(intensities), mean(intensities))); +setFromTag('txt_spot_stats', sprintf('%d Spots, Average Intensity %.2f', numel(res), mean(res))); end function btn_add_callback(hObject, eventdata, handles) % Get popup options global intensities; - +global res; choices = get(findobj('Tag', 'popup_add_to'),'String'); choice = choices{getFromTag('popup_add_to')}; expression = ['Channel (?\d+) [BGThr ]+(?[\d]*).*']; tokenNames = regexp(choice,expression,'names'); if isempty(tokenNames.cat) %BG - setFromTag(sprintf('txt_manual_bg_ch_%s',tokenNames.channel(1)), sprintf('%.1f',mean(intensities))); + setFromTag(sprintf('txt_manual_bg_ch_%s',tokenNames.channel(1)), sprintf('%.2f',mean(res))); else - setFromTag(sprintf('txt_manual_cat_%s_ch_%s',tokenNames.cat(1), tokenNames.channel(1)), sprintf('%.1f',mean(intensities))); + setFromTag(sprintf('txt_manual_cat_%s_ch_%s',tokenNames.cat(1), tokenNames.channel(1)), sprintf('%.2f',mean(res))); end end \ No newline at end of file diff --git a/functions/sortBrute.m b/functions/sortBrute.m index bfb7d13..bbacbac 100644 --- a/functions/sortBrute.m +++ b/functions/sortBrute.m @@ -1,24 +1,27 @@ function [ centroids, finalIdx ] = sortBrute(data, nCat, theMax, bg) % Divide the Max by the number of categories step = (theMax-bg) / (nCat); edges = bg:step:(step*nCat); edges = [0 edges Inf]; finalIdx = zeros(size(data,1),1); for i=1:size(data,2) [~, idx] = histc(data(:,i), edges); idx(idx==0) = 1; finalIdx(:,i) = idx; end +[C ia ic] = unique(finalIdx, 'rows'); +uClusters = C; +% for the indexes, make a new array from 1 to to numger of unique +% rows +newIdx = 1:size(C,1); +centroids = []; -[uClusters] = unique(finalIdx, 'rows'); +finalIdx = newIdx(ic)'; -% Index each row of data. - -%Return the centroids centroids = (uClusters-1)*step - step/2 + bg; centroids(uClusters==1) = bg/2; \ No newline at end of file