diff --git a/Internal/ag.m b/Internal/ag.m index 3432d2e..a4ea095 100755 --- a/Internal/ag.m +++ b/Internal/ag.m @@ -1,4 +1,4 @@ -function [im,im_min,imax] = ag (im,imin,imax) +function [im,imin,imax] = ag (im,imin,imax) % ag : autogain, it increases the contrast of image im, using imin and imax. % It subtracts the the minimum from of the image, divides by the max and % then normalizes to 255. @@ -31,25 +31,33 @@ im = double(im); + + im(isinf(im(:))) = nan; -if exist( 'imin', 'var') && ~isempty( imin ) - im_min = imin; +if ~exist( 'imin', 'var') || isempty( imin ) + imin = min( im(:) ); else - im_min = min(im(:)); + imin = double( imin ); end -if ~exist( 'imax', 'var') || isempty(imax) - imax = max(im(:)); + +if ~exist( 'imax', 'var') || isempty( imax ) + imax = max( im(:) ); +else + imax = double( imax ); end + +if imin == imax + if imin > 0 + im = im/imax; + end +else + im = (im-imin)/(imax-imin); +end + +% autogain and normalization to uint8 +im = uint8(255*im); -im_max = imax-im_min; - -% subtract min -im = im - double(im_min); - - - % autogain and normalization to uint8 -im = uint8(255*im/double(im_max)); end \ No newline at end of file diff --git a/Internal/intFixFields.m b/Internal/intFixFields.m new file mode 100644 index 0000000..eb41c53 --- /dev/null +++ b/Internal/intFixFields.m @@ -0,0 +1,22 @@ +function CONST = intFixFields( CONST, CONST0 ) +% This function adds fields that exist in CONST0 but do not exist in CONST +% to CONST +if isstruct( CONST0 ) + C0n = fieldnames( CONST0 ); + + for ii = 1:numel( C0n ) + + if isfield( CONST, C0n{ii} ) + CONST = setfield( CONST, C0n{ii}, ... + intFixFields( getfield( CONST, C0n{ii} ),... + getfield( CONST0, C0n{ii}) ) ); + else + CONST = setfield( CONST, C0n{ii}, getfield( CONST0, C0n{ii})); + end + + end +%else +% CONST = CONST0; +end + +end \ No newline at end of file diff --git a/Internal/intFixFileName.m b/Internal/intFixFileName.m new file mode 100644 index 0000000..c03adcc --- /dev/null +++ b/Internal/intFixFileName.m @@ -0,0 +1,22 @@ +function name_mod = intFixFileName( name, str_end) +% Fixes a file name by adding the suffix str_end if it doesn't already +% exist +if str_end(1) ~= '.' + str_end = ['.',str_end]; +end + +ns = numel( str_end ); +nn = numel( name ); + +% check file name length +if ns > nn + name_mod = [ name, str_end]; +elseif ~strcmp( name( [end-ns+1:end] ), str_end ) + name_mod = [ name, str_end]; +else + name_mod = [ name ]; +end + +end + + diff --git a/Internal/intGetChannelNum.m b/Internal/intGetChannelNum.m new file mode 100644 index 0000000..0992de6 --- /dev/null +++ b/Internal/intGetChannelNum.m @@ -0,0 +1,17 @@ +function nnc = intGetChannelNum( data ) +%% comp number of fluor channels + +nc = numel(find(~cellfun('isempty',strfind(fieldnames(data),'fluor')))); +nnc = 0; + +for jj = 1:nc + + fluorName = ['fluor',num2str(jj)]; + + if isfield( data, fluorName ) + nnc = nnc + 1; + end + +end + +end \ No newline at end of file diff --git a/Internal/intImRead.m b/Internal/intImRead.m new file mode 100644 index 0000000..6433d27 --- /dev/null +++ b/Internal/intImRead.m @@ -0,0 +1,24 @@ +function im = intImRead(out_name) +% More flexible method for loading images... if the file is a mat file, it +% will load the image in that... else it uses imread +im = []; + +if numel(out_name) > 4 + if strcmp(out_name([end-3:end]), '.mat' ) + tmp = load( out_name ); + if isfield( tmp, 'im' ); + im = tmp.im; + end + elseif strcmp(out_name([end-3:end]), '.tif' ) + im = imread( out_name ); + end +end + + +if numel(size(im)) > 2 + disp('Images are in color - attempting to convert to monochromatic.'); + im = convertToMonochromatic(im); +end +end + + diff --git a/Internal/intImWrite.m b/Internal/intImWrite.m new file mode 100644 index 0000000..f3b27b4 --- /dev/null +++ b/Internal/intImWrite.m @@ -0,0 +1,15 @@ +function intImWrite(im,out_name) +% More flexible metho of writing images. Can use save if the image name is +% .mat. +if numel( out_name ) > 4 +if strcmp( out_name(end-3:end), '.mat' ) + out_name = intFixFileName( out_name, '.mat' ); + save( out_name, 'im' ); +else + out_name = intFixFileName( out_name, '.tif' ); + imwrite(uint16(im), out_name ,'tif','Compression', 'none'); +end + +end + + diff --git a/Internal/intMakeMinMax.m b/Internal/intMakeMinMax.m new file mode 100644 index 0000000..f4d4498 --- /dev/null +++ b/Internal/intMakeMinMax.m @@ -0,0 +1,6 @@ + function minmax = intMakeMinMax( im ) + minner = medfilt2( im, [2,2], 'symmetric' ); + maxxer = max( minner(:)); + minner = min( minner(:)); + minmax = [minner,maxxer]; + end \ No newline at end of file diff --git a/Internal/intRange.m b/Internal/intRange.m new file mode 100644 index 0000000..af49ea1 --- /dev/null +++ b/Internal/intRange.m @@ -0,0 +1,6 @@ +function ranger = intRange( im, CDFr ) +% put max and min in range + +ranger = [min( im ),max( im )]; + +end \ No newline at end of file diff --git a/Internal/intShiftIm.m b/Internal/intShiftIm.m index 491bbba..c1f99cf 100644 --- a/Internal/intShiftIm.m +++ b/Internal/intShiftIm.m @@ -44,4 +44,6 @@ imOut = (real(ifft2(fftB).*exp(-1i*phase))); +%imOut2 = imtranslate( imIn, -out([4,3]),'FillValues', mean(imIn(:))); + end \ No newline at end of file diff --git a/Internal/intShiftImMod.m b/Internal/intShiftImMod.m new file mode 100644 index 0000000..272a136 --- /dev/null +++ b/Internal/intShiftImMod.m @@ -0,0 +1,52 @@ +function imOut = intShiftIm( imIn, out ) +%% intShiftIm: shifts image 'imIn' by the parameters in 'out' +% out is produced by intAlignIm( imA, imB, precision ). +% +% INPUT : +% imIn : input image +% out : output of intAlignIm, +% where the 3rd element is the row_shift and 4th and col_shift +% +% OUTPUT : +% imOut : shifted image +% +% Copyright (C) 2016 Wiggins Lab +% Written by Paul Wiggins. +% University of Washington, 2016 +% This file is part of SuperSegger. +% +% SuperSegger is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% SuperSegger is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with SuperSegger. If not, see . + +% +% fftB = fft2(imIn); % fourier transform +% +% deltar = out(3); % net_row_shift in subpixel +% deltac = out(4); % net_col_shift in subpixel +% +% phase = 0; +% [nr,nc] = size(imIn); % nr : num of rows, nc : num of columns +% Nr = ifftshift(-fix(nr/2):ceil(nr/2)-1); % swaps the left and right halves +% Nc = ifftshift(-fix(nc/2):ceil(nc/2)-1); +% [Nc,Nr] = meshgrid(Nc,Nr); +% +% fftB = fftB.*exp(1i*2*pi*(deltar*Nr/nr+deltac*Nc/nc)); +% +% imOut = (real(ifft2(fftB).*exp(-1i*phase))); +% +% This re-implementation uses the matlab built in imtranslate. + + +imOut = imtranslate( imIn, -out([4,3]),'FillValues', mean(imIn(:))); + +end \ No newline at end of file diff --git a/Internal/isRightNameFormat.m b/Internal/isRightNameFormat.m index 57306cd..4b866fa 100644 --- a/Internal/isRightNameFormat.m +++ b/Internal/isRightNameFormat.m @@ -26,12 +26,12 @@ % along with SuperSegger. If not, see . -contents = dir([dirname,filesep,'*.tif']); +contents = dir([dirname,filesep,'*.tif*']); filenames = {contents.name}'; -nameWithXy=regexpi(filenames,'t\d+xy\d+c\d+.tif','once'); -nameWithoutXy=regexpi(filenames,'t\d+c\d+.tif','once'); -nameWithoutt=regexpi(filenames,'xy\d+c\d+.tif','once'); +nameWithXy=regexpi(filenames,'t\d+xy\d+c\d+.tif+','once'); +nameWithoutXy=regexpi(filenames,'t\d+c\d+.tif+','once'); +nameWithoutt=regexpi(filenames,'xy\d+c\d+.tif+','once'); numWithXy = sum(~cellfun('isempty',nameWithXy)); numWithoutXY = sum(~cellfun('isempty',nameWithoutXy)); diff --git a/batch/BatchSuperSeggerOpti.m b/batch/BatchSuperSeggerOpti.m index 2e4a225..027cb7c 100644 --- a/batch/BatchSuperSeggerOpti.m +++ b/batch/BatchSuperSeggerOpti.m @@ -119,7 +119,7 @@ function BatchSuperSeggerOpti(dirname_,skip,clean_flag,res,startEnd,showWarnings % align frames if exist( dirname_, 'dir' ) if exist( [dirname_,filesep,'raw_im'] ,'dir') && ... - (numel(dir ([dirname_,filesep,'raw_im',filesep,'*.tif'])) || ... + (numel(dir ([dirname_,filesep,'raw_im',filesep,'*.tif*'])) || ... exist([dirname_,filesep,'raw_im',filesep,'cropbox.mat'],'file')) disp('BatchSuperSeggerOpti : images already aligned'); if exist([dirname_,filesep,'raw_im',filesep,'cropbox.mat'],'file') @@ -128,7 +128,7 @@ function BatchSuperSeggerOpti(dirname_,skip,clean_flag,res,startEnd,showWarnings else crop_box_array = cell(1,10000); end - elseif numel(dir ([dirname_,filesep,'*.tif'])) + elseif numel(dir ([dirname_,filesep,'*.tif*'])) % check naming convention if ~isRightNameFormat(dirname_) disp('Images in incorrect naming format. Using convertImageNames to convert names.') @@ -139,8 +139,8 @@ function BatchSuperSeggerOpti(dirname_,skip,clean_flag,res,startEnd,showWarnings if CONST.align.ALIGN_FLAG crop_box_array = trackOptiAlignPad( dirname_,... CONST.parallel.parallel_pool_num, CONST); - movefile( [dirname_,filesep,'*.tif'], [dirname_,filesep,'raw_im'] ) % moves images to raw_im - movefile( [dirname_,'align',filesep,'*.tif'], [dirname_,filesep]); % moves aligned back to main folder + movefile( [dirname_,filesep,'*.tif*'], [dirname_,filesep,'raw_im'] ) % moves images to raw_im + movefile( [dirname_,'align',filesep,'*.tif*'], [dirname_,filesep]); % moves aligned back to main folder rmdir( [dirname_,'align'] ); % removes _align directory else copyfile( [dirname_,filesep,'*.tif'], [dirname_,filesep,'raw_im'] ) % moves images to raw_im @@ -251,7 +251,7 @@ function intProcessXY( dirname_xy, skip, nc, num_c, clean_flag, ... % processor all the information it needs to process the images. % Initialization -file_filter = '*.tif'; +file_filter = '*.tif*'; verbose = CONST.parallel.verbose; % get header to show xy position diff --git a/batch/convertImageNames.m b/batch/convertImageNames.m index 2fc2d29..e0d8a47 100644 --- a/batch/convertImageNames.m +++ b/batch/convertImageNames.m @@ -43,11 +43,11 @@ function convertImageNames(dirname, basename, timeFilterBefore, ... % along with SuperSegger. If not, see . -images = dir([dirname,filesep,'*.tif']); +images = dir([dirname,filesep,'*.tif*']); % directory to move original images dirOriginal = [dirname,filesep,'original',filesep] ; -imagesInOrig = dir([dirOriginal,filesep,'*.tif']); +imagesInOrig = dir([dirOriginal,filesep,'*.tif*']); elementsTime='t'; elementsXY ='xy'; @@ -87,10 +87,13 @@ function convertImageNames(dirname, basename, timeFilterBefore, ... end if isempty(imagesInOrig) % move original images - movefile([dirname,filesep,'*.tif'],dirOriginal); % move all images to dir original + + + movefile([dirname,filesep,'*.tif*'],dirOriginal); % move all images to dir original + end -images = dir([dirOriginal,filesep,'*.tif']); +images = dir([dirOriginal,filesep,'*.tif*']); % go through every image for j = 1: numel (images) @@ -186,4 +189,4 @@ function convertImageNames(dirname, basename, timeFilterBefore, ... numbers = str2double(pattern); end -end \ No newline at end of file +end diff --git a/batch/processExp.m b/batch/processExp.m index ad44132..d7c35fc 100644 --- a/batch/processExp.m +++ b/batch/processExp.m @@ -90,6 +90,7 @@ function processExp( dirname ) CONST.trackOpti.NEIGHBOR_FLAG = false; % calculate number of neighbors (default = false) CONST.imAlign.AlignChannel = 1; % change this if you want the images to be aligned to fluorescence channel +CONST.view.fluorColor = {'y','r','b'}; %% Skip Frames for Segmentation % For fast time-lapse or slow growth you can skip phase image frames diff --git a/batch/superSeggerGui.m b/batch/superSeggerGui.m index 5a41ed0..72a1701 100644 --- a/batch/superSeggerGui.m +++ b/batch/superSeggerGui.m @@ -315,6 +315,7 @@ function end_step_CreateFcn(hObject, eventdata, handles) % Hint: edit controls usually have a white background on Windows. % See ISPC and COMPUTER. + if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) set(hObject,'BackgroundColor','white'); end diff --git a/batch/trackOptiAlignPad.m b/batch/trackOptiAlignPad.m index aee39d6..7084278 100644 --- a/batch/trackOptiAlignPad.m +++ b/batch/trackOptiAlignPad.m @@ -51,7 +51,7 @@ dirname_ = fixDir(dirname_); verbose = CONST.parallel.verbose; -file_filter = '*.tif'; +file_filter = '*.tif*'; contents=dir([dirname_ file_filter]); num_im = numel( contents ); @@ -110,6 +110,7 @@ crop_box = cell(1, num_xy); % parallelized alignment for each xy +%for jj=1:num_xy parfor(jj=1:num_xy, workers) crop_box{jj} = intFrameAlignXY( SHOW_FLAG, nt, nz, nc, nxy(jj), ... dirname_, targetd, nameInfo, precision, CONST); @@ -179,12 +180,7 @@ if verbose disp(['trackOptiAlignPad : Image name: ',in_name]); end - im = imread(in_name); - - if numel(size(im)) > 2 - disp('Images are in color - attempting to convert to monochromatic.'); - im = convertToMonochromatic(im); - end + im = intImRead(in_name); if (ic == nc(1)) && (iz == nnz2 | iz == -1) % align phase image at half the z axis @@ -214,8 +210,9 @@ end end - im = intShiftIm(im, out); - + %im = intShiftIm(im, out); + im = intShiftImMod(im, out ); + if SHOW_FLAG if ic == nc(1) % phase image if ic>0 @@ -234,11 +231,11 @@ figure(ic) clf; - if mod(ic,2) == 0 - imshow( cat( 3, backer, backer0+fluor, backer0)); - else - imshow( cat( 3, backer+fluor, backer0, backer0)); + + if ~isfield (CONST.view,'fluorColor') + CONST.view.fluorColor = {'g','r','b'}; end + comp( {backer}, {fluor,CONST.view.fluorColor{ic-1}} ); end drawnow; end @@ -288,16 +285,18 @@ if verbose disp(['Image name: ',in_name]); end - im_ = imread( in_name ); + im_ = intImRead( in_name ); + if numel(size(im_)) > 2 disp('Images are in color - attempting to convert to monochromatic.'); im_ = convertToMonochromatic(im_); end + im = zeros(sspad, class(im_) ) + mean( im_(:)); im((1-miny):(ss(1)-miny),(1-minx):(ss(2)-minx)) = im_; out = [0,0,OutArray(countt,:)]; - im = intShiftIm(im, out + CONST.imAlign.out{ic} - ... + im = intShiftImMod(im, out + CONST.imAlign.out{ic} - ... CONST.imAlign.out{1}); if ~initFlag % first time through, set previous image @@ -318,11 +317,11 @@ figure(ic) clf; - if mod(ic,2) == 0 - imshow( cat( 3, backer, backer0+fluor, backer0)); - else - imshow( cat( 3, backer+fluor, backer0, backer0)); + + if ~isfield (CONST.view,'fluorColor') + CONST.view.fluorColor = {'g','r','b'}; end + comp( {backer}, {fluor,CONST.view.fluorColor{ic-1}} ); end drawnow; hold on; @@ -338,7 +337,7 @@ if FocusArray(countt) % image focused, with low error % save shifted image to target directory out_name = [targetd, MakeFileName(nameInfo)]; - imwrite(uint16(im), out_name ,'tif','Compression', 'none'); + intImWrite(im, out_name ); initFlag = true; if ic == nc(1) diff --git a/batch/trackOptiCropMulti.m b/batch/trackOptiCropMulti.m index d362c9c..c92ea78 100644 --- a/batch/trackOptiCropMulti.m +++ b/batch/trackOptiCropMulti.m @@ -28,7 +28,7 @@ if ~isempty(dirname) - file_filter = '*.tif'; + file_filter = '*.tif*'; dirname = fixDir(dirname); contents=dir([dirname,file_filter]); @@ -70,10 +70,14 @@ for nnxy = nxy % displays the first and last image on top of each other - nameInfo.npos(:,1) = [nt(1); nc(1); nnxy; nz(1)]; - im1 = imread( [dirname, MakeFileName(nameInfo) ]); + + + nameInfo.npos(:,1) = [nt(1); nc(1); nnxy; nz(1)]; + + im1 = intImRead( [dirname, MakeFileName(nameInfo) ]); + nameInfo.npos(:,1) = [nt(end); nc(1); nnxy; nz(1)]; - imEnd = imread( [dirname, MakeFileName(nameInfo) ]); + imEnd = intImRead( [dirname, MakeFileName(nameInfo) ]); figure(1); clf; @@ -115,10 +119,14 @@ nameInfo.npos(:,1) = [it; ic; nnxy; iz]; in_name = [dirname, MakeFileName(nameInfo)]; disp( in_name ); - im = imread( in_name ); + + + + im = intImRead( in_name ); out_name = [targetd, MakeFileName(nameInfo)]; - imwrite( im(yy,xx), out_name, 'TIFF' ); - end + intImWrite( im(yy,xx), out_name ); + end + end end end diff --git a/batch/trackOptiPD.m b/batch/trackOptiPD.m index d615396..6c02330 100644 --- a/batch/trackOptiPD.m +++ b/batch/trackOptiPD.m @@ -24,7 +24,7 @@ function trackOptiPD(dirname, CONST) % % You should have received a copy of the GNU General Public License % along with SuperSegger. If not, see . -file_filter = '*.tif'; +file_filter = '*.tif*'; if(nargin<1 || isempty(dirname)) dirname = uigetdir(); diff --git a/batch/trackOptiSkipMerge.m b/batch/trackOptiSkipMerge.m index de06af4..3938d81 100644 --- a/batch/trackOptiSkipMerge.m +++ b/batch/trackOptiSkipMerge.m @@ -136,8 +136,9 @@ function intSkipPar(i,dirname_xy,nameInfo,nt,nc,nz,skip,num_c,num_z) nameInfo_tmp.npos(4,1) = 1; name = MakeFileName(nameInfo_tmp); + % do the min merge of z phase -phase = imread( [dirname_xy,'phase',filesep,name] ); +phase = intImRead( [dirname_xy,'phase',filesep,name] ); for k = 2:num_z nameInfo_tmp.npos(4,1) = nz(k); name = MakeFileName(nameInfo_tmp); @@ -155,9 +156,15 @@ function intSkipPar(i,dirname_xy,nameInfo,nt,nc,nz,skip,num_c,num_z) dataname_ref = [dirname_xy,'seg', filesep,name_ref,'_err.mat']; data = load(dataname_ref); + + % loads the data reference for the min merge of z phase, sets tha name and % nameInfo, and the fluorescence field from the image to be merged. if mod(i-1,skip) + + imRange = nan( [2, num_c ] ); + imRange(:,1) = intRange( phase(:) ); + data.phase = phase; data.basename = name; nameInfo_tmp = nameInfo; @@ -169,9 +176,15 @@ function intSkipPar(i,dirname_xy,nameInfo,nt,nc,nz,skip,num_c,num_z) name = MakeFileName( nameInfo_tmp ); fluorImage = imread( [dirname_xy,'fluor',num2str(nc(k)-1),filesep,name]); data.(['fluor',num2str(nc(k)-1)]) = fluorImage; - end + + imRange(:,k) = intRange( fluorImage(:) ); + end + + data.imRange = imRange; + end + save(dataname2,'-STRUCT','data'); end diff --git a/cell/trackOptiClist.m b/cell/trackOptiClist.m index 362b561..878abb0 100644 --- a/cell/trackOptiClist.m +++ b/cell/trackOptiClist.m @@ -45,6 +45,12 @@ % Get the track file names... contents=dir([dirname '*_err.mat']); + + +imRangeGlobal = []; + + + if isempty( contents ) clist.data = []; clist.def={}; @@ -86,6 +92,20 @@ % loop through all the images (*err.mat files) for i = 1:num_im data_c = loaderInternal([dirname,contents(i).name]); + + % get info on max and min values of each channel over all timesteps + if isfield( data_c, 'imRange' ) + if isempty( imRangeGlobal ) + imRangeGlobal = data_c.imRange; + else + + for kk = 1:size( imRangeGlobal, 2 ) + imRangeGlobal(1,kk) = min( [data_c.imRange(1,kk),imRangeGlobal(1,kk)] ); + imRangeGlobal(2,kk) = max( [data_c.imRange(2,kk),imRangeGlobal(2,kk)] ); + end + end + end + if ~isempty( data_c.CellA) % record the number of cell neighbors if CONST.trackOpti.NEIGHBOR_FLAG && ... @@ -254,6 +274,24 @@ % removes cells with 0 cell id clist.data = clist_tmp(logical(clist_tmp(:,1)),:); clist.data3D = clist_3D(clist.data(:,1),:,:); + + + clist = gateTool( clist, 'add3Dt' ); + + % add channel max and min + clist.imRangeGlobal = imRangeGlobal; + + + %add3dtime stuff + len_time_ind = grabClistIndex(clist, 'Long axis (L)', 1); + + ss = size( clist.data3D ); + if numel(ss) == 2 + ss(3) = 1; + end + len = reshape( ~isnan(squeeze(clist.data3D(:,len_time_ind(1),:))),[ss(1),ss(3)]); + age = cumsum( len, 2 ); + age(~len) = nan; % Add time, age and relative age to 3D clist. clist = gateTool( clist, 'add3Dt' ); diff --git a/dev-lab/trackOptiZMerge.m b/dev-lab/trackOptiZMerge.m new file mode 100644 index 0000000..28e677a --- /dev/null +++ b/dev-lab/trackOptiZMerge.m @@ -0,0 +1,346 @@ +function trackOptiZMerge( dirname, targetname, CONST, dz ) + + +data.mag = 5; + +if ~isfield( CONST, 'maxMerge' ) || isempty(CONST.maxMerge) + CONST.maxMerge = false; +end + +if ~exist( 'dz', 'var' ) || isempty(dz) + dz = 0; +end + +data.CONST = CONST; +data.dz = dz; + + +%% get the dir contents first and set up the file names +dirname = fixDir( dirname ); +targetname = fixDir( targetname ); + +data.dirname = dirname; +data.targetname = targetname; + + +file_filter = '*.tif'; +contents=dir([data.dirname file_filter]); +num_im = numel( contents ); + +if num_im < 1 + disp( 'No images have been found.' ); + return +end + + +nt = []; +nc = []; +nxy = []; +nz = []; + +% extract name information for each image +for i = 1:num_im + nameInfo0 = ReadFileName(contents(i).name); + nt = [nt, nameInfo0.npos(1,1)]; + nc = [nc, nameInfo0.npos(2,1)]; + nxy = [nxy,nameInfo0.npos(3,1)]; + nz = [nz, nameInfo0.npos(4,1)]; +end + + +data.nameInfo0 = nameInfo0; + +nt = sort(unique(nt))'; +nc = sort(unique(nc)); +nxy = sort(unique(nxy)); +nz = sort(unique(nz)); + +data.nt = nt'; +data.nc = nc; +data.nxy = nxy; +data.nz = nz; + +numz = numel(nz); + +data.numz = numz; + +if numel(nz) < 2 + disp( 'There are not at least two z positions' ); + return +end + +%% make target d + +if ~exist( 'targetname', 'dir' ) + mkdir( data.targetname ); +end + +%% Load up first images and get the size + +im = imread( [dirname,contents(1).name] ); + +if numel(size(im)) > 2 + im = im(:,:,2); +end + +% figure out the full image size +ss0 = size( im ) +data.ss0 = ss0; + +% fix up full image size mesh grids +[X2f,Y2f] = meshgrid( (1:ss0(2)), (1:ss0(1)) ); +[X3f,Y3f,Z3f] = meshgrid( (1:ss0(2)), (1:ss0(1)), 1:numz ); + +data.X2f = X2f; +data.Y2f = Y2f; + +data.X3f = X3f; +data.Y3f = Y3f; +data.Z3f = Z3f; + +% mask smaller gides +imr = imresize( im, 1/data.mag ); + +ss = size( imr ); +data.ss = ss; + +[X3,Y3,Z3] = meshgrid( data.mag*(1:ss(2)), data.mag*(1:ss(1)), 1:numz ); +[X2,Y2] = meshgrid( data.mag*(1:ss(2)), data.mag*(1:ss(1)) ); +[X2i,Y2i] = meshgrid( data.mag*(0:ss(2)), data.mag*(0:ss(1)) ); + +data.X2 = X2; +data.Y2 = Y2; + +data.X2i = X2i; +data.Y2i = Y2i; + +data.X3 = X3; +data.Y3 = Y3; +data.Z3 = Z3; + + +% Make the filters +data.disk_fs = fspecial('disk',1); +data.g_fs = fspecial('gaussian',14,2); + +%% Do the main loop + +numt = numel(nt); +data.numt = numt; + +% Loop through xy's +for nnxy = nxy + + disp( ['XY: ',num2str( nnxy ),' / ',num2str(numel(nxy))] ); + %loop through times + + % parfor jj = 1:numt + + for jj = 1:numt + + intDoTimeStep( nt(jj), data, nnxy ) + + end +end +end + +function intDoTimeStep( it, data, nnxy ) + + +nameInfo_in = data.nameInfo0; +nameInfo_out = data.nameInfo0; + + +ims = zeros( [data.ss0, data.numz] ); + +disp( ['t: ',num2str( it ),' / ',num2str(data.numt)] ); + + +for ic = data.nc + %% Load the z stack + for iz = 1:data.numz + nameInfo_in.npos(:,1) = [it; ic; nnxy; iz]; + in_name = [data.dirname, MakeFileName(nameInfo_in)]; + + tmp = imread( in_name ); + + if numel(size(tmp)) > 2 + tmp = tmp(:,:,2); + end + ims(:,:,iz) = tmp; + end + + if (ic == 1)||(ic == -1 ) + Z2f = makeMergeMap( ims, data ); + end + + if data.CONST.maxMerge && (ic ~= 1) + im_merge = intMaxMerge( ims, datad ); + else + im_merge = intDoMerge( ims, Z2f, data ); + end + + nameInfo_out.npos(4,:) = 0; + nameInfo_out.npos(:,1) = [it; ic; nnxy; -1]; + out_name = [data.targetname, MakeFileName(nameInfo_out)]; + + imwrite( uint16(im_merge), out_name ); + +end + +end + + + +function Z2f = makeMergeMap( ims, data ) + +tmp_max = 0; + +curver = zeros( [data.ss,data.numz] ); + +% this removes bright glass chunks from the field +mask = false( data.ss0 ); + +for ii = 1:data.numz + rad = 1; + + tmp = medfilt2( ims(:,:,ii), [3,3], 'symmetric' ); + + tmp_mean = mean(tmp(:)); + + + tmp = ims(:,:,ii); + + flagger = tmp<.3*tmp_mean; + %mask = or( flagger,mask); + tmp(flagger) = 0.3*tmp_mean; + + flagger = tmp>2.5*tmp_mean; + mask = or( flagger,mask); + tmp( flagger) = 2.5*tmp_mean; + + tmp_max = tmp_max+tmp_mean; + + + [~,~,~,~,~,~,~,tmp ] = curveFilter( tmp, rad ); + + tmp = imresize( tmp, 1/data.mag ); + + tmp = imfilter( tmp, data.disk_fs, 'replicate' ); + curver(:,:,ii) = tmp; +end + +mask_r = logical(imresize( double(mask), 1/data.mag )); +mask_rbw = bwmorph( bwmorph( mask_r, 'erode',2),'dilate',4); + +int_min = imresize(min( ims, [], 3), 1/data.mag ); + +tmp_max = tmp_max/data.numz; + +curver = curver/tmp_max; + +%% Do max merge + +[tmp,ord] = max( curver,[],3 ); + +ord3 = data.Z3; +for ii = 1:data.numz + ord3(:,:,ii) = ord; +end + +curver_mod = curver; + +curver_mod(abs(ord3(:)-data.Z3(:))>2) = nan; + + +minner = min(curver_mod,[],3); +for ii = 1:data.numz + curver_mod(:,:,ii) = curver_mod(:,:,ii) - minner; +end + +Z_ = nansum(curver_mod.*data.Z3,3)./nansum(curver_mod,3); + + +%% Model background Z position based on length gradient + +mask_min = int_min<0.9*mean(int_min(:)); + +mask = and( (tmp>0.02), mask_min ); + +mask = bwmorph( mask, 'dilate', 1 ); +mask = bwmorph( mask, 'erode', 1 ); + +mask_e = bwmorph( mask, 'erode', 2 ); +mask_o = (mask-mask_e)>0; +mask_o(mask_rbw) = false; + +N = sum(mask_o(:)); + +Z0 = mean( Z_(mask_o)); + +X0 = mean( data.X2(mask_o) ); +Y0 = mean( data.Y2(mask_o) ); +XZ0 = mean( data.X2(mask_o).*Z_(mask_o) ); +YZ0 = mean( data.Y2(mask_o).*Z_(mask_o) ); +X20 = mean( data.X2(mask_o).*data.X2(mask_o) ); +Y20 = mean( data.Y2(mask_o).*data.Y2(mask_o) ); + +mX = (XZ0-X0*Z0)/(X20-X0^2); +mY = (YZ0-Y0*Z0)/(Y20-Y0^2); +b = Z0 - mX*X0-mY*Y0; + +ZZ = b + mX*data.X2 + mY*data.Y2; + + + + +Z__ = Z_; + +Z__(~mask) = ZZ(~mask); + +Z__ = medfilt2( Z__, [3,3] ); +Z2 = imfilter( Z__, data.g_fs, 'replicate' ); + +Z2 = Z2 + data.dz; + +Z2(Z2>data.numz) = data.numz; +Z2(Z2<1) = 1; + + +% Show the position for debugging +%figure(3); +%imshow( Z2, [] ); +%drawnow; + + +%% +Z2 = Z2([1,1:end],[1,1:end]); + +Z2f = interp2( data.X2i,data.Y2i,Z2,data.X2f,data.Y2f); + +end + + +function im_merge = intDoMerge( ims, Z2f, data ) + + + +figure(4); + +im_merge = interp3( data.X3f,data.Y3f,data.Z3f,ims,data.X2f,data.Y2f,Z2f ); + +imshow( im_merge, [] ); +drawnow; + +end + +function im_merge = intMaxMerge( ims ) + +im_merge = max( ims,[], 3); + +figure(4); + +imshow( im_merge, [] ); +drawnow; + +end diff --git a/fluorescence/curveFilter.m b/fluorescence/curveFilter.m index 270ae8b..53293fd 100755 --- a/fluorescence/curveFilter.m +++ b/fluorescence/curveFilter.m @@ -35,6 +35,9 @@ % You should have received a copy of the GNU General Public License % along with SuperSegger. If not, see . + +oldflag = true; + im = double(im); % filter width @@ -52,10 +55,16 @@ v = filterWidth^2; gau = 1/(2*pi*v) * exp( -R2/(2*v) ); -f_xx = (2*pi*v^2)*((X/v).^2-1/v).*gau; -f_yy = (2*pi*v^2)*((Y/v).^2-1/v).*gau; -f_xy = (2*pi*v^2)*X.*Y.*gau/v^2; +if oldflag + f_xx = (2*pi*v^2)*((X/v).^2-1/v).*gau; + f_yy = (2*pi*v^2)*((Y/v).^2-1/v).*gau; + f_xy = (2*pi*v^2)*X.*Y.*gau/v^2; +else + f_xx = ((X/v).^2-1/v).*gau; + f_yy = ((Y/v).^2-1/v).*gau; + f_xy = X.*Y.*gau/v^2; +end % Do filtering im_xx = imfilter( im, f_xx, 'replicate' ); im_yy = imfilter( im, f_yy, 'replicate' ); diff --git a/fluorescence/intFindFociCurve.m b/fluorescence/intFindFociCurve.m index 992037a..959ca8d 100644 --- a/fluorescence/intFindFociCurve.m +++ b/fluorescence/intFindFociCurve.m @@ -58,7 +58,8 @@ cytoplasmicFlourescenceSTD = 1; disp ('Possibly empty mask for image - foci may not be found'); end -normalizedImage = originalImage/cytoplasmicFlourescenceSTD; + +normalizedImage = originalImage/cytoplasmicFlourescenceSTD; % normalization so that intensities; %Take only pixels above 1 std (noise reduction) normalizedImage = normalizedImage - 1; @@ -219,9 +220,10 @@ focus = focusInit; if numel(sortedFoci) > 0 - flagFoci = (([sortedFoci.intensity] > 0.33 * ... - sortedFoci(1).intensity) | [sortedFoci.intensity] > 5); - maxIndex = find(flagFoci); + + %maxIndex = find([sortedFoci.intensity] > 0.333 * sortedFoci(1).intensity); + maxIndex = 1:numel(sortedFoci); + if numel(maxIndex) > CONST.trackLoci.numSpots(channelID) maxIndex = maxIndex(1:CONST.trackLoci.numSpots(channelID)); end diff --git a/gate/gateTool.m b/gate/gateTool.m old mode 100644 new mode 100755 index 2f89aaf..72411cb --- a/gate/gateTool.m +++ b/gate/gateTool.m @@ -397,6 +397,7 @@ if isnumeric( next_arg ) data.multi = next_arg; + end @@ -678,6 +679,7 @@ data.multi = next_arg; else % if there is no numeric ind's turn all to log + error( 'Resolution must be a double.' ); end diff --git a/gate/makePed.m b/gate/makePed.m new file mode 100644 index 0000000..9ef882e --- /dev/null +++ b/gate/makePed.m @@ -0,0 +1,41 @@ +function data = makePed( data ) + +ID0 = data.ID; +ID = sort( ID0 ); + +nc = numel( ID ); + +ped_vec = cell([1,nc]); + +for jj = 1:nc + + id = ID(jj); + + ii = find( id==ID0, 1, 'first' ); + + m = data.mother(ii); + ped = ''; + + if m == 0 || isnan(m) + ped = '0'; + else + ind = find( m==ID0 ); + + if ~isempty(ind); + ped = ped_vec{ind}; + + if data.pole(ii) == 2 + ped = [ped,'1']; + else + ped = [ped,'0']; + end + end + end + + ped_vec{ii} = ped; + gen(ii) = numel(ped); +end + +data.ped = ped_vec; + +end \ No newline at end of file diff --git a/segmentation/defineGoodSegs.m b/segmentation/defineGoodSegs.m index 88e387a..2380a17 100644 --- a/segmentation/defineGoodSegs.m +++ b/segmentation/defineGoodSegs.m @@ -159,7 +159,17 @@ if calcScores % Calculate the score to determine if the seg will be included. % if score is less than 0 set the segment off - [scoreRaw(ii)] = CONST.seg.segmentScoreFun( seg_info(ii,:), A ); + + if isfield( CONST.seg, 'forceOff' ) && CONST.seg.forceOff + % this allows all segments to be turned off + scoreRaw(ii) = -infty; + elseif isfield( CONST.seg, 'forceOn' ) && CONST.seg.forceOn + % this allows all sgments to be turned on + scoreRaw(ii) = infty; + else + [scoreRaw(ii)] = CONST.seg.segmentScoreFun( seg_info(ii,:), A ); + end + score(ii) = double( 0 < scoreRaw (ii)); % update the good and bad segs images. diff --git a/segmentation/doSeg.m b/segmentation/doSeg.m index 1a27761..abf86fd 100644 --- a/segmentation/doSeg.m +++ b/segmentation/doSeg.m @@ -69,7 +69,7 @@ nameInfo_tmp.npos(4,1) = 1; % z value name = MakeFileName(nameInfo_tmp); namePhase = [dirname_xy,'phase',filesep,name]; - phase = imread( namePhase ); + phase = intImRead( namePhase ); if num_z > 1 % if there are z frames phaseCat = zeros( [size(phase), num_z], 'uint16' ); @@ -78,11 +78,13 @@ for iz = 2:num_z nameInfo_tmp.npos(4,1) = iz; name = MakeFileName(nameInfo_tmp); - phaseCat(:,:,iz) = imread( [dirname_xy,'phase',filesep,name] ); + phaseCat(:,:,iz) = intImRead( [dirname_xy,'phase',filesep,name] ); end phase = mean( phaseCat, 3); end + imRange = nan( [2, num_c ] ); + if ~mod(i-1,skip) if CONST.superSeggerOpti.segmenting_fluorescence @@ -93,6 +95,8 @@ phase = max(phase(:)) - phase; end + imRange(:,1) = intRange( phase(:) ); + % do the segmentation here [data, ~] = CONST.seg.segFun( phase, CONST, header, dataname, crop_box); if ~isempty( crop_box ) @@ -106,9 +110,13 @@ nameInfo_tmp.npos(2,1) = nc(k); nameInfo_tmp.npos(4,1) = 1; name = MakeFileName( nameInfo_tmp ); - fluor_tmp = imread( [dirname_xy,'fluor',num2str(nc(k)-1),filesep,name] ); - data.(['fluor',num2str(nc(k)-1)])=fluor_tmp; + fluor_tmp = intImRead( [dirname_xy,'fluor',num2str(nc(k)-1),filesep,name] ); + data.(['fluor',num2str(nc(k)-1)])=fluor_tmp; + + imRange(:,k) = intRange( fluor_tmp(:) ); end + + data.imRange = imRange; save(dataname,'-STRUCT','data'); % Save data structure into the seg file. end diff --git a/segmentation/removeDebris.m b/segmentation/removeDebris.m index 3692843..4aeeba4 100644 --- a/segmentation/removeDebris.m +++ b/segmentation/removeDebris.m @@ -30,9 +30,11 @@ + INTENSITY_DIF = CONST.superSeggerOpti.INTENSITY_DIF; PEBBLE_CONST = CONST.superSeggerOpti.PEBBLE_CONST; debugFlag = false; + pad = 6; ss = size( phase ); @@ -93,9 +95,14 @@ figure(8); clf; - halo_keep = find( DI>INTENSITY_DIF ); - pebble_keep = find( I_K>PEBBLE_CONST ); - imshow( comp( phase, mask_bg, ismember( label_bg,halo_keep ), ismember( label_bg,pebble_keep) ) ); + + halo_keep = find( DI> INTENSITY_DIF); + pebble_keep = find( I_K> PEBBLE_CONST ); + comp( phase, ... + {mask_bg,.3}, ... + {ismember( label_bg,halo_keep ),.3},... + {ismember( label_bg,pebble_keep),.3} ); + for ii = 1:num_reg text( props(ii).Centroid(1),props(ii).Centroid(2), [num2str( -I_m(ii)+I_p(ii), '%2.2g' ),',',num2str( I_K(ii), '%2.2g' )] ); @@ -103,7 +110,7 @@ figure(9); clf - imshow( comp( phase, ~ismember( label_bg, keeper))); + comp( phase, {~ismember( label_bg, keeper),.3} ); end end diff --git a/segmentation/superSeggerOpti.m b/segmentation/superSeggerOpti.m index 14839c7..4f82fac 100755 --- a/segmentation/superSeggerOpti.m +++ b/segmentation/superSeggerOpti.m @@ -183,10 +183,12 @@ [~,~,~,~,~,K,~,~] = curveFilter(phaseNormUnfilt, 3 ); aK = abs(K); + if CONST.superSeggerOpti.remove_debris mask_colonies = removeDebris(mask_colonies, phaseNormUnfilt, aK, CONST); end + % remove bright halos from the mask mask_halos = (magicPhase>CUT_INT); @@ -270,6 +272,13 @@ break end end + + tmp_3s = compConn( logical(wsl_segs_good), 4 ); + tmp_3s([1,end],:) = 0; + tmp_3s(:,[1,end]) = 0; + + wsl_segs_good(tmp_3s==0)=0; + ws(yy,xx) = double(0<(ws(yy,xx) + wsl_segs_good)); end end diff --git a/settings/loadConstants.m b/settings/loadConstants.m index d0693a3..f1e39bc 100644 --- a/settings/loadConstants.m +++ b/settings/loadConstants.m @@ -34,6 +34,9 @@ % You should have received a copy of the GNU General Public License % along with SuperSegger. If not, see . + + + % gets the list of all possible constants in the settings folder [possibleConstants, list, filepath] = getConstantsList(); @@ -144,7 +147,7 @@ CONST.view.LogView = false; CONST.view.filtered = 1; CONST.view.maxNumCell = []; % maximum number of cells used for analysis tools - +CONST.view.background = [0.7, 0.7, 0.7]; % super resolution constants - not used in released version % Const for findFocusSR diff --git a/settings/loadConstantsFile.m b/settings/loadConstantsFile.m new file mode 100644 index 0000000..303ec42 --- /dev/null +++ b/settings/loadConstantsFile.m @@ -0,0 +1,28 @@ +function CONST = loadConstantsFile( filename ) +% Needed for back compatibility. +% fixes old loadConstants files... +% + +CONST0 = []; + +% view constants +CONST0.view.showFullCellCycleOnly = false; % only uses full cell cycle for analysis tools +CONST0.view.orientFlag = true; % to orient the cells along the horizontal axis for the analysis tools +CONST0.view.falseColorFlag = false; +CONST0.view.fluorColor = {'g','r','b','c','o','y'}; % order of channel colors to be used for display +CONST0.view.LogView = false; +CONST0.view.filtered = 1; +CONST0.view.maxNumCell = []; % maximum number of cells used for analysis tools +CONST0.view.background = [0.7, 0.7, 0.7]; + + +if exist( filename, 'file' ) + CONST = load( filename ); + CONST = intFixFields( CONST, CONST0 ); +else + disp( ['File ',filename, ' does not exist.'] ); + CONST = []; +end + + +end \ No newline at end of file diff --git a/trainingConstants/trainingGui.m b/trainingConstants/trainingGui.m index 135171b..897c3eb 100644 --- a/trainingConstants/trainingGui.m +++ b/trainingConstants/trainingGui.m @@ -138,6 +138,7 @@ function cut_and_seg_Callback(hObject, eventdata, handles) CONSTtemp.parallel.verbose = 1; CONSTtemp.align.ALIGN_FLAG = 0; CONSTtemp.seg.OPTI_FLAG = 1; + BatchSuperSeggerOpti(settings_train.imageDirectory, skip, clean_flag, CONSTtemp, start_end_steps, 1); % make a backup of the seg files @@ -146,6 +147,8 @@ function cut_and_seg_Callback(hObject, eventdata, handles) settings_train.frameNumber = 1; setWorkingDirectory(settings_train.loadDirectory(1:end-9)); + + updateUI(handles); % --- Executes on button press in try_const. diff --git a/viz/comp.m b/viz/comp.m index 4ea9515..a801e76 100644 --- a/viz/comp.m +++ b/viz/comp.m @@ -1,62 +1,179 @@ function [ varargout ] = comp( varargin ) -% comp : creates composite image +% comp : Makes composite image for the superSegger/trackOpti package. +% +% INPUT : +% +% comp( im_RGB, ... ): Compose im_RGB with other arguments +% +% comp( im_grey, ... ): Compose im_grey (greyscale) in the grey channel +% with other arguments +% +% comp( {im_grey,cc} ... ): Compose im_grey (greyscale) in the cc channel +% with other arguments. cc can be 'rygcbm....' or +% a double triplet +% +% comp( {im_grey,del,cc} ... ): Compose im_grey (greyscale) in the cc channel +% with other arguments. cc can be 'rygcbm....' or +% a double triplet. del is a double which modulates the +% intensity +% +% comp( {im_grey,cc} ... ): Compose im_grey (greyscale) in the cc channel +% with other arguments. cc also be false +% color +% +% +% comp( {im_grey,cc,'log'} ): Compose im_grey (greyscale) in the cc channel +% with other arguments. cc can be 'rygcbm....' or +% a double triplet. Log scale. +% +% comp( {im_grey,cc,'log',floor} ): Compose im_grey (greyscale) in the cc channel +% with other arguments. cc can be 'rygcbm....' or +% a double triplet. Log scale with floor floor. +% +% comp( {im_grey,'pow',.5} ): Compose im_grey (greyscale) in the grey channel +% Powlaw scale with power .5. +% +% comp( {mask,'r'},... ): Shows logical mask in red +% +% comp( im_grey, {mask,'r'},... ): Shows logical mask in red on top of +% im_grey in the grey channel +% +% comp( im_grey, {regs_label,'label',birth} ): +% Show regs_label regions with label +% birth +% +% comp( {fluor1,'mask', mask,'back',[.3,.3,.3] } ) +% Show fluor1 masked by mask with +% backgournd color [.3,.3,.3] +% +% comp( {fluor1,'mask', mask} ) +% Show fluor1 masked by mask +% +% comp( {fluor1,[min,max]} ) +% Show fluor1 autoscaled with min and max +% +% Copyright (C) 2016 Wiggins Lab +% Written by Paul Wiggins +% University of Washington, 2016 +% This file is part of SuperSegger. +% +% SuperSegger is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version +% +% SuperSegger is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with SuperSegger. If not, see . + label_flag = false; im_comp = []; + +% read the commands +% loop through all input arguments for ii = 1:nargin data = varargin{ii}; - + im = []; del = []; cc = []; com = []; - com2 = []; + + com2 = []; + + min_ = []; + max_ = []; + + % if the argument is a cell, then read the commands contained to format + % the image if iscell( data ) numin = numel( data ); + + if numin == 0 else - im = data{1}; - jj = 2; + % The first argument is always an image + im = data{1}; + + % set the cell argument counter to zer and get the next + jj = 2; + + com = {}; + com2 = {}; + ncom = 0; + + min_ = []; + max_ = []; + % loop through the arguments + while jj<=numin + % if the argument is a single char, it is a color if ischar(data{jj}) if numel( data{jj} ) == 1 cc = data{jj}; else - com = data{jj}; + % if the argument is multiple characters, then it + % is a command not a color + + ncom = ncom + 1; + com{ncom} = data{jj}; + % if there are no more entries, then put ID in com2 if jj+1 > numin - com2 = 'ID'; + com2{ncom} = 'ID'; else - com2 = data{jj+1}; + % if there are more entries, each the next + % entry as the argument. + com2{ncom} = data{jj+1}; end + % advance the counter to compensate for eating the + % argument. jj = jj + 1; end elseif all(isnumeric( data{jj} )) + % if the argument is numeric, it specifies the + % relative intensity if numel(data{jj}) == 1 del = data{jj}; + % if the argument is numeric, with two entries it is a + % min and a max + elseif numel(data{jj}) == 2 + + min_ = data{jj}(1); + max_ = data{jj}(2); + % else it is a color or colormap else cc = data{jj}; end end + % augment the counter jj = jj + 1; end end else + % if the argeument isn't a cell, then it must be an image. im = data; del = []; cc = []; end + % if the color isn't specified, make it white for argument 1 and + % alternate the color automatically for later arguments. if isempty( cc ) if ii == 1 cc = [1,1,1]; @@ -67,99 +184,193 @@ cc( ind ) = 1; end + % is the color is a char, make it a triplet elseif ischar( cc) cc = convert_color( cc ); end if isempty( del ) - if ~isempty( im ) && islogical( im ) - del = 0.2; - else - del = 1; - end + % make default intensity 1 + + %if ~isempty( im ) && islogical( im ) + % del = 0.2; + %else + del = 1; + %end end + % if the image isn't empty, go on if ~isempty( im ) + mask = []; + back = [0,0,0]; + modx = 0; + log_flag = false; + pow_flag = false; + + % process commands if ~isempty( com ) - if strcmp( com, 'label' ) - label_flag = true; - + for ii = 1:ncom - if ischar( com2 ) - com2_ = com2; - else - com2_ = ''; - end + com_ = com{ii}; + com2_ = com2{ii}; - ID_flag = false; - if strcmp( com2_, 'ID' ) - com2_ = ''; - ID_flag = true; + if strcmp( com_, 'label' ) + label_flag = true; + + + if ischar( com2 ) + com2__ = com2; + else + com2__ = ''; + end + + ID_flag = false; + if strcmp( com2__, 'ID' ) + com2__ = ''; + ID_flag = true; + end + + + if isempty( com2__ ) + str = {'Centroid'}; + else + str = {'Centroid',com2__}; + end + + props = regionprops( im, str ); + + + if ID_flag + vec = 1:numel(props); + + elseif ischar( com2_ ) + vec = drill( props, ['.',com2__] ); + else + vec = com2_; + end end - if isempty( com2_ ) - str = {'Centroid'}; - else - str = {'Centroid',com2_}; + if isnan( min_ ) + min_ = []; + end + if isnan( max_ ) + max_ = []; end - props = regionprops( im, str ); - + if strcmp( com_,'log' ) + log_flag = true; + + if isempty( com2_ ) || strcmp( com2_, 'ID' ) + modx = 0; + else + modx = com2_; + end + end - if ID_flag - vec = 1:numel(props); + if strcmp( com_,'pow' ) + pow_flag = true; - elseif ischar( com2 ) - vec = drill( props, ['.',com2_] ); - else - vec = com2; + modx = com2_; + end + + % if the image in masked, load a mask + if strcmp( com_,'mask' ) + mask = double(com2_); + end + + if strcmp( com_,'back' ) + back = double(com2_); end end end - - if strcmp( com,'log' ) - if isempty( com2 ) || strcmp( com2, 'ID' ) - com2 = 0; + + + % Make the image here: + + if log_flag + backer = double(ag( log(double(im+modx)) )); + elseif pow_flag + backer = double(ag( (double(im).^modx) )); + elseif ndims( im ) == 2 + backer = double(ag( im, min_, max_ )); + %[min_,max_] + end + + + + if ndims( im ) == 3 + + + % if the image is rgb already, keep it this way + if strcmp( class(im), 'double' ) + if isempty(im_comp) + im_comp = im*255; + else + im_comp = im_comp + im*255; + end + else + if isempty(im_comp) + im_comp = uint8(im); + else + im_comp = im_comp + uint8(im); + end end + % if the number of entries in the vector is great than 3, cc is + % a colormap + elseif numel(cc)>3 + im_tmp = uint8(255*(doColorMap( backer, cc ))); - backer = double(ag( log(double(im+com2)) )); + if isempty( im_comp ) + im_comp = im_tmp; + else + im_comp = im_comp + im_tmp; + end - elseif strcmp( com,'pow' ) - backer = double(ag( (double(im).^com2) )); - else - backer = double(ag( im )); - end - - if numel(cc)>3 - im_tmp = (255*(doColorMap( backer, cc ))); else - im_tmp = cat(3, backer*del*cc(1), backer*del*cc(2), backer*del*cc(3) ); + + if isempty( im_comp ) + im_comp = uint8(cat(3, backer*del*cc(1), backer*del*cc(2), backer*del*cc(3) )); + else + %disp('new'); + for ii = 1:3 + im_comp(:,:,ii) = im_comp(:,:,ii) + uint8(backer*del*cc(ii));%, backer*del*cc(2), backer*del*cc(3) ); + end + end + + end - - if isempty( im_comp ) - im_comp = im_tmp; - else - im_comp = im_comp + im_tmp; + end + + if exist( 'mask', 'var' ) && ~isempty( mask ) + for ii = 1:3; + im_comp(:,:,ii) = uint8(double(im_comp(:,:,ii)).*mask)+uint8(255*(1-mask)*back(ii)); end - - - end + +% if isempty( im_comp ) +% im_comp = im_tmp; +% else +% im_comp = im_comp + im_tmp; +% end + + + end + im_comp = uint8(im_comp); if nargout == 0 imshow( im_comp ); varargout = {}; - if label_flag + if label_flag hold on; x = drill( props, '.Centroid(1)' ); y = drill( props, '.Centroid(2)' ); @@ -182,36 +393,36 @@ function outColor = convert_color(inColor) - charValues = 'rgbcmywk'.'; %#' - rgbValues = [eye(3); 1-eye(3); 1 1 1; 0 0 0]; - assert(~isempty(inColor),'convert_color:badInputSize',... - 'Input argument must not be empty.'); - - if ischar(inColor) %# Input is a character string +charValues = 'rgbcmywk'.'; %#' +rgbValues = [eye(3); 1-eye(3); 1 1 1; 0 0 0]; +assert(~isempty(inColor),'convert_color:badInputSize',... + 'Input argument must not be empty.'); +if ischar(inColor) %# Input is a character string + [isColor,colorIndex] = ismember(inColor(:),charValues); assert(all(isColor),'convert_color:badInputContents',... - 'String input can only contain the characters ''rgbcmywk''.'); + 'String input can only contain the characters ''rgbcmywk''.'); outColor = rgbValues(colorIndex,:); - - elseif isnumeric(inColor) || islogical(inColor) %# Input is a numeric or - %# logical array + +elseif isnumeric(inColor) || islogical(inColor) %# Input is a numeric or + %# logical array assert(size(inColor,2) == 3,'convert_color:badInputSize',... - 'Numeric input must be an N-by-3 matrix'); + 'Numeric input must be an N-by-3 matrix'); inColor = double(inColor); %# Convert input to type double scaleIndex = max(inColor,[],2) > 1; %# Find rows with values > 1 inColor(scaleIndex,:) = inColor(scaleIndex,:)./255; %# Scale by 255 [isColor,colorIndex] = ismember(inColor,rgbValues,'rows'); assert(all(isColor),'convert_color:badInputContents',... - 'RGB input must define one of the colors ''rgbcmywk''.'); + 'RGB input must define one of the colors ''rgbcmywk''.'); outColor = charValues(colorIndex(:)); - - else %# Input is an invalid type - + +else %# Input is an invalid type + error('convert_color:badInputType',... - 'Input must be a character or numeric array.'); + 'Input must be a character or numeric array.'); + +end + - end - - end \ No newline at end of file diff --git a/viz/doDrawCellOutline.m b/viz/doDrawCellOutline.m new file mode 100644 index 0000000..1e332db --- /dev/null +++ b/viz/doDrawCellOutline.m @@ -0,0 +1,92 @@ +function doDrawCellOutline( data, ids1, ids2) +% Description : +% +% Opens fig with outlines of cells drawn. The script currently allows +% you to input two sets of cell IDs to be colored in blue (ids1) and red +% (ids2). Currently any cells with IDs not listed in ids1 or ids2 will be +% outlined in yellow. This is all customizable. If you wish to +% change the colors, replace 'b' etc with the color of your choice. If you +% do not want cells whose IDs are missing from the ID lists to be outlined, +% remove code in 'else' block. If you wish to send in additional id lists, +% add ids3, etc to the line above, and ammend the if/else block. +% +% List of inputs: +% +% data: A loaded err.mat file for the image you want outlines drawn on +% ids1: IDs of cells you want outlined in one color (default: blue) +% ids2: IDs of cells you want outlined in a second color (default: red) +% +% Copyright (C) 2016 Wiggins Lab +% Written by Silas Boye Nissen, Connor Brennan, Stella Stylianidou. +% University of Washington, 2016. Modified in 2018 by S Mangiameli and +% P. Wiggins. This file is part of SuperSegger. +% +% SuperSegger is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% SuperSegger is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with SuperSegger. If not, see . + + +clf; + +% To draw outlines on the fluorescence image, replace phase with fluor +im = cat(3, ag(data.phase), ag(data.phase), ag(data.phase)); +imshow( im, [] ); +hold on; + + +rl = data.regs.regs_label; +ids = data.regs.ID; + +nc = max( rl(:) ); + +props = regionprops( rl, 'PixelList' ); + +% Sets color depending on cell ID +for ii = 1:nc + +id = ids(ii); + +if ismember(id,ids1) + cc = 'b'; +elseif ismember(id, ids2) + cc = 'r'; +else + cc = 'y'; +end + + +x = props(ii).PixelList(:,1); +y = props(ii).PixelList(:,2); + +k = boundary( x,y ); +k = boundary( x,y ); + +hold on; + +skip = 3; + +kk = k([1:skip:end-1]); +kk = kk([end-3:end,1:end,1:4]); + +n = 1:numel(kk); +nn = 5:.1:(numel(kk)-3); + +% Interprets from pixel outline to smooth drawn outline +xx = interp1( n, x(kk), nn,'pchip' ); +yy = interp1( n, y(kk), nn,'pchip' ); + +% Plots outline on phase image +plot( xx, yy, 'LineStyle','-','Color',cc,'LineWidth', 2 ); + +end + +end \ No newline at end of file diff --git a/viz/doDrawCellOutlinePAW.m b/viz/doDrawCellOutlinePAW.m new file mode 100644 index 0000000..21aa869 --- /dev/null +++ b/viz/doDrawCellOutlinePAW.m @@ -0,0 +1,113 @@ +function doDrawCellOutlinePAW( data, ids1, ids2) +% Description : +% +% Opens fig with outlines of cells drawn. The script currently allows +% you to input two sets of cell IDs to be colored in blue (ids1) and red +% (ids2). Currently any cells with IDs not listed in ids1 or ids2 will be +% outlined in yellow. This is all customizable. If you wish to +% change the colors, replace 'b' etc with the color of your choice. If you +% do not want cells whose IDs are missing from the ID lists to be outlined, +% remove code in 'else' block. If you wish to send in additional id lists, +% add ids3, etc to the line above, and ammend the if/else block. +% +% List of inputs: +% +% data: A loaded err.mat file for the image you want outlines drawn on +% channel: The channel to draw outline on (1-phase, 2-fluor1) +% ids1: IDs of cells you want outlined in one color (default: blue) +% ids2: IDs of cells you want outlined in a second color (default: red) +% +% +% Copyright (C) 2016 Wiggins Lab +% Written by Silas Boye Nissen, Connor Brennan, Stella Stylianidou. +% University of Washington, 2016. Modified in 2018 by S Mangiameli and +% P. Wiggins. +% This file is part of SuperSegger. +% +% SuperSegger is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% SuperSegger is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with SuperSegger. If not, see . + +% Fill unset inputs +if ~exist('ids1','var') || isempty( ids1 ) + ids1 = []; +end + +if ~exist('ids2','var') || isempty( ids2 ) + ids2 = []; +end + + + + + + + +% Draw outlines + +rl = data.regs.regs_label; +ids = data.regs.ID; +nc = max( rl(:) ); + +props = regionprops( rl, 'PixelList' ); + +% Sets color depending on cell ID +for ii = 1:nc + + id = ids(ii); + + draw_flag = true; + if ismember(id,ids1) + cc = 'w'; + elseif ismember(id, ids2) + cc = 'y'; + else + cc = 'r'; + draw_flag = false; + end + + if draw_flag + % Mask for current region + tmp = rl; + tmp(tmp ~= ii) = 0; + + % Increase size of mask by 1 px and find boundary + se = strel('disk',1); + tmp2 = logical(imdilate(tmp,se)); + [y,x] = find(tmp2 == 1); + k = boundary(x,y,1); + + + hold on; + skip = 1; + kk = k([1:skip:end]); + kk = kk([end-3:end,1:end,1:4]); + + n = 1:numel(kk); + nn = 5:1:(numel(kk)-1); + + % Interprets from pixel outline to smooth drawn outline + % xx = interp1( n, x(kk), nn,'spline' ); + % yy = interp1( n, y(kk), nn,'spline' ); + + p = 0.1; %smaller value of p gives more smoothing + xx = fnval(csaps( n, x(kk),p), nn); + yy = fnval(csaps( n, y(kk),p), nn); + + + % Plots outline on phase image + plot( xx, yy, 'LineStyle','-','Color',cc,'LineWidth', .5 ); + end + +end + +end \ No newline at end of file diff --git a/viz/doDrawCellOutlineSMM.m b/viz/doDrawCellOutlineSMM.m new file mode 100755 index 0000000..04c2f63 --- /dev/null +++ b/viz/doDrawCellOutlineSMM.m @@ -0,0 +1,119 @@ +function doDrawCellOutlineSMM( data, channel, ids1, ids2) +% Description : +% +% Opens fig with outlines of cells drawn. The script currently allows +% you to input two sets of cell IDs to be colored in blue (ids1) and red +% (ids2). Currently any cells with IDs not listed in ids1 or ids2 will be +% outlined in yellow. This is all customizable. If you wish to +% change the colors, replace 'b' etc with the color of your choice. If you +% do not want cells whose IDs are missing from the ID lists to be outlined, +% remove code in 'else' block. If you wish to send in additional id lists, +% add ids3, etc to the line above, and ammend the if/else block. +% +% List of inputs: +% +% data: A loaded err.mat file for the image you want outlines drawn on +% channel: The channel to draw outline on (1-phase, 2-fluor1) +% ids1: IDs of cells you want outlined in one color (default: blue) +% ids2: IDs of cells you want outlined in a second color (default: red) +% +% +% Copyright (C) 2016 Wiggins Lab +% Written by Silas Boye Nissen, Connor Brennan, Stella Stylianidou. +% University of Washington, 2016. Modified in 2018 by S Mangiameli and +% P. Wiggins. +% This file is part of SuperSegger. +% +% SuperSegger is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% SuperSegger is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with SuperSegger. If not, see . + +% Fill unset inputs +if ~exist('ids1','var') || isempty( ids1 ) + ids1 = []; +end + +if ~exist('ids2','var') || isempty( ids2 ) + ids2 = []; +end + +if ~exist('channel','var') || isempty( channel ) + channel = 1; +end + +clf; + +% To draw outlines on the fluorescence image, replace phase with fluor +if channel == 1 + im = cat(3, ag(data.phase), ag(data.phase), ag(data.phase)); +elseif channel == 2 + im = cat(3, ag(data.fluor1)*0, ag(data.fluor1), ag(data.fluor1)*0); +elseif channel ==3 + im = cat(3, ag(data.fluor2), ag(data.fluor2)*0, ag(data.fluor2)*0); +end + +imshow( im, [] ); +hold on; + +rl = data.regs.regs_label; +ids = data.regs.ID; +nc = max( rl(:) ); + +props = regionprops( rl, 'PixelList' ); + +% Sets color depending on cell ID +for ii = 1:nc + + id = ids(ii); + + if ismember(id,ids1) + cc = 'b'; + elseif ismember(id, ids2) + cc = 'r'; + else + cc = 'y'; + end + + % Mask for current region + tmp = rl; + tmp(tmp ~= ii) = 0; + + % Increase size of mask by 1 px and find boundary + se = strel('disk',1); + tmp2 = logical(imdilate(tmp,se)); + [y,x] = find(tmp2 == 1); + k = boundary(x,y,1); + + + hold on; + skip = 1; + kk = k([1:skip:end]); + kk = kk([end-3:end,1:end,1:4]); + + n = 1:numel(kk); + nn = 5:1:(numel(kk)-1); + + % Interprets from pixel outline to smooth drawn outline + % xx = interp1( n, x(kk), nn,'spline' ); + % yy = interp1( n, y(kk), nn,'spline' ); + + p = 0.1; %smaller value of p gives more smoothing + xx = fnval(csaps( n, x(kk),p), nn); + yy = fnval(csaps( n, y(kk),p), nn); + + + % Plots outline on phase image + plot( xx, yy, 'LineStyle','-','Color',cc,'LineWidth', .5 ); + +end + +end \ No newline at end of file diff --git a/viz/fixFlags.m b/viz/fixFlags.m index b41f4be..bd5507c 100644 --- a/viz/fixFlags.m +++ b/viz/fixFlags.m @@ -29,6 +29,11 @@ FLAGS.edit_links = 0; end +if ~isfield(FLAGS, 'autoscale'); + disp('there is no flag field legend'); + FLAGS.autoscale = 0; +end + % displays legend for regions/ poles if ~isfield(FLAGS,'legend') FLAGS.legend = 1; @@ -59,6 +64,11 @@ FLAGS.P_flag = 1; end +% shows region outlines +if ~isfield(FLAGS,'log_view') + FLAGS.log_view = zeros( [1,10] );; +end + % shows region outlines if ~isfield(FLAGS,'Outline_flag') FLAGS.Outline_flag = 0; @@ -76,7 +86,7 @@ % shows composite image of all fluor channels found if ~isfield(FLAGS,'composite') - FLAGS.composite = 0; + FLAGS.composite = 1; end % shows poles @@ -84,12 +94,18 @@ FLAGS.p_flag = 0; end +% shows foci +if ~isfield(FLAGS,'s_flag') || numel( FLAGS.s_flag )==1 + FLAGS.s_flag = zeros( [1,10] ); +end + % shows foci scores -if ~isfield(FLAGS,'s_flag') - FLAGS.s_flag = 1; +if ~isfield(FLAGS,'scores_flag') || numel( FLAGS.scores_flag )==1 + FLAGS.scores_flag = zeros( [1,10] ); end + if ~isfield(FLAGS,'c_flag') FLAGS.c_flag = 1; end @@ -97,12 +113,16 @@ % shows filtered fluorescence if ~isfield(FLAGS,'filt') - FLAGS.filt = 1; + FLAGS.filt = zeros( [1,10] ); +elseif numel(FLAGS.filt) < 10; + FLAGS.filt = zeros( [1,10] ); end + + % shows phase image or mask if it is 0 -if ~isfield(FLAGS, 'phase_flag'); - FLAGS.phase_flag = 1; +if ~isfield(FLAGS, 'phase_flag') || numel( FLAGS.phase_flag ) == 1; + FLAGS.phase_flag = ones([1,10]); end % modifies the transparency of the phase/mask - use as double from 0 - 1 @@ -110,6 +130,39 @@ FLAGS.phase_level = 1; end + +% modifies the transparency of the phase/mask - use as double from 0 - 1 +if ~isfield(FLAGS, 'level'); + FLAGS.level = 0.8*ones([1,10]); +end + +% modifies the transparency of the phase/mask - use as double from 0 - 1 +if ~isfield(FLAGS, 'lut_min'); + FLAGS.lut_min = nan([1,10]); +end + +% modifies the transparency of the phase/mask - use as double from 0 - 1 +if ~isfield(FLAGS, 'lut_max'); + FLAGS.lut_max = nan([1,10]); +end + +% modifies the transparency of the phase/mask - use as double from 0 - 1 +if ~isfield(FLAGS, 'include'); + FLAGS.include = ones([1,10]); +end + + +% modifies the transparency of the phase/mask - use as double from 0 - 1 +if ~isfield(FLAGS, 'manual_lut'); + FLAGS.manual_lut = zeros([1,10]); +end + + +if ~isfield(FLAGS, 'gbl_auto'); + FLAGS.gbl_auto = zeros([1,10]); +end + + % not used if ~isfield(FLAGS,'lyse_flag') FLAGS.lyse_flag = 0; diff --git a/viz/getRGBColor.m b/viz/getRGBColor.m index 03053fc..544c368 100644 --- a/viz/getRGBColor.m +++ b/viz/getRGBColor.m @@ -6,48 +6,55 @@ % OUTPUT : % colorRBG : color rgb value % -% Copyright (C) 2016 Wiggins Lab +% Copyright (C) 2016 Wiggins Lab % Written by Stella Stylianidou. % University of Washington, 2016 % This file is part of SuperSegger. -% +% % SuperSegger is free software: you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation, either version 3 of the License, or % (at your option) any later version. -% +% % SuperSegger is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. -% +% % You should have received a copy of the GNU General Public License % along with SuperSegger. If not, see . -cyan_col = [0,255,255]/255; -orange_col = [255,165,0]/255; -red_col = [255,0,0]/255; -green_col = [0,255,0]/255; -blue_col = [0,0,255]/255; -yellow_col = [255,255,0]/255; -if color_name == 'r' - colorRBG = red_col; -elseif color_name == 'c' - colorRBG = cyan_col; -elseif color_name == 'y' - colorRBG = yellow_col; -elseif color_name == 'b' - colorRBG = blue_col; -elseif color_name == 'o' - colorRBG = orange_col; -elseif color_name == 'g' - colorRBG = green_col; +if ischar( color_name ) + cyan_col = [0,255,255]/255; + orange_col = [255,165,0]/255; + red_col = [255,0,0]/255; + green_col = [0,255,0]/255; + blue_col = [0,0,255]/255; + yellow_col = [255,255,0]/255; + + + if color_name == 'r' + colorRBG = red_col; + elseif color_name == 'c' + colorRBG = cyan_col; + elseif color_name == 'y' + colorRBG = yellow_col; + elseif color_name == 'b' + colorRBG = blue_col; + elseif color_name == 'o' + colorRBG = orange_col; + elseif color_name == 'g' + colorRBG = green_col; + else + disp ('color not found'); + end + else - disp ('color not found'); + + colorRBG = color_name; end - end diff --git a/viz/intLoadDataViewer.m b/viz/intLoadDataViewer.m index 9bd8185..a78cbeb 100644 --- a/viz/intLoadDataViewer.m +++ b/viz/intLoadDataViewer.m @@ -36,6 +36,7 @@ data_r = []; data_f = []; if shouldLoadNeighborFrames(FLAGS) + 'boom' if nn > 1 data_r = loaderInternal([dirname,contents(nn-1).name], clist); end diff --git a/viz/intMakeMultiChannel.m b/viz/intMakeMultiChannel.m new file mode 100644 index 0000000..4db1720 --- /dev/null +++ b/viz/intMakeMultiChannel.m @@ -0,0 +1,123 @@ +function im = intMakeMultiChannel( data, FLAGS, CONST, clist, nc ) +% intMakeMultiChannel: Code for making a multichannel compsite fluorescent +% image. +% Notes: The long term goal is to implement this code for all the +% visualization modules... so updates will update all at once. This +% implementation isn't done yet... but will happen eventually. +% +% INPUT : +% data : cell/frame data file +% FLAGS: the flags struct from superSeggerViewerGui +% CONST : segmentation parameters +% clist : cell list +% nc: Number of fluorescent channels +% +% OUTPUT : +% composite 8 bit color image. +% +% Copyright (C) 2016 Wiggins Lab +% Written by Paul Wiggins +% University of Washington, 2018 +% This file is part of SuperSegger. +% +% SuperSegger is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% SuperSegger is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with SuperSegger. If not, see . + +im = []; + +if (FLAGS.f_flag == 0 && ~FLAGS.composite ) || ... + (FLAGS.phase_flag( FLAGS.f_flag +1 ) && ~FLAGS.composite) ... + || (FLAGS.composite && FLAGS.include(1) ); + + if FLAGS.manual_lut(1) && ~isnan( FLAGS.lut_min(1) ) && ~isnan( FLAGS.lut_max(1)) + minmax = [FLAGS.lut_min(1), FLAGS.lut_max(1)]; + elseif FLAGS.gbl_auto(1) && isfield( clist, 'imRangeGlobal') + minmax = clist.imRangeGlobal(:,1); + else + minmax = intMakeMinMax( data.phase ); + end + + im = comp( {data.phase, minmax, FLAGS.level(1)} ); +end + +% if you are in fluorescence mode (f_flag) draw the fluor channels +if FLAGS.f_flag && CONST.view.falseColorFlag + ranger = FLAGS.f_flag; +elseif FLAGS.composite + ranger = find(FLAGS.include(2:(nc+1))); +elseif ~FLAGS.f_flag + ranger = []; +else + ranger = FLAGS.f_flag; +end + +for ii = ranger; + + flName = ['fl',num2str(ii),'bg']; + + filtName = ['fluor',num2str(ii),'_filtered']; + + if FLAGS.filt(ii) && isfield( data, filtName); + flourName = filtName; + else + flourName = ['fluor',num2str(ii)]; + end + + im_tmp = data.(flourName); + + if FLAGS.filt(ii) + minmax = intMakeMinMax( im_tmp ); + + elseif FLAGS.manual_lut(ii+1) && ~isnan( FLAGS.lut_min(ii+1) ) && ~isnan( FLAGS.lut_max(ii+1)) + minmax = [FLAGS.lut_min(ii+1), FLAGS.lut_max(ii+1)]; + elseif FLAGS.gbl_auto(ii+1) && isfield( clist, 'imRangeGlobal') + minmax = clist.imRangeGlobal(:,ii+1); + else + minmax = intMakeMinMax( im_tmp ); + + if isfield( data, flName ) + minmax(1) = data.(flName); + end + + end + + if CONST.view.falseColorFlag && FLAGS.f_flag + cc = jet(256); + else + cc = CONST.view.fluorColor{ii}; + end + + + command = {im_tmp, cc, FLAGS.level(ii+1)}; + + if FLAGS.log_view(ii) + command = {command{:}, 'log'}; + else + command = {command{:}, minmax }; + end + + im = comp( {im}, command ); + + +end + + + + + + + + + + +end \ No newline at end of file diff --git a/viz/makeCellMovie.m b/viz/makeCellMovie.m index 86f26d4..857ae21 100644 --- a/viz/makeCellMovie.m +++ b/viz/makeCellMovie.m @@ -1,4 +1,4 @@ -function mov = makeCellMovie(data) +function mov = makeCellMovie(data, CONST, FLAGS, clist) % makeCellMovie : creates a movie for a single cell file % INPUT : % data : a Cell data structure @@ -24,6 +24,11 @@ % You should have received a copy of the GNU General Public License % along with SuperSegger. If not, see . + +if ~isfield (CONST.view,'fluorColor') + CONST.view.fluorColor = {'g','r','b'}; +end + figure(2); num_im = numel(data.CellA); @@ -39,75 +44,130 @@ figure(2); clf; dataA = data.CellA{ii}; - back = ag(dataA.phase); + + +% back = ag(dataA.phase); +% +% if isfield( dataA, 'fluor1' ) +% fluo = ag(dataA.fluor1); +% else +% fluo = back*0; +% end; +% +% +% if isfield( dataA, 'fluor2' ) +% fluo2 = ag(dataA.fluor2); +% else +% fluo2 = fluo*0; +% end; +% +% +% mask_ = imdilate(dataA.mask,strel('square',3)); +% mask = dataA.mask; +% outline= mask_-mask; +% maski = ag(outline); +% +% if exist( 'fluo2', 'var' ); +% fluo2_thresh = fluo2(logical(mask)); +% fluo2_thresh = mean(fluo2_thresh); +% end +% +% fluo_thresh = fluo(logical(mask)); +% fluo_thresh = mean(fluo_thresh); +% gChan = fixIm(0.6*ag(double(uint8(fluo-0*fluo_thresh)).*(0.3+double(mask)*0.6))+0.3*back,ss); +% [bChan,roffset] = fixIm(0.3*maski+0.3*back,ss); +% +% if exist( 'fluo2', 'var' ); +% rChan = fixIm(0.6*ag(double(uint8(fluo2-0*fluo2_thresh)).*(0.3+double(mask)*0.6))+0.3*back,ss); +% else +% rChan = fixIm(0.3*back,ss); +% end - if isfield( dataA, 'fluor1' ) - fluo = ag(dataA.fluor1); - else - fluo = back*0; - end - - if isfield( dataA, 'fluor2' ) - fluo2 = ag(dataA.fluor2); + [~,roffset] = fixIm( dataA.phase, ss); + + if FLAGS.autoscale + imm = comp( dataA.phase ); else - fluo2 = fluo*0; + imm = comp( {dataA.phase, clist.imRangeGlobal(:,1) } ); end - - mask_ = imdilate(dataA.mask,strel('square',3)); - mask = dataA.mask; - outline= mask_-mask; - maski = ag(outline); - if exist( 'fluo2', 'var' ) - fluo2_thresh = fluo2(logical(mask)); - fluo2_thresh = mean(fluo2_thresh); + if ~FLAGS.phase_flag + imm = 0*imm; end - fluo_thresh = fluo(logical(mask)); - fluo_thresh = mean(fluo_thresh); - gChan = fixIm(0.6*ag(double(uint8(fluo-0*fluo_thresh)).*(0.3+double(mask)*0.6))+0.3*back,ss); - [bChan,roffset] = fixIm(0.3*maski+0.3*back,ss); + nc = numel(find(~cellfun('isempty',strfind(fieldnames(dataA),'fluor')))); - if exist('fluo2', 'var') - rChan = fixIm(0.6*ag(double(uint8(fluo2-0*fluo2_thresh)).*(0.3+double(mask)*0.6))+0.3*back,ss); - else - rChan = fixIm(0.3*back,ss); - end + for jj = 1:nc + fluorName = ['fluor',num2str(jj)]; - imshow( cat(3, rChan, gChan, bChan), [],'InitialMagnification','fit'); - hold on; - ro = dataA.r_offset; - r = dataA.r; - plot( r(1)-ro(1)+1+roffset(1), r(2)-ro(2)+1+roffset(2), 'w.' ); + if FLAGS.f_flag == jj || FLAGS.composite + if isfield(dataA, fluorName ) + cc = CONST.view.fluorColor{jj}; + + if FLAGS.filt(jj) && isfield( dataA, [fluorName,'_filtered'] ) + fluor_tmp = dataA.([fluorName,'_filtered']); + else + fluor_tmp = dataA.(fluorName); + end + + if FLAGS.autoscale || FLAGS.filt(jj) + imm = comp( {imm}, {fluor_tmp, cc } ); + else + imm = comp( {imm}, ... + {fluor_tmp, clist.imRangeGlobal(:,jj+1), cc} ); + end + end + end + end - ll = dataA.length; - llmaj = [ll(1),-ll(1)]; - llmin = [ll(2),-ll(2)]; + mask = dataA.mask; + mask = double(mask)+ 0.33*(1-double(mask)); - xx = llmaj*dataA.coord.e1(1)/2; - yy = llmaj*dataA.coord.e1(2)/2; - plot( r(1)-ro(1)+1+xx+roffset(1), r(2)-ro(2)+1+yy+roffset(2), 'b:' ); + imm = comp( {imm, 'mask', mask } ); - xx = llmin*dataA.coord.e2(1)/2; - yy = llmin*dataA.coord.e2(2)/2; - plot( r(1)-ro(1)+1+xx+roffset(1), r(2)-ro(2)+1+yy+roffset(2), 'b:' ); + imshow( imm, [],'InitialMagnification','fit'); - if isfield(dataA, 'locus1' ) - num_spot = numel( dataA.locus1 ); - for jj = 1:num_spot - r = dataA.locus1(jj).r; - plot( r(1)-ro(1)+1+roffset(1), r(2)-ro(2)+1+roffset(2), 'go' ); + if FLAGS.s_flag + hold on; + + ro = dataA.r_offset; + r = dataA.r; + + % ro = dataA.r_offset; + % r = dataA.r; + % plot( r(1)-ro(1)+1+roffset(1), r(2)-ro(2)+1+roffset(2), 'w.' ); + % + % ll = dataA.length; + % llmaj = [ll(1),-ll(1)]; + % llmin = [ll(2),-ll(2)]; + % + % xx = llmaj*dataA.coord.e1(1)/2; + % yy = llmaj*dataA.coord.e1(2)/2; + % plot( r(1)-ro(1)+1+xx+roffset(1), r(2)-ro(2)+1+yy+roffset(2), 'b:' ); + % + % xx = llmin*dataA.coord.e2(1)/2; + % yy = llmin*dataA.coord.e2(2)/2; + % plot( r(1)-ro(1)+1+xx+roffset(1), r(2)-ro(2)+1+yy+roffset(2), 'b:' ); + + for jj = 1:nc + fluorName = ['locus',num2str(jj)]; + if FLAGS.f_flag == jj || FLAGS.composite + if isfield(dataA, fluorName ) + cc = CONST.view.fluorColor{jj}; + + num_spot = numel( dataA.(fluorName) ); + for jj = 1:num_spot; + r = dataA.(fluorName)(jj).r; + plot( r(1)-ro(1)+1+roffset(1), r(2)-ro(2)+1+roffset(2),... + '.', 'Color', cc); + end + end + end end + end - if isfield(dataA, 'locus2' ) - num_spot = numel(dataA.locus2 ); - for jj = 1:num_spot - r = dataA.locus2(jj).r; - plot( r(1)-ro(1)+1+roffset(1), r(2)-ro(2)+1+roffset(2), 'ro' ); - end - end drawnow; mov(ii) = getframe; diff --git a/viz/makeFrameMosaic.m b/viz/makeFrameMosaic.m index 40d2588..e0aade4 100644 --- a/viz/makeFrameMosaic.m +++ b/viz/makeFrameMosaic.m @@ -1,4 +1,4 @@ -function [im] = makeFrameMosaic( data, CONST, xdim, disp_flag, skip ) +function [im] = makeFrameMosaic( data, CONST, xdim, disp_flag, skip, FLAGS ) % makeFrameMosaic: Creates a tower for a single cell. % The cell is shown masked. If CONST.view.orientFlag is true the cell % is oriented horizontally, it can be shown with FalseColor and @@ -18,7 +18,22 @@ % University of Washington, 2016 % This file is part of SuperSeggerOpti. -with_outline = 1; + +if ~exist( 'FLAGS', 'var' ) || isempty( FLAGS ) + FLAGS.composite = 1; + FLAGS.f_flag = 1; + FLAGS.Outline_flag = 0; +end + + + +%which_channel = [1,1,1]; +% if ~exist( 'which_channel', 'var' ) || isempty(which_channel) +% which_channel = [1,1,1]; +% end + +nc = intGetChannelNum( data.CellA{1} ); + persistent strel1; if isempty( strel1 ) @@ -131,13 +146,21 @@ mask_mosaic = zeros(imdim(1), imdim(2)); im_list = []; + + +imm = cell([1,nc]); + for ii = 1:skip:numframe + + yy = floor((ii-1)/nx/skip); xx = (ii-1)/skip-yy*nx; ss = ssCell{ii}; dx = floor((max_x-ss(2))/2); dy = floor((max_y-ss(1))/2); + + if orientFlag mask = imCell{ii}; mask = (imdilate( mask, strel1 )); @@ -148,103 +171,99 @@ mask_mosaic(1+yy*max_y+(1:ss(1))+dy, 1+xx*max_x+(1:ss(2))+dx) = mask; + + + FLAG_ = zeros([1,nc]); % fluor1 - if isfield( data.CellA{ii}, 'fluor1' ) - if isfield( CONST.view, 'filtered' ) && ... - CONST.view.filtered && ... - isfield( data.CellA{ii}, 'fluor1_filtered' ) - fluor1 =data.CellA{ii}.fluor1_filtered; - else - fluor1 = data.CellA{ii}.fluor1; - if isfield( data.CellA{ii}, 'fl1' ) && ... - isfield( data.CellA{ii}.fl1, 'bg' ) - fluor1 = fluor1 - data.CellA{ii}.fl1.bg; - end - end - - fluor1 = imrotate(fluor1,alpha(ii),'bilinear'); - fluor1 = fluor1(yyCell{ii}, xxCell{ii}); - im1_(1+yy*max_y+(1:ss(1))+dy, 1+xx*max_x+(1:ss(2))+dx) = fluor1; - FLAG1 = true; - else - im1_ = 0*mask_mosaic; - FLAG1 = false; - f1mm = [0,1]; - end + % loop over channels - % fluor2 - flag2 = isfield( data.CellA{ii}, 'fluor2' ); - if isfield( data.CellA{ii}, 'fluor2' ) && 1 + for jj = 1:nc + - if isfield( CONST.view, 'filtered' ) && ... - CONST.view.filtered && ... - isfield( data.CellA{ii}, 'fluor2_filtered' ) - - fluor2 =data.CellA{ii}.fluor2_filtered; - else - fluor2 = data.CellA{ii}.fluor2; + if ii==1 + imm{jj} = mask_mosaic; end - fluor2 = imrotate(fluor2,alpha(ii),'bilinear'); - fluor2 = fluor2(yyCell{ii}, xxCell{ii}); - + fluorName = ['fluor',num2str(jj)]; + ffiltName = ['fluor',num2str(jj),'_filtered']; + flName = ['fl',num2str(jj)]; - if isfield( data.CellA{ii}, 'fl2' ) && ... - isfield( data.CellA{ii}.fl2, 'bg' ) - fluor2 = fluor2 - data.CellA{ii}.fl2.bg; - fluor2(fluor2<0) = 0; + if isfield( data.CellA{ii}, fluorName ) + if FLAGS.filt(jj) && ... + isfield( data.CellA{ii}, ffiltName ) + fluor_tmp =data.CellA{ii}.(ffiltName); + else + fluor_tmp = data.CellA{ii}.(fluorName); + if isfield( data.CellA{ii}, flName ) && ... + isfield( data.CellA{ii}.(flName), 'bg' ) + fluor_tmp = fluor_tmp - data.CellA{ii}.(flName).bg; + end + end + + fluor_tmp = imrotate(fluor_tmp, alpha(ii), 'bilinear'); + fluor_tmp = fluor_tmp(yyCell{ii}, xxCell{ii}); + imm{jj}(1+yy*max_y+(1:ss(1))+dy, 1+xx*max_x+(1:ss(2))+dx) = fluor_tmp; + + FLAG_(jj) = true; + else + %im1_ = 0*mask_mosaic; + FLAG_(jj) = false; + f1mm = [0,1]; end + +% if FLAG2 +% im_list = [im_list, data.CellA{ii}.fluor1(:)', data.CellA{ii}.fluor2(:)']; +% elseif FLAG1 +% im_list = [im_list, data.CellA{ii}.fluor1(:)']; +% else +% im_list = [im_list]; +% end - im2_(1+yy*max_y+(1:ss(1))+dy, 1+xx*max_x+(1:ss(2))+dx) = fluor2; - FLAG2 = true; - else - im2_ = uint8(0*mask_mosaic); - FLAG2 = false; - f2mm = [0,1]; - end - - if FLAG2 - im_list = [im_list, data.CellA{ii}.fluor1(:)', data.CellA{ii}.fluor2(:)']; - elseif FLAG1 - im_list = [im_list, data.CellA{ii}.fluor1(:)']; - else - im_list = [im_list]; end + end % autogain the images -im1_ = ag(im1_); -im2_ = ag(im2_); + + +%im1_ = ag(im1_); +%im2_ = ag(im2_); +disk1 = strel('disk',1); + + % different display methods if isfield(CONST.view, 'falseColorFlag') && ... - CONST.view.falseColorFlag && ~flag2 + CONST.view.falseColorFlag % false color image - only works if there is only one channel - im = ag(doColorMap( im1_, colormap_ )); - back3 = uint8( cat( 3, double(CONST.view.background(1))*double(1-mask_mosaic),... - double(CONST.view.background(2))*double(1-mask_mosaic),... - double(CONST.view.background(3))*double(1-mask_mosaic))); - mask3 = cat( 3, mask_mosaic, mask_mosaic, mask_mosaic ); - im = uint8(uint8( double(im).*mask3)+back3); -elseif with_outline - % plots normal mosaic with region outline - del = 1; - disk1 = strel('disk',1); - outer = imdilate(mask_mosaic, disk1).*double(~mask_mosaic); - im = cat( 3, ... - uint8(double(im2_).*mask_mosaic)+del*ag(1-mask_mosaic), ... - uint8(double(im1_).*mask_mosaic)+del*ag(1-mask_mosaic), ... - del*ag(1-mask_mosaic)+ag(outer)); + + im = comp( {imm{jj},colormap_,'mask', mask_mosaic, 'back' ,CONST.view.background} ); else - del = 1; - disk1 = strel('disk',1); - im = cat( 3, ... - uint8(double(im2_).*mask_mosaic)+del*ag(1-mask_mosaic), ... - uint8(double(im1_).*mask_mosaic)+del*ag(1-mask_mosaic), ... - del*ag(1-mask_mosaic) ); + + if FLAGS.Outline_flag + + disk1 = strel('disk',2); + outer = imdilate(mask_mosaic, disk1).*double(~mask_mosaic); + else + outer = zeros( size( im1_ ) ); + end + + % plots normal mosaic with region outline + im = []; + for jj = 1:nc + if FLAGS.composite || FLAGS.f_flag == jj + if FLAGS.include(jj+1) + im = comp( {im}, {imm{jj}, CONST.view.fluorColor{jj}, FLAGS.level(jj+1)} ); + end + end + end + + im = comp( {im,'mask',mask_mosaic,'back',CONST.view.background},... + {ag(outer),'b'} ); end + inv_flag = 0; frameNumbers = 1:skip:numframe; if disp_flag diff --git a/viz/makeFrameStripeMosaic.m b/viz/makeFrameStripeMosaic.m index 00b4846..264628f 100644 --- a/viz/makeFrameStripeMosaic.m +++ b/viz/makeFrameStripeMosaic.m @@ -1,4 +1,4 @@ -function [imTot] = makeFrameStripeMosaic( dirName, CONST, skip, disp_flag, clist ) +function [imTot] = makeFrameStripeMosaic( dirName, CONST, skip, disp_flag, clist, FLAGS ) % makeFrameStripeMosaic : Creates a long stripe with all the cell towers. % % INPUT : @@ -69,7 +69,7 @@ cellArrayNum{ii} = floor(str2num(contents(ii).name(lpos+1:ppos-1))); end - tmp_im = makeFrameMosaic(data,CONST,1,false, skip ); + tmp_im = makeFrameMosaic(data,CONST,1,false, skip, FLAGS ); if isfield( CONST.view, 'saveFiles' ) && CONST.view.saveFiles loadname(end-2:end)='png'; @@ -87,21 +87,22 @@ end if ~CONST.view.saveFiles + + tmptmp = ones( [ssTot(1), ssTot(2)] ); + if CONST.view.falseColorFlag if ~isfield( CONST.view, 'background' ); CONST.view.background = [0,0,0]; end - tmptmp = zeros( [ssTot(1), ssTot(2)] ); - imTot = uint8( cat( 3, tmptmp + CONST.view.background(1),... - tmptmp + CONST.view.background(2),... - tmptmp + CONST.view.background(3))); + imTot = comp( {tmptmp, CONST.view.background} ); else del = 0.0; - limTot = uint8(zeros( [ssTot(1), ssTot(2), 3] )); + imTot = comp( {tmptmp, CONST.view.background} ); + end colPos = 1; diff --git a/viz/makeKymoMosaic.m b/viz/makeKymoMosaic.m index 3131536..007543a 100644 --- a/viz/makeKymoMosaic.m +++ b/viz/makeKymoMosaic.m @@ -1,4 +1,4 @@ -function [im]= makeKymoMosaic (dirname, CONST) +function [im]= makeKymoMosaic (dirname, CONST, FLAGS) % makeKymoMosaic creates a mosaic kymograph of multiple cells. % make kymo mosaic is only for fl1 in makeKymograph, which is currently % set to gfp. A kymograph shows the fluorescence of the cell along the @@ -7,25 +7,25 @@ % INPUT : % dirname : directory with cell data files % CONST : segmentation parameters -% OUTPUT : +% OUTPUT : % im : output image of kymo mosaic % % -% Copyright (C) 2016 Wiggins Lab +% Copyright (C) 2016 Wiggins Lab % Written by Paul Wiggins, Stella Stylianidou. % University of Washington, 2016 % This file is part of SuperSegger. -% +% % SuperSegger is free software: you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation, either version 3 of the License, or % (at your option) any later version. -% +% % SuperSegger is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. -% +% % You should have received a copy of the GNU General Public License % along with SuperSegger. If not, see . @@ -57,141 +57,152 @@ CONST.view.maxNumCell = 100; else - num_list_ = min( [num_list_, CONST.view.maxNumCell] ); - num_list = 0; - - for ii = 1:num_list_ - if (~isempty(dir_list(ii).name)) - num_list = num_list + 1; - end +num_list_ = min( [num_list_, CONST.view.maxNumCell] ); +num_list = 0; + +for ii = 1:num_list_ + if (~isempty(dir_list(ii).name)) + num_list = num_list + 1; end +end + +numa = ceil(sqrt(num_list)); +numb = ceil( num_list/numa); + + +clf; +max_x = 0; +max_t = 0; +data_A = cell(1,num_list); +del = .1; +ii = 0; + +h = waitbar(0, 'Computation' ); +cleanup = onCleanup( @()( delete( h ) ) ); + +for jj = 1:num_list_ - numa = ceil(sqrt(num_list)); - numb = ceil( num_list/numa); - - - clf; - max_x = 0; - max_t = 0; - data_A = cell(1,num_list); - del = .1; - ii = 0; - - h = waitbar(0, 'Computation' ); - cleanup = onCleanup( @()( delete( h ) ) ); - - for jj = 1:num_list_ + if ~isempty(dir_list(jj).name) - if ~isempty(dir_list(jj).name) - - ii = ii + 1; - filename = [dirname,filesep,dir_list(jj).name]; - data = load(filename); - [kymo,~,f1mm,~] = makeKymographC(data,0,CONST); - - name(jj) = data.ID; - pole(jj) = getPoleSign( data ); - - if CONST.view.falseColorFlag - backer3 = double(cat(3, kymo.b, kymo.b, kymo.b)>1); - im = doColorMap( ag(kymo.g,f1mm(1), f1mm(2)), colormap_ ); - data_A{ii} =( im.*backer3+.6*(1-backer3) ); - else - data_A{ii} = cat(3,del*ag(1-kymo.b)+ag(kymo.r),... - del*ag(1-kymo.b)+ag(kymo.g),del*ag(1-kymo.b)); - end - - ss = size(data_A{ii}); - max_x = max([max_x,ss(1)]); - max_t = max([max_t,ss(2)]); - end - waitbar(jj/num_list_,h); - end - close(h); - - max_x = max_x+1; - max_t = max_t+1; - imdim = [ max_x*numa + 1, max_t*numb + 1 ]; - - for ii = 1:2 - if isnan(imdim(ii)) - imdim (ii)= 0; - end - end - - - if CONST.view.falseColorFlag - cc = 'w'; - im = (zeros(imdim(1), imdim(2), 3 )); - im(:,:,:) = del*0; + ii = ii + 1; + filename = [dirname,filesep,dir_list(jj).name]; + data = load(filename); + data_A{ii} = makeKymographC(data, 0, CONST, FLAGS); + + name(jj) = data.ID; + pole(jj) = getPoleSign( data ); - for ii = 1:num_list - yy = floor((ii-1)/numb); - xx = ii-yy*numb-1; - - ss = size(data_A{ii}); - dx = floor((max_x-ss(1))/2); - - im(1+yy*max_x+(1:ss(1))+dx, 1+xx*max_t+(1:ss(2)),:) = data_A{ii}; - end - else - cc = 'w'; - im = uint8(zeros(imdim(1), imdim(2), 3 )); - im(:,:,:) = del*255; +% if CONST.view.falseColorFlag +% backer3 = double(cat(3, kymo.b, kymo.b, kymo.b)>1); +% im = doColorMap( ag(kymo.c1,f1mm(1), f1mm(2)), colormap_ ); +% data_A{ii} =( im.*backer3+.6*(1-backer3) ); +% else +% data_A{ii} = comp( {ag(1-kymo.b),[del,del,del]}, ... +% {ag(kymo.c2),CONST.view.fluorColor{2} },... +% {ag(kymo.c1),CONST.view.fluorColor{1} }); +% end - for ii = 1:num_list - yy = floor((ii-1)/numb); - xx = ii-yy*numb-1; - - ss = size(data_A{ii}); - dx = floor((max_x-ss(1))/2); - - im(1+yy*max_x+(1:ss(1))+dx, 1+xx*max_t+(1:ss(2)),:) = data_A{ii}; - end + + + ss = size(data_A{ii}); + max_x = max([max_x,ss(1)]); + max_t = max([max_t,ss(2)]); end - - ss = size(im); - - T_ = (1:ss(2))*TimeStep; - X_ = (1:ss(1))*PixelSize; - - inv_flag = 0; - figure; - clf; - if inv_flag - imagesc(T_,X_,255-im); - else - imagesc(T_,X_,im); + waitbar(jj/num_list_,h); +end + close(h); + +max_x = max_x+1; +max_t = max_t+1; +imdim = [ max_x*numa + 1, max_t*numb + 1 ]; + +for ii = 1:2 + if isnan(imdim(ii)) + imdim (ii)= 0; + end +end + + +if CONST.view.falseColorFlag + cc = 'w'; + im = (zeros(imdim(1), imdim(2), 3 )); + + for ii = 1:3 + im(:,:,ii) = uint8(CONST.view.background(ii)*255); end - hold on; - - nx = ceil(sqrt( num_list*max_x/max_t)); - ny = ceil(num_list/nx); - - max_T = max(T_); - max_X = max(X_); for ii = 1:num_list yy = floor((ii-1)/numb); xx = ii-yy*numb-1; - y = yy*(max_X/numa); - x = xx*(max_T/numb); - text( x+max_T/20/numb, y+max_X/20/numa, [num2str(name(ii))],'Color',cc,'FontSize',12,'VerticalAlignment','Top','HorizontalAlignment','Left'); + + ss = size(data_A{ii}); + dx = floor((max_x-ss(1))/2); + + im(1+yy*max_x+(1:ss(1))+dx, 1+xx*max_t+(1:ss(2)),:) = data_A{ii}; end - - - dd = [1,numa*max_x+1]; - for xx = 1:(numb-1) - plot( (0*dd + 1+xx*max_t)*TimeStep, dd*PixelSize,[':',cc]); +else + cc = 'w'; + im = uint8(zeros(imdim(1), imdim(2), 3 )); + for ii = 1:3 + im(:,:,ii) = uint8(CONST.view.background(ii)*255); end - dd = [1,numb*max_t+1]; - for yy = 1:(numa-1) - plot( (dd)*TimeStep, (0*dd + 1+yy*max_x)*PixelSize, [':',cc]); + for ii = 1:num_list + yy = floor((ii-1)/numb); + xx = ii-yy*numb-1; + + ss = size(data_A{ii}); + dx = floor((max_x-ss(1))/2); + + im(1+yy*max_x+(1:ss(1))+dx, 1+xx*max_t+(1:ss(2)),:) = data_A{ii}; end - - xlabel('Time (h)'); - ylabel('Long Axis Position (um)'); - end +im = uint8( im ); + +ss = size(im); + +T_ = (1:ss(2))*TimeStep; +X_ = (1:ss(1))*PixelSize; + +inv_flag = 0; +figure; +clf; +if inv_flag + imagesc(T_,X_,255-im); +else + imagesc(T_,X_,im); +end +hold on; + +nx = ceil(sqrt( num_list*max_x/max_t)); +ny = ceil(num_list/nx); + +max_T = max(T_); +max_X = max(X_); + +for ii = 1:num_list + yy = floor((ii-1)/numb); + xx = ii-yy*numb-1; + y = yy*(max_X/numa); + x = xx*(max_T/numb); + text( x+max_T/20/numb, y+max_X/20/numa, [num2str(name(ii))],'Color',cc,'FontSize',12,'VerticalAlignment','Top','HorizontalAlignment','Left'); +end + + +dd = [1,numa*max_x+1]; +for xx = 1:(numb-1) + plot( (0*dd + 1+xx*max_t)*TimeStep, dd*PixelSize,[':',cc]); +end + +dd = [1,numb*max_t+1]; +for yy = 1:(numa-1) + plot( (dd)*TimeStep, (0*dd + 1+yy*max_x)*PixelSize, [':',cc]); +end + +xlabel('Time (h)'); +ylabel('Long Axis Position (um)'); + +end + + diff --git a/viz/makeKymographC.m b/viz/makeKymographC.m index a7372e4..4c9bd68 100644 --- a/viz/makeKymographC.m +++ b/viz/makeKymographC.m @@ -1,4 +1,4 @@ -function [Kymo,ll1,f1mm,f2mm] = makeKymographC( data, disp_flag, CONST, which_channel ) +function [imm] = makeKymographC( data, disp_flag, CONST, FLAGS ) % makeKymographC : creates a kymograph for given cell data file.. % A kymograph shows the fluorescence of the cell along the long axis % of the cell, with time. @@ -34,6 +34,18 @@ % You should have received a copy of the GNU General Public License % along with SuperSegger. If not, see . +% compute number of channels +nc = intGetChannelNum( data.CellA{1} ); + +if ~exist( 'FLAGS', 'var' ) || isempty( FLAGS ) + FLAGS.composite = 1; + FLAGS.f_flag = 1; + FLAGS.Outline_flag = 0; + FLAGS.filt = zeros( [1,10] );; +end + + + white_bg = 0; % set to 1 for white background, outlined kymo Kymo = []; ll1=[]; @@ -50,17 +62,15 @@ CONST.view.falseColorFlag = false; end -if ~exist( 'which_channel', 'var' ) || isempty(which_channel) - which_channel = [1,1,1]; -end +% if ~exist( 'which_channel', 'var' ) || isempty(which_channel) +% which_channel = [1,1,1]; +% end if ~isfield(CONST.view, 'filtered' ) CONST.view.filtered = true; end -filt_channel = CONST.view.filtered ; - - +filt_channel = FLAGS.filt;%CONST.view.filtered ; persistent colormap_; if isempty( colormap_ ) @@ -104,56 +114,19 @@ nn = numel( ll1 ); -kymoR = zeros(nn,num_im); -kymoG = zeros(nn,num_im); -kymoB = zeros(nn,num_im); +kymo_cell = cell([1,nc]); +if ~isfield(data.CellA{1}, 'pole'); + data.CellA{1}.pole.op_ori = 1; +end + for ii = 1:num_im - - mask = data.CellA{ii}.mask; - - if isfield( data.CellA{ii}, 'fluor1') && which_channel(1) - if filt_channel && isfield( data.CellA{ii},'fluor1_filtered') - fluor1 =data.CellA{ii}.fluor1_filtered; - else - fluor1 = data.CellA{ii}.fluor1; - if isfield( data.CellA{ii}, 'fl1' ) && isfield( data.CellA{ii}.fl1, 'bg' ) - fluor1 = fluor1 - data.CellA{ii}.fl1.bg; - fluor1(fluor1<0) = 0; - else - fluor1 = fluor1 - mean( fluor1(mask)); - fluor1(fluor1<0) = 0; - end - end - else - fluor1 = 0*mask; - end - - if isfield( data.CellA{ii}, 'fluor2') && which_channel(2) - if filt_channel && isfield( data.CellA{ii}, 'fluor2_filtered' ) - fluor2 = data.CellA{ii}.fluor2_filtered; - else - fluor2 = data.CellA{ii}.fluor2; - if isfield( data.CellA{ii}, 'fl12' ) && ... - isfield( data.CellA{ii}.fl2, 'bg' ) - fluor2 = fluor2 - data.CellA{ii}.fl2.bg; - fluor2(fluor1<0) = 0; - else - fluor2 = fluor2 - mean( fluor2(mask)); - fluor2(fluor2<0) = 0; - end - end - else - fluor2 = 0*data.CellA{ii}.mask; - end - + mask = data.CellA{ii}.mask; - - % Make all the images the same sizes - [rChan,~] = (fixIm(double((fluor2)).*double(mask),ss)); - [gChan,~] = (fixIm(double((fluor1)).*double(mask),ss)); - [bChan,roffset] = fixIm(mask,ss); + + % take care of background image first + [Chan_tmp,roffset] = fixIm(mask,ss); ro = data.CellA{ii}.r_offset; r = data.CellA{ii}.r; @@ -164,64 +137,94 @@ LL1x = LL1*e1(1)+LL2*e2(1)+r(1)-ro(1)+1+roffset(1); LL2y = LL1*e1(2)+LL2*e2(2)+r(2)-ro(2)+1+roffset(2); - rChanp = (interp2(XX,YY,double(rChan),LL1x,LL2y)); - gChanp = (interp2(XX,YY,double(gChan),LL1x,LL2y)); - bChanp = (interp2(XX,YY,double(bChan),LL1x,LL2y)); + Chan_tmp = (interp2(XX,YY,double(Chan_tmp),LL1x,LL2y)); + Chan_tmp = sum( double(Chan_tmp) ); + kymo_back(:,ii) = Chan_tmp'; + + if data.CellA{1}.pole.op_ori < 0 % flip the kymograph + kymo_back(:,ii) = kymo_back(end:-1:1,ii); + end + % compute fluor channels - rChanps = sum( double(rChanp) ); - gChanps = sum( double(gChanp) ); - bChanps = sum( double(bChanp) ); - kymoR(:,ii) = rChanps'; - kymoG(:,ii) = gChanps'; - kymoB(:,ii) = bChanps'; + for jj = 1:nc + + + fluorName = ['fluor',num2str(jj)]; + ffiltName = ['fluor',num2str(jj),'_filtered']; + flName = ['fl',num2str(jj)]; + + if isfield( data.CellA{ii}, fluorName ) && ... + ( FLAGS.f_flag == jj || FLAGS.composite ) + + + if ii == 1 + kymo_cell{jj} = zeros(nn,num_im); + end + + if filt_channel(jj) && isfield( data.CellA{ii},ffiltName) + fluor_tmp =data.CellA{ii}.(ffiltName); + else + fluor_tmp = data.CellA{ii}.(fluorName); + + if isfield( data.CellA{ii}, flName ) && isfield( data.CellA{ii}.(flName), 'bg' ) + fluor_tmp = fluor_tmp - data.CellA{ii}.(flName).bg; + fluor_tmp(fluor_tmp<0) = 0; + else + fluor_tmp = fluor_tmp - mean( fluor_tmp(mask)); + fluor_tmp(fluor_tmp<0) = 0; + end + end + else + fluor_tmp = []; + end + + if ~isempty( fluor_tmp ) + [Chan_tmp,~] = (fixIm(double((fluor_tmp)).*double(mask),ss)); + + Chan_tmp = (interp2(XX,YY,double(Chan_tmp),LL1x,LL2y)); + Chan_tmp = sum( double(Chan_tmp) ); + kymo_cell{jj}(:,ii) = Chan_tmp'; + + if data.CellA{1}.pole.op_ori < 0 % flip the kymograph + kymo_cell{jj}(:,ii) = kymo_cell{jj}(end:-1:1,ii); + end + end + + end end -Kymo = []; +kymo_back(isnan(kymo_back)) = 0; -if ~isfield(data.CellA{1}, 'pole'); - data.CellA{1}.pole.op_ori = 1; +kymo_back(kymo_back>1) = 1; + +% get min and mask values in masked region for each channel +imRange = nan( [2,nc] ); +for jj = 1:nc + if ~isempty(kymo_cell{jj}) + imRange(:,jj) = intRange(kymo_cell{jj}(logical(kymo_back))); + end end -if data.CellA{1}.pole.op_ori < 0 % flip the kymograph - Kymo.g = kymoG(end:-1:1,:); - Kymo.b = kymoB(end:-1:1,:); - Kymo.b(isnan(Kymo.b)) = 0; - Kymo.r = kymoR(end:-1:1,:); +if CONST.view.falseColorFlag && FLAGS.f_flag > 0 + imm = comp( {kymo_cell{FLAGS.f_flag},imRange(:,FLAGS.f_flag),... + colormap_,'mask',kymo_back,'back', CONST.view.background} ); else - Kymo.g = kymoG; - Kymo.b = kymoB; - Kymo.b(isnan(Kymo.b)) = 0; - Kymo.r = kymoR; -end - -f1mm(1) = min(Kymo.g(logical(Kymo.b))); -f1mm(2) = max(Kymo.g(logical(Kymo.b))); -f2mm(1) = min(Kymo.r(logical(Kymo.b))); -f2mm(2) = max(Kymo.r(logical(Kymo.b))); - - -if CONST.view.falseColorFlag - % false color figure - backer3 = double(cat(3, Kymo.b, Kymo.b, Kymo.b)>1); - im = doColorMap( ag(Kymo.g,f1mm(1), f1mm(2)), colormap_ ); - imm = im.*backer3+.6*(1-backer3); -elseif white_bg - % figure with outline and white background - sq = [1 1 1 ; 1 1 1 ; 1 1 1]; - backer = (ag(~Kymo.b)); - outline = imdilate(backer,sq) - backer; - imm = cat(3, (ag(Kymo.r))+backer+0.2*outline, ... - (ag(Kymo.g))+backer+0.2*outline,... - backer+0.6*outline); -else - % figure without outline and gray background - backer = (ag(Kymo.b)); - backer = 0.3*(max(backer(:))-backer); - imm = cat(3, (ag(Kymo.r))+backer, ... - (ag(Kymo.g))+backer,... - backer); + + imm = []; + + for jj = 1:nc + if ~isempty( kymo_cell{jj} ) && (FLAGS.composite || FLAGS.f_flag==jj ) + if FLAGS.include( jj+1) + imm = comp( {imm}, {kymo_cell{jj}, imRange(:,jj),... + CONST.view.fluorColor{jj}, FLAGS.level(jj+1)} ); + end + end + end + + imm = comp( {imm, 'mask', kymo_back , 'back', CONST.view.background} ); + end if disp_flag @@ -251,4 +254,4 @@ printError(ME); end roffset = offset(2:-1:1); -end \ No newline at end of file +end diff --git a/viz/makeLineage.m b/viz/makeLineage.m index ec52456..e865b04 100755 --- a/viz/makeLineage.m +++ b/viz/makeLineage.m @@ -24,6 +24,7 @@ % You should have received a copy of the GNU General Public License % along with SuperSegger. If not, see . +global mother_index; global daughter1_index; global daughter2_index; global cell_birth_index; @@ -82,15 +83,21 @@ legend_text = {}; count = 0; -mother_index = grabClistIndex(clist, 'mother id'); -daughter1_index = grabClistIndex(clist, 'daughter1 id'); -daughter2_index = grabClistIndex(clist, 'daughter2 id'); -cell_div_index = grabClistIndex(clist, 'Cell Death Time'); -stat_0_index = grabClistIndex(clist,'stat0'); -cell_birth_index = grabClistIndex(clist,'Cell Birth Time'); -cell_error_index = grabClistIndex(clist,'Error Frame'); -cell_age_index = grabClistIndex(clist,'Cell Age' ); -pole_age_index = grabClistIndex(clist,'Old Pole Age' ); + +mother_index = grabClistIndex(clist, 'mother id'); +daughter1_index = grabClistIndex(clist, 'daughter1 id'); +daughter2_index = grabClistIndex(clist, 'daughter2 id'); +cell_div_index = grabClistIndex(clist, 'Cell Division Time'); +if isempty( cell_div_index ) + cell_div_index = grabClistIndex(clist, 'Cell death time'); +end +stat_0_index = grabClistIndex(clist, 'stat0'); +cell_birth_index = grabClistIndex(clist, 'Cell Birth Time'); +cell_error_index = grabClistIndex(clist, 'Error Frame'); +cell_age_index = grabClistIndex(clist, 'Cell Age' ); +pole_age_index = grabClistIndex(clist, 'Old Pole Age' ); + + if isempty(cell_error_index) disp ('no error frame found in clist') @@ -104,7 +111,8 @@ % Make new lineage ID = clist.data(ii,1); - [width,list,time,death,stat0,starter,error,age,gen,pole] ... + [width,list,time,death,stat0,starter,error,age,gen,pole,... + mother,daughter1,daughter2] ... = intGetWidth(ID, clist, starter,1); if (width >= min_width) || time(1) == 1 @@ -112,15 +120,18 @@ stat0, starter, hh, hh2, error, gated, data ); count = count + 1; - data.width = width; - data.ID = list; - data.birth = time; - data.death = death; - data.stat0 = stat0; - data.error = error; - data.age = age; - data.gen = gen; - data.pole = pole; + data.width = width; + data.ID = list; + data.birth = time; + data.death = death; + data.stat0 = stat0; + data.error = error; + data.age = age; + data.gen = gen; + data.pole = pole; + data.mother = mother; + data.daughter1 = daughter1; + data.daughter2 = daughter2; legend_text{count} = ['Cell ',num2str( ID )]; end @@ -132,7 +143,8 @@ for ii = 1:numel(ID_) ID = ID_(ii); - [width,list,time,death,stat0,starter,error,age,gen,pole] = ... + [width,list,time,death,stat0,starter,error,age,gen,pole,... + mother,daughter1,daughter2] = ... intGetWidth(ID, clist, starter, 1); [hh,hh2,data] = intDoDraw( clist, list, time, death, stat0, starter, ... @@ -147,6 +159,9 @@ data.age = age; data.gen = gen; data.pole = pole; + data.mother = mother; + data.daughter1 = daughter1; + data.daughter2 = daughter2; legend_text{ii} = ['Cell ',num2str( ID )]; end @@ -197,9 +212,33 @@ set( gca, 'YGrid', 'on') + + +figure(4); +ylabel( 'Length' ); +xlabel( 'Time (frames)' ); +legend( hh, legend_text, 'Location' , 'NorthWest' ); +set( gca, 'YScale', 'log' ); + + +figure(5); +ylabel( 'Length' ); +xlabel( 'Time (frames)' ); +legend( hh, legend_text, 'Location' , 'NorthWest' ); +set( gca, 'YScale', 'log' ); + +figure(6); +ylabel( 'Length' ); +xlabel( 'Time (frames)' ); +legend( hh, legend_text, 'Location' , 'NorthWest' ); +set( gca, 'YScale', 'log' ); + +data = makePed( data ); + end -function [width,list,time,death,stat0,starter,error,age,gen,pole] = ... +function [width,list,time,death,stat0,starter,error,age,gen,pole,... + mother,daughter1,daughter2] = ... intGetWidth(ID, clist, starter, gen__) global cell_birth_index; global cell_div_index; @@ -221,14 +260,18 @@ age = []; gen = []; pole = []; + daughter1 = []; + daughter2 = []; + mother = []; + else - [ID1,ID2] = intGetDaughter( ID, clist ); + [ID1,ID2,m] = intGetDaughter( ID, clist ); error_ = clist.data(ind,cell_error_index); death_ = clist.data(ind,cell_div_index); age_ = clist.data(ind,cell_age_index); gen_ = gen__; - + if isempty(error_) error_ = nan; end @@ -236,29 +279,37 @@ if isnan(ID1) || isnan(ID2) || (ID1==0) || (ID2==0) || ~isnan(error_) starter = [starter,ID]; - if death_ ~= end_time && isnan(error_); + if death_ ~= end_time && isnan(error_) error_ = death_; end end - [w1,l1,t1,d1,s1,starter,e1,a1,g1,p1] = intGetWidth( ID1, clist, starter,gen__ + 1 ); - [w2,l2,t2,d2,s2,starter,e2,a2,g2,p2] = intGetWidth( ID2, clist, starter,gen__ + 1 ); + [w1,l1,t1,d1,s1,starter,e1,a1,g1,p1,m1,d11,d12] = intGetWidth( ID1, clist, starter,gen__ + 1 ); + [w2,l2,t2,d2,s2,starter,e2,a2,g2,p2,m2,d21,d22] = intGetWidth( ID2, clist, starter,gen__ + 1 ); stat0_ = clist.data(ind,stat_0_index); time_ = clist.data(ind,cell_birth_index); pole_ = clist.data(ind,pole_age_index); %death_ = death_ + time_; - width = 1 + w1 + w2; - list = [ID,l1,l2]; - time = [time_,t1,t2]; - death = [death_,d1,d2]; - stat0 = [stat0_,s1,s2]; - error = [error_,e1,e2]; - age = [age_,a1,a2]; - gen = [gen_,g1,g2]; - pole = [pole_,p1,p2]; + width = 1 + w1 + w2; + list = [ID,l1,l2]; + time = [time_,t1,t2]; + death = [death_,d1,d2]; + stat0 = [stat0_,s1,s2]; + error = [error_,e1,e2]; + age = [age_,a1,a2]; + gen = [gen_,g1,g2]; + pole = [pole_,p1,p2]; + mother = [m,m1,m2]; + daughter1 = [ID1,d11,d21]; + daughter2 = [ID2,d12,d22]; + + if numel(daughter1) ~= numel(mother) + 'hi'; + end + end end @@ -406,17 +457,65 @@ end -function [ID1,ID2] = intGetDaughter( ID, clist ) +function [ID1,ID2,m] = intGetDaughter( ID, clist ) global daughter1_index global daughter2_index +global mother_index + ind = find( clist.data(:,1)==ID ); if isempty(ind) ID1 = nan; ID2 = nan; + m = nan; else ID1 = clist.data(ind,daughter1_index); ID2 = clist.data(ind,daughter2_index); + m = clist.data(ind,mother_index); +end + + +end + +function intDoLengthAn( clist, list ) + +flagger = ismember( clist.data(:,1), list ); + +list = clist.data(flagger,1); + +lengths = squeeze( clist.data3D(flagger,2,:) ); + +figure(4); + +n_ii = numel(list); +for ii = 1:n_ii + ll = lengths(ii,:); + + h = semilogy( ll ); + hold on; + + cc = h.Color; + indf = find(~isnan(ll),1,'first'); + indl = find(~isnan(ll),1,'last'); + + plot( indf, ll(indf), '.', 'Color', cc ); + plot( indl, ll(indl), 'x', 'Color', cc ); end -end \ No newline at end of file +lsum = nansum(lengths,1); +figure(5); +semilogy( lsum ); +hold on; + + +ind = find(lsum>0,1,'first'); + +figure(6); +semilogy( lsum/lsum(ind),':' ); +hold on; + + +end + + + diff --git a/viz/showSeggerImage.m b/viz/showSeggerImage.m index 5a158ab..7a22b3a 100644 --- a/viz/showSeggerImage.m +++ b/viz/showSeggerImage.m @@ -1,4 +1,4 @@ -function im = showSeggerImage( data, data_r, data_f, FLAGS, clist, CONST, gui_fig) +function [im, im_ptr] = showSeggerImage( data, data_r, data_f, FLAGS, clist, CONST, gui_fig) % showSeggerImage : produces the superSeggerViewer image according to clist and % flags. If the clist has a gate it outlines cells passing the gate. % @@ -64,7 +64,7 @@ return end % fix are any missing flags -FLAGS = intFixFlags( FLAGS ); +FLAGS = fixFlags( FLAGS ); % if there is a clist enables look only cells included in the clist if exist('clist','var') && ~isempty(clist) @@ -83,7 +83,7 @@ [xx,yy] = intGetImSize( data, FLAGS ); mask_full = data.mask_cell; -im = makeIm( data, FLAGS, ID_LIST, CONST ); +im = makeIm( data, FLAGS, ID_LIST, CONST, clist ); if FLAGS.m_flag % mask flag : shows reverse, forward, current, and masked image view if isempty(data_r) @@ -91,7 +91,7 @@ im_r = cat(3,mask_full_r,mask_full_r,mask_full_r); else mask_full_r = data_r.mask_cell; - im_r = makeIm( data_r, FLAGS ); + im_r = makeIm( data_r, FLAGS, [], [], clist ); end if isempty(data_f) @@ -99,7 +99,7 @@ im_f = cat(3,mask_full_f,mask_full_f,mask_full_f); else mask_full_f = data_f.mask_cell; - im_f = makeIm( data_f, FLAGS ); + im_f = makeIm( data_f, FLAGS, [], [], clist ); end im = [im_r(yy,xx,:),im(yy,xx,:); im_f(yy,xx,:), ... @@ -109,10 +109,10 @@ end if isempty(gui_fig) - imshow(im) + im_ptr = imshow(im) else axes(gui_fig); - imshow(im); + im_ptr = imshow(im); FLAGS.axis = axis; end hold on; @@ -172,9 +172,8 @@ function doAnnotation( data_, x_, y_ ) end % plots spots, only if we are at fluorescence view - if FLAGS.f_flag && FLAGS.s_flag && isfield(data_,'CellA') - intPlotSpot( data_, x_, y_, FLAGS, ID_LIST, CONST ); - end + intPlotSpot( data_, x_, y_, FLAGS, ID_LIST, CONST ); + % plots poles if FLAGS.p_flag @@ -222,7 +221,7 @@ function doFrameMerge( x_, y_ ) end -function im = makeIm( data, FLAGS, ID_LIST, CONST ) +function im = makeIm( data, FLAGS, ID_LIST, CONST, clist ) % makeIm puts together the image if data is segmented % but not the text/pole/other labels. % INPUT : @@ -231,10 +230,9 @@ function doFrameMerge( x_, y_ ) % ID_LIST : are the ids of cells selected through a clist % CONST : are the segmentation constants -persistent colormap_; -if isempty( colormap_ ) - colormap_ = colormap( 'jet' ); -end +nc = intGetChannelNum( data ); + + % get the image size ss = size(data.phase); @@ -242,25 +240,8 @@ function doFrameMerge( x_, y_ ) % if the phase image exists use this as the background, else use the cell % masks -phase_level = FLAGS.phase_level; -if isfield(data,'phase') && FLAGS.phase_flag - back = phase_level * ag(data.phase); - im = cat(3,back,back,back); -else - mask = phase_level * ag(~data.mask_cell); - im = cat(3, mask,mask,mask); -end - +im = intMakeMultiChannel( data, FLAGS, CONST, clist, nc ); -% this code highlights the lysed cells -if isfield( data, 'regs' ) && isfield( data.regs, 'lyse' ) && FLAGS.lyse_flag - is_lyse = and( or( data.regs.lyse.errorColor1bCum, ... - data.regs.lyse.errorColor2bCum), data.regs.lyse.errorShapeCum); - lyse_im = intDoOutline2(ismember( ... - data.regs.regs_label,find(is_lyse))); -else - lyse_im = zeros( ss ); -end @@ -268,23 +249,27 @@ function doFrameMerge( x_, y_ ) if FLAGS.composite nc = numel(find(~cellfun('isempty',strfind(fieldnames(data),'fluor')))); for i = 1 : nc - im = updateFluorImage(data, im, i, FLAGS, CONST); + im = updateFluorImage(data, im, i, FLAGS, CONST, clist); end elseif FLAGS.f_flag > 0 im = updateFluorImage(data, im, FLAGS.f_flag, FLAGS, CONST); end + if FLAGS.colored_regions im = label2rgb (data.regs.regs_label, 'lines', 'k'); elseif FLAGS.Outline_flag % it just outlines the cells if FLAGS.cell_flag && isfield(data,'cell_outline') - im(:,:,:) = im(:,:,:) + cat(3,0.4*ag(data.cell_outline),0.4*ag(data.cell_outline),0.5*ag(data.cell_outline)); + %im(:,:,:) = im(:,:,:) + cat(3,0.4*ag(data.cell_outline),0.4*ag(data.cell_outline),0.5*ag(data.cell_outline)); + im = comp( im, {double(data.cell_outline), [0,0,.6]} ); elseif isfield(data,'outline') - im(:,:,:) = im(:,:,:) + cat(3,0.3*ag(data.outline),0.3*ag(data.outline),0.5*ag(data.outline)); + %im(:,:,:) = im(:,:,:) + cat(3,0.3*ag(data.outline),0.3*ag(data.outline),0.5*ag(data.outline)); + im = comp( im, {double(data.outline), [0,0,.6]} ); elseif isfield(data,'mask_cell')% no outline field (not loaded through super segger viewer) data.outline = xor(bwmorph( data.mask_cell,'dilate'), data.mask_cell); - im(:,:,:) = im(:,:,:) + cat(3,0.3*ag(data.outline),0.3*ag(data.outline),0.5*ag(data.outline)); + %im(:,:,:) = im(:,:,:) + cat(3,0.3*ag(data.outline),0.3*ag(data.outline),0.5*ag(data.outline)); + im = comp( im, {double(data.outline), [0,0,.6]} ); end elseif FLAGS.P_flag % if P_flag is true, it shows the regions with color. %% colors : @@ -295,9 +280,10 @@ function doFrameMerge( x_, y_ ) % purple : has error in forward frame % red outlines : dividing or has just divided if ~isfield( data,'regs') || ~isfield( data.regs, 'ID') % no cell ids - seg files - blueChannel = 0.3*(data.mask_cell); - reg_color = uint8( 255*cat(3, 0*blueChannel,blueChannel,blueChannel)); - im = reg_color + im; + + + + im = comp( im, {data.mask_cell, [0,.3,.3]} ); else if isfield( data.regs, 'ignoreError' ) ignoreErrorV = data.regs.ignoreError; @@ -305,81 +291,211 @@ function doFrameMerge( x_, y_ ) ignoreErrorV = 0*data.reg.divide; end + % cells in the ID list and in this region % if v_flag is off, all cells are in is_in_cell_V cells_In_Frame = ismember( data.regs.ID, ID_LIST); cellBorn = or(and(data.regs.birthF,data.regs.stat0),data.regs.divide); - if ~isempty(cells_In_Frame) + if 0 % cells with ehist & error current->reverse or ignoreError map_error_ind = find(and(cells_In_Frame,or(and(data.regs.ehist,... data.regs.error.r),ignoreErrorV))); map_err_rev = double(ismember( data.regs.regs_label, map_error_ind )); + cc1 = [0.35,0,0]; % cells with ehist in this frame, but no error current->reverse or ignoreError map_ehist_in_frame_ind = find(and(cells_In_Frame,or(and(data.regs.ehist,... ~data.regs.error.r),ignoreErrorV))); map_ehist_in_frame = double(ismember( data.regs.regs_label, map_ehist_in_frame_ind )); - + cc2 = [0.55,0,0]; % cells without error history map_no_err_ind = find(and(cells_In_Frame,or(~data.regs.ehist,ignoreErrorV))); map_no_err = double(ismember( data.regs.regs_label, map_no_err_ind)); + cc3 = [0,0.3,0]; % in list, cell was not born in this frame with good division or divided % but stat0==2 : succesfful division was observed map_stat0_2_ind = find(and(cells_In_Frame,data.regs.stat0==2)); map_stat0_2 = double(ismember( data.regs.regs_label,map_stat0_2_ind )); + cc4 = [0,0,0.7]; % outline the ones that were just born with stat0 == 2 map_stat0_2O_ind = find(and(cells_In_Frame,and(cellBorn,data.regs.stat0==2))); map_stat0_2_Outline = intDoOutline2(ismember(data.regs.regs_label, map_stat0_2O_ind)); - + cc5 = [0.35,0,0]; % in list, cell was not born in this frame with good division or divided % stat0==1 : cell was result of succesfful division map_stat0_1_ind = find(and(cells_In_Frame,data.regs.stat0==1)); map_stat0_1 = double( ismember( data.regs.regs_label,map_stat0_1_ind )); + cc6 = [0,0.2,0.6]; % outline the ones that were just born with stat0 == 1 map_stat0_1O_ind = find(and(cells_In_Frame,and(cellBorn,data.regs.stat0==1))); map_stat0_1_Outline = intDoOutline2(ismember(data.regs.regs_label, map_stat0_1O_ind)); - + cc7 = [0.35,0,0]; % in list, cell was not born in this frame with good division or divided % stat0 == 0 : cell has errors, or division not observed map_stat0_0_ind = find(and(cells_In_Frame,data.regs.stat0==0)); map_stat0_0 = double(ismember( data.regs.regs_label, map_stat0_0_ind )); + cc8 = [0,0.2,0.3]; % outline the ones that were just born with stat0 == 1 map_stat0_0O_ind = find(and(cells_In_Frame,and(cellBorn,data.regs.stat0==0))); map_stat0_0_Outline = intDoOutline2(ismember(data.regs.regs_label, map_stat0_0O_ind)); + cc9 = [0.35,0,0]; - redChannel = double(lyse_im)+0.5*(0.7*(map_err_rev)+1.1*(map_ehist_in_frame)+.7*(map_stat0_2_Outline+map_stat0_1_Outline +map_stat0_0_Outline)); - greenChannel = 0.3*(map_no_err) - 0.2*(map_stat0_1)+0.2*(map_stat0_0); - blueChannel = 0.7*(map_stat0_2)+ 0.6*(map_stat0_1)+0.3*(map_stat0_0); + + tic + im = comp( im, {map_err_rev, cc1},... + {map_ehist_in_frame, cc2},... + {map_no_err, cc3},... + {map_stat0_2, cc4},... + {map_stat0_2_Outline, cc5},... + {map_stat0_1, cc6},... + {map_stat0_1_Outline, cc7},... + {map_stat0_0, cc8},... + {map_stat0_0_Outline, cc9}); + + toc - reg_color = uint8( 255*cat(3, redChannel,greenChannel,blueChannel)); - im = reg_color + im; + else + %tic + if ~isempty(cells_In_Frame) + % cells with ehist & error current->reverse or ignoreError + map_error_ind = find(and(cells_In_Frame,or(and(data.regs.ehist,... + data.regs.error.r),ignoreErrorV))); + map_err_rev = double(ismember( data.regs.regs_label, map_error_ind )); + + % cells with ehist in this frame, but no error current->reverse or ignoreError + map_ehist_in_frame_ind = find(and(cells_In_Frame,or(and(data.regs.ehist,... + ~data.regs.error.r),ignoreErrorV))); + map_ehist_in_frame = double(ismember( data.regs.regs_label, map_ehist_in_frame_ind )); + + + % cells without error history + map_no_err_ind = find(and(cells_In_Frame,or(~data.regs.ehist,ignoreErrorV))); + map_no_err = double(ismember( data.regs.regs_label, map_no_err_ind)); + + % in list, cell was not born in this frame with good division or divided + % but stat0==2 : succesfful division was observed + map_stat0_2_ind = find(and(cells_In_Frame,data.regs.stat0==2)); + map_stat0_2 = double(ismember( data.regs.regs_label,map_stat0_2_ind )); + + % outline the ones that were just born with stat0 == 2 + map_stat0_2O_ind = find(and(cells_In_Frame,and(cellBorn,data.regs.stat0==2))); + map_stat0_2_Outline = intDoOutline2(ismember(data.regs.regs_label, map_stat0_2O_ind)); + + + % in list, cell was not born in this frame with good division or divided + % stat0==1 : cell was result of succesfful division + map_stat0_1_ind = find(and(cells_In_Frame,data.regs.stat0==1)); + map_stat0_1 = double( ismember( data.regs.regs_label,map_stat0_1_ind )); + + % outline the ones that were just born with stat0 == 1 + map_stat0_1O_ind = find(and(cells_In_Frame,and(cellBorn,data.regs.stat0==1))); + map_stat0_1_Outline = intDoOutline2(ismember(data.regs.regs_label, map_stat0_1O_ind)); + + + % in list, cell was not born in this frame with good division or divided + % stat0 == 0 : cell has errors, or division not observed + map_stat0_0_ind = find(and(cells_In_Frame,data.regs.stat0==0)); + map_stat0_0 = double(ismember( data.regs.regs_label, map_stat0_0_ind )); + + % outline the ones that were just born with stat0 == 1 + map_stat0_0O_ind = find(and(cells_In_Frame,and(cellBorn,data.regs.stat0==0))); + map_stat0_0_Outline = intDoOutline2(ismember(data.regs.regs_label, map_stat0_0O_ind)); + + + + redChannel = 0.5*(0.7*(map_err_rev)+1.1*(map_ehist_in_frame)+.7*(map_stat0_2_Outline+map_stat0_1_Outline +map_stat0_0_Outline)); + greenChannel = 0.3*(map_no_err) - 0.2*(map_stat0_1)+0.2*(map_stat0_0); + blueChannel = 0.7*(map_stat0_2)+ 0.6*(map_stat0_1)+0.3*(map_stat0_0); + + reg_color = uint8( 255*cat(3, redChannel,greenChannel,blueChannel)); + + im = reg_color + im; + end + %toc end + + end end end -function im = updateFluorImage(data, im, channel, FLAGS, CONST) + +% function im = updateFluorImage(data, im, channel, FLAGS, CONST) +% +% fluorName = ['fluor',num2str(channel)]; +% +% fluorName = ['fluor',num2str(channel)]; +% flbgName = ['fl',num2str(channel),'bg']; +% if isfield(data, fluorName ) +% +% +% if ~isfield (CONST.view,'fluorColor') +% CONST.view.fluorColor = {'g','r','b'}; +% end +% +% curColor = getRGBColor( CONST.view.fluorColor{channel}); +% +% if FLAGS.filt && isfield( data, [fluorName,'_filtered'] ) +% fluor_tmp = data.([fluorName,'_filtered']); +% else +% fluor_tmp = data.(fluorName); +% if isfield( data, 'fl1bg' ) +% fluor_tmp = fluor_tmp - data.(flbgName); +% fluor_tmp( fluor_tmp< 0 ) = 0; +% else +% fluor_tmp = fluor_tmp-mean(fluor_tmp(:)); +% fluor_tmp( fluor_tmp< 0 ) = 0; +% end +% end +% +% if isfield( CONST.view, 'LogView' ) && CONST.view.LogView && ~FLAGS.composite +% fluor_tmp = ag( double(fluor_tmp).^.6 ); +% end +% +% +% minner = medfilt2( fluor_tmp, [2,2], 'symmetric' ); +% maxxer = max( minner(:)); +% minner = min( minner(:)); +% if CONST.view.falseColorFlag +% im = im + doColorMap( ag(fluor_tmp,minner,maxxer), uint8(255*jet(256)) ); +% else +% imFluor = 0.8*ag(fluor_tmp,minner,maxxer); +% im(:,:,1) = im(:,:,1) + curColor(1) * imFluor; +% im(:,:,2) = im(:,:,2) + curColor(2) * imFluor; +% im(:,:,3) = im(:,:,3) + curColor(3) * imFluor; +% end +% +% +% end +% end + +function im = updateFluorImage(data, im, channel, FLAGS, CONST, clist) + + fluorName = ['fluor',num2str(channel)]; flbgName = ['fl',num2str(channel),'bg']; + if isfield(data, fluorName ) + + if ~isfield (CONST.view,'fluorColor') CONST.view.fluorColor = {'g','r','b'}; end - curColor = getRGBColor( CONST.view.fluorColor{channel}); + cc = CONST.view.fluorColor{channel}; - if FLAGS.filt && isfield( data, [fluorName,'_filtered'] ) + if FLAGS.filt(channel) && isfield( data, [fluorName,'_filtered'] ) fluor_tmp = data.([fluorName,'_filtered']); else fluor_tmp = data.(fluorName); @@ -392,21 +508,26 @@ function doFrameMerge( x_, y_ ) end end - if isfield( CONST.view, 'LogView' ) && CONST.view.LogView && ~FLAGS.composite - fluor_tmp = ag( double(fluor_tmp).^.6 ); - end + + if ~FLAGS.filt(channel) && ... + isfield( clist, 'imRangeGlobal' ) && ... + isempty( clist.imRangeGlobal ) && ... + FLAGS.gbl_auto(channel+1) + + minner = clist.imRangeGlobal( 1, channel+1 ); + maxxer = clist.imRangeGlobal( 2, channel+1 ); - minner = medfilt2( fluor_tmp, [2,2], 'symmetric' ); - maxxer = max( minner(:)); - minner = min( minner(:)); - if CONST.view.falseColorFlag - im = im + doColorMap( ag(fluor_tmp,minner,maxxer), uint8(255*jet(256)) ); + else + minner = medfilt2( fluor_tmp, [2,2], 'symmetric' ); + maxxer = max( minner(:)); + minner = min( minner(:)); + end + + if CONST.view.falseColorFlag && ~FLAGS.composite + im = comp( im, {fluor_tmp,[minner,maxxer],jet(256)} ); else - imFluor = 0.8*ag(fluor_tmp,minner,maxxer); - im(:,:,1) = im(:,:,1) + curColor(1) * imFluor; - im(:,:,2) = im(:,:,2) + curColor(2) * imFluor; - im(:,:,3) = im(:,:,3) + curColor(3) * imFluor; + im = comp( im, {fluor_tmp,[minner,maxxer],FLAGS.level(channel+1),cc} ); end @@ -527,59 +648,73 @@ function intPlotSpot( data, x_, y_, FLAGS, ID_LIST, CONST ) channel_num = FLAGS.f_flag; locus_name = ['locus',num2str(channel_num)]; -min_score_name = (['FLUOR',num2str(channel_num),'_MIN_SCORE']); -if ~isfield(CONST.getLocusTracks,min_score_name) - CONST.getLocusTracks.(min_score_name) = 3; -end -min_score = CONST.getLocusTracks.(min_score_name); +nc = intGetChannelNum( data ); -if isfield( data, 'CellA' ) && ~isempty( data.CellA ) && isfield(data.CellA{1},locus_name) - counter = 0; - maxCounter = 500; - locus_txt = {}; - locus_x = []; - locus_y = []; - for kk = 1:data.regs.num_regs - % only plot spots in the cell that are gated. - if (~FLAGS.cell_flag || ismember(data.regs.ID(kk), ID_LIST)) - if isfield( data.CellA{kk},(locus_name)) - locus_field = data.CellA{kk}.(locus_name); - num_spot = numel(locus_field); - mm = 0; - while mm < num_spot && counter < maxCounter - mm = mm + 1; - r = locus_field(mm).r; - text_ = [num2str(locus_field(mm).score, '%0.1f')]; +if isfield( data, 'CellA' ) && ~isempty( data.CellA ) + + + + ind = find( FLAGS.s_flag ); + + for jj = ind; + + counter1 = 0; + maxCounter1 = 500; + locus_1_txt = {}; + locus1_x = []; + locus1_y = []; + + for kk = 1:data.regs.num_regs + % only plot spots in the cell that are gated. + if (~FLAGS.cell_flag || ismember(data.regs.ID(kk), ID_LIST)) + + + + + % locus + locusName = [ 'locus',num2str(jj)']; + + if isfield( data.CellA{kk},locusName ) + num_spot = numel( data.CellA{kk}.(locusName)); + mm = 0; - if isfield (locus_field(mm),'score') && locus_field(mm).score > 1 %min_score - xpos = r(1)+x_; - ypos = r(2)+y_; - if (FLAGS.axis(1)xpos) && ... - (FLAGS.axis(3)ypos) - counter = counter + 1; - txt = ['-s:',num2str(locus_field(mm).score, '%0.1f')]; - if isfield (locus_field(mm),'score') - txt = ['-in:',num2str(locus_field(mm).normIntensity, '%0.1f'),txt]; - end - if isfield (locus_field(mm),'normIntensityScore') - txt = ['-is:',num2str(locus_field(mm).normIntensityScore, '%0.1f'),txt]; - end - if isfield (locus_field(mm),'intensity') - txt = ['-i:',num2str(locus_field(mm).intensity, '%0.1f'),txt]; + while mm < num_spot && counter1 < maxCounter1 + mm = mm + 1; + r = data.CellA{kk}.(locusName)(mm).r; + text_ = [num2str(data.CellA{kk}.(locusName)(mm).score, '%0.1f')]; + + scoreName = [ 'FLUOR',num2str(jj),'_MIN_SCORE']; + if ~isfield( CONST.getLocusTracks, scoreName ) + CONST.getLocusTracks.(scoreName) = 0; + end + + if data.CellA{kk}.(locusName)(mm).score > CONST.getLocusTracks.(scoreName) + xpos = r(1)+x_; + ypos = r(2)+y_; + if (FLAGS.axis(1)xpos) && ... + (FLAGS.axis(3)ypos) + counter1 = counter1 + 1; + locus_1_txt{end+1} = [num2str(data.CellA{kk}.(locusName)(mm).score, ... + '%0.1f')]; + locus1_x = [locus1_x;xpos]; + locus1_y = [locus1_y;ypos]; end - locus_txt{end+1} = txt; - locus_x = [locus_x;xpos]; - locus_y = [locus_y;ypos]; end end + + + if FLAGS.scores_flag(jj) + text( locus1_x+1, locus1_y, locus_1_txt, 'Color',CONST.view.fluorColor{jj} ); + end + plot( locus1_x, locus1_y, '.', 'Color',CONST.view.fluorColor{jj} ); + end end end + end - text( locus_x+1, locus_y, locus_txt, 'Color', [1,1,1]); - plot( locus_x, locus_y, '.', 'Color', [1,1,1]); - + end end @@ -815,108 +950,7 @@ function intPlotPole( data, x_, y_,FLAGS ) end end -function FLAGS = intFixFlags( FLAGS ) -% intFixFlags : sets default flag values if the value is missing. -% Outline_flag -% ID_flag -% lyse_flag -% m_flag -% c_flag - -if ~isfield(FLAGS, 'legend') - disp('there is no flag legend'); - FLAGS.legend = 1; -end - -if ~isfield(FLAGS, 'Outline_flag') - disp('there is no flag Outline_flag'); - FLAGS.Outline_flag = 0; -end -if ~isfield(FLAGS, 'ID_flag') - disp('there is no flag ID_flag'); - FLAGS.ID_flag = 1; -end - -if ~isfield(FLAGS, 'lyse_flag') - disp('there is no flag lyse_flag') - FLAGS.lyse_flag = 0; -end - -if ~isfield(FLAGS,'m_flag') - disp('there is no flag m_flag') - FLAGS.m_flag = 0; -end - -if ~isfield(FLAGS, 'c_flag') - disp('there is no flag c_flag') - FLAGS.c_flag = 0; -end - -if ~isfield(FLAGS, 'P_flag') - disp('there is no flag P_flag') - FLAGS.P_flag = 1; -end - -if ~isfield(FLAGS, 'phase_flag') - disp('there is no flag phase_flag') - FLAGS.phase_flag = 1; -end - -if ~isfield(FLAGS, 'phase_level') - disp('there is no flag phase_level') - FLAGS.phase_level = 1; -end - -if ~isfield(FLAGS, 'cell_flag' ) - disp('there is no flag cell_flag') - FLAGS.cell_flag = 0; -end - -if ~isfield(FLAGS, 'f_flag') - disp('there is no flag f_flag') - FLAGS.f_flag = 0; -end - -if ~isfield(FLAGS, 's_flag') - disp('there is no flag s_flag') - FLAGS.s_flag = 0; -end - -if ~isfield(FLAGS, 'T_flag') - disp('there is no flag T_flag') - FLAGS.T_flag = 0; -end - -if ~isfield(FLAGS, 'filt') - disp('there is no flag filt') - FLAGS.filt = [0,0,0]; -end - -if ~isfield(FLAGS, 'p_flag') - disp('there is no field p_flag') - FLAGS.p_flag = 0; -end - -if ~isfield(FLAGS,'composite') - disp('there is no flag composite') - FLAGS.composite = 0; -end - - -if ~isfield(FLAGS, 'showLinks') - disp('there is no flag showLinks') - FLAGS.showLinks = 0; -end - -if ~isfield(FLAGS, 'colored_regions') - disp('there is no flag colored_regions') - FLAGS.colored_regions = 0; -end - -FLAGS.link_flag = FLAGS.s_flag || FLAGS.ID_flag; - -end function outline = intDoOutline(map) persistent sqrStrel; @@ -933,4 +967,9 @@ function intPlotPole( data, x_, y_,FLAGS ) sqrStrel = strel('square',3); end outline = double(imdilate( map, sqrStrel ))-double(map); -end \ No newline at end of file +end + + + + + diff --git a/viz/superSeggerViewer.m b/viz/superSeggerViewer.m index 9f473c0..509b1d7 100644 --- a/viz/superSeggerViewer.m +++ b/viz/superSeggerViewer.m @@ -110,7 +110,8 @@ function superSeggerViewer(dirname) end if exist([dirname0,'CONST.mat'],'file') - CONST = load([dirname0,'CONST.mat']); + %CONST = load([dirname0,'CONST.mat']); + CONST = loadConstantsFile( [dirname0,'CONST.mat'] ); if isfield( CONST, 'CONST' ) CONST = CONST.CONST; end @@ -594,7 +595,7 @@ function superSeggerViewer(dirname) if ~isempty( data_cell ) figure(2); clf; - im_tmp = makeFrameMosaic(data_cell, CONST, xdim__); + im_tmp = makeFrameMosaic(data_cell, CONST, xdim__,[],[],FLAGS.filt)); end end @@ -612,7 +613,7 @@ function superSeggerViewer(dirname) if ~isempty( data_cell ) figure(2); clf; - makeKymographC(data_cell, 1, CONST,[],FLAGS.filt); + makeKymographC(data_cell, 1, CONST,[],FLAGS); ylabel('Long Axis (pixels)'); xlabel('Time (frames)' ); disp('Press enter to continue'); diff --git a/viz/superSeggerViewerGui.fig b/viz/superSeggerViewerGui.fig index 6e67aec..1284cb3 100644 Binary files a/viz/superSeggerViewerGui.fig and b/viz/superSeggerViewerGui.fig differ diff --git a/viz/superSeggerViewerGui.m b/viz/superSeggerViewerGui.m index 76ac705..43d65d7 100644 --- a/viz/superSeggerViewerGui.m +++ b/viz/superSeggerViewerGui.m @@ -238,8 +238,14 @@ function initImage(hObject, handles) % Not updated handles.cell_poles.Value = FLAGS.p_flag; handles.legend_box.Value = FLAGS.legend; handles.outline_cells.Value = FLAGS.Outline_flag; -handles.fluor_foci_scores.Value = FLAGS.s_flag; -handles.filtered_fluorescence.Value = FLAGS.filt; +handles.foci_box.Value = FLAGS.s_flag; +handles.scores_foci.Value = FLAGS.scores_flag; + +if FLAGS.f_flag + handles.filt.Value = FLAGS.filt(FLAGS.f_flag); +else + handles.filt.Value = 0; +end handles.region_outlines.Value = FLAGS.P_flag; handles.region_scores.Value = FLAGS.regionScores; handles.use_seg_files.Value = FLAGS.useSegs; @@ -254,13 +260,16 @@ function initImage(hObject, handles) % Not updated else handles.go_to_frame_no.String = '1'; end - +handles.autoscale.Value = FLAGS.autoscale; handles.kymograph_cell_no.String = ''; handles.movie_cell_no.String = ''; handles.cell_no.String = ''; handles.max_cell_no.String = ''; handles.find_cell_no.String = ''; +handles.channel_color.String = {'r','m','y','g','c','b','w'}; + + handles.contents = dir([handles.dirname_seg, file_filter]); handles.contents_seg = dir([handles.dirname_seg, '*seg.mat']); handles.num_seg = length(handles.contents_seg); @@ -275,7 +284,8 @@ function initImage(hObject, handles) % Not updated handles.use_seg_files.Value = FLAGS.useSegs; if exist([dirname0, 'CONST.mat'], 'file') - CONST = load([dirname0, 'CONST.mat']); + %CONST = load([dirname0, 'CONST.mat']); + CONST = loadConstantsFile( [dirname0,'CONST.mat'] ); if isfield(CONST, 'CONST') CONST = CONST.CONST; end @@ -296,12 +306,29 @@ function initImage(hObject, handles) % Not updated handles.filename_flags = filename_flags; handles.FLAGS.f_flag = 0; handles.channel.String = 0; -handles.go_to_frame_no_text.String = ['Go to frame # (max ' num2str(handles.num_im) ')']; +handles.go_to_frame_no_text.String = ['Time (frames) max: ', num2str(handles.num_im)]; update_clist_panel(hObject, handles) handles = updateOutputPanel (handles); handles = updateImage(hObject, handles); guidata(hObject, handles); +c = FLAGS.f_flag; +if c == 0 + handles.color.String = ''; + handles.min_score.String = ''; +else + handles.color.String = CONST.view.fluorColor{c}; + + scoreName = [ 'FLUOR',num2str(c),'_MIN_SCORE']; + + if isfield( CONST.getLocusTracks, scoreName ) + handles.min_score.String = num2str(CONST.getLocusTracks.(scoreName) ); + else + handles.min_score.String = ''; + end +end + + function handles = updateImage(hObject, handles) delete(get(handles.axes1, 'Children')) handles.previous.Enable = 'off'; @@ -349,7 +376,13 @@ function initImage(hObject, handles) % Not updated delete(findall(findall(gcf, 'Type', 'axe'), 'Type', 'text')) [handles.data_r, handles.data_c, handles.data_f] = intLoadDataViewer(handles.dirname_seg, handles.contents, ... nn, handles.num_im, handles.clist, forcedFlags); - showSeggerImage(handles.data_c, handles.data_r, handles.data_f, forcedFlags, handles.clist, handles.CONST, handles.axes1); + [~,im_ptr] = showSeggerImage(handles.data_c, handles.data_r, handles.data_f, forcedFlags, handles.clist, handles.CONST, handles.axes1); + set(im_ptr,'ButtonDownFcn',{@clickOnImageInfo,handles} ); + + + intShowLUT( handles ); + + try save(handles.filename_flags, 'FLAGS', 'nn', 'dirnum' ); catch @@ -364,11 +397,22 @@ function initImage(hObject, handles) % Not updated makeActive(handles.use_seg_files); end + makeActive(handles.autoscale) + if handles.num_seg == 0 handles.use_seg_files.Enable = 'off'; end - handles.switch_xy_directory_text.String = ['Switch xy (', num2str(handles.num_xy), ')']; + %handles.switch_xy_directory_text.String = ['Switch xy (', num2str(handles.num_xy), ')']; + for kk = 1:handles.num_xy + handles.xy_popup.String{kk} = num2str(kk); + end + + nc = intGetChannelNum(handles.data_c); + for kk = 0:nc + handles.channel_popup.String{kk+1} = num2str(kk); + end + f = 0; while true if isfield(handles,'data_c') && isfield(handles.data_c, ['fluor' num2str(f+1)] ) @@ -378,20 +422,17 @@ function initImage(hObject, handles) % Not updated end end handles.channel_text.String = ['Channel (', num2str(f), ')']; - if handles.FLAGS.f_flag >= 1 && ~handles.FLAGS.composite% Fluorescence + if handles.FLAGS.f_flag >= 1 %&& ~handles.FLAGS.composite% Fluorescence makeActive(handles.log_view); makeActive(handles.false_color); if shouldUseErrorFiles(handles.FLAGS, handles.canUseErr) - makeActive(handles.fluor_foci_scores); - makeActive(handles.filtered_fluorescence); + makeActive(handles.foci_box); else - makeInactive(handles.fluor_foci_scores); - makeInactive(handles.filtered_fluorescence); + makeInactive(handles.foci_box); end else makeInactive(handles.log_view); - makeInactive(handles.fluor_foci_scores); - makeInactive(handles.filtered_fluorescence); + makeInactive(handles.foci_box); makeInactive(handles.false_color); end if shouldUseErrorFiles(handles.FLAGS, handles.canUseErr) @@ -508,6 +549,15 @@ function previous_Callback(hObject, eventdata, handles) go_to_frame_no_Callback(hObject, eventdata, handles); end + +function save_CONST_Callback(hObject, eventdata, handles) +if ~isempty(handles.FLAGS) + CONST = handles.CONST; + + save( [handles.dirname0,'CONST.mat'], '-STRUCT', 'CONST' ); +end + + function max_cell_no_Callback(hObject, eventdata, handles) handles.CONST.view.maxNumCell = round(str2double(handles.max_cell_no.String)); handles.max_cell_no.String = num2str(round(str2double(handles.max_cell_no.String))); @@ -567,21 +617,6 @@ function switch_xy_directory_CreateFcn(hObject, eventdata, handles) % Display options -function channel_Callback(hObject, eventdata, handles) -if ~isempty(handles.FLAGS) - f = 0; - while isfield(handles,'data_c') && isfield(handles.data_c, ['fluor' num2str(f+1)] ) - f = f+1; - end - c = round(str2double(handles.channel.String)); - if isnan(c) || c < 0 || c > f - handles.channel.String = '0'; - else - handles.channel.String = num2str(c); - end - handles.FLAGS.f_flag = c; - updateImage(hObject, handles); -end function channel_CreateFcn(hObject, eventdata, handles) if ispc && isequal(get(hObject, 'BackgroundColor'), get(0, 'defaultUicontrolBackgroundColor')) @@ -596,6 +631,9 @@ function find_cell_no_Callback(hObject, eventdata, handles) function find_cell_no(handles) if ~isempty(handles.FLAGS) + + axes( handles.axes1 ); + c = round(str2double(handles.find_cell_no.String)); maxIndex = handles.data_c.regs.num_regs; if areCellsLoaded(handles) @@ -608,6 +646,7 @@ function find_cell_no(handles) if handles.FLAGS.cell_flag && shouldUseErrorFiles(handles.FLAGS, handles.canUseErr) regnum = find(handles.data_c.regs.ID == c); if ~isempty(regnum) + plot(handles.data_c.regs.props(regnum).Centroid(1),... handles.data_c.regs.props(regnum).Centroid(2),'yx','MarkerSize',50); else @@ -674,26 +713,48 @@ function false_color_Callback(hObject, eventdata, handles) updateImage(hObject, handles); end -function filtered_fluorescence_Callback(hObject, eventdata, handles) +function gbl_auto_Callback(hObject, eventdata, handles) if ~isempty(handles.FLAGS) - handles.FLAGS.filt = handles.filtered_fluorescence.Value; - handles.CONST.view.filtered = handles.filtered_fluorescence.Value; + + chan = handles.FLAGS.f_flag; + + handles.FLAGS.gbl_auto(chan+1) = handles.gbl_auto.Value; updateImage(hObject, handles); end -function fluor_foci_scores_Callback(hObject, eventdata, handles) +function filt_Callback(hObject, eventdata, handles) if ~isempty(handles.FLAGS) - handles.FLAGS.s_flag = handles.fluor_foci_scores.Value; + + channel = handles.FLAGS.f_flag; + handles.FLAGS.filt(channel) = handles.filt.Value; + handles.CONST.view.filtered = handles.filt.Value; updateImage(hObject, handles); end +function foci_box_Callback(hObject, eventdata, handles) +if ~isempty(handles.FLAGS) + + chan = handles.FLAGS.f_flag; + handles.FLAGS.s_flag(chan) = handles.foci_box.Value; + updateImage(hObject, handles); +end + +function fluor_scores_Callback(hObject, eventdata, handles) +if ~isempty(handles.FLAGS) + + chan = handles.FLAGS.f_flag; + + handles.FLAGS.scores_flag(chan) = handles.scores_foci.Value; + updateImage(hObject, handles); +end + + function log_view_Callback(hObject, eventdata, handles) if ~isempty(handles.FLAGS) - if ~isfield( handles.CONST, 'view' ) || ~isfield( handles.CONST.view, 'LogView' ) || isempty( handles.CONST.view.LogView ) - handles.CONST.view.LogView = true; - else - handles.CONST.view.LogView = handles.log_view.Value; - end + + chan = handles.FLAGS.f_flag; + + handles.FLAGS.log_view(chan) = handles.log_view.Value; updateImage(hObject, handles); end @@ -737,6 +798,21 @@ function use_seg_files_Callback(hObject, eventdata, handles) end end +function manual_lut_Callback(hObject, eventdata, handles) +if ~isempty(handles.FLAGS) + chan = handles.FLAGS.f_flag; + handles.FLAGS.manual_lut(chan+1) = handles.manual_lut.Value; + updateImage(hObject, handles); +end + +function level_Callback(hObject, eventdata, handles) +if ~isempty(handles.FLAGS) + chan = handles.FLAGS.f_flag; + handles.FLAGS.level(chan+1) = str2double(handles.level.String); + updateImage(hObject, handles); +end + + % Gate options function clear_gates_Callback(hObject, eventdata, handles) @@ -772,11 +848,111 @@ function histogram_clist_Callback(hObject, eventdata, handles) gateHist(handles.clist, handles.histogram_clist.Value); end + +function channel_color_Callback(hObject, eventdata, handles) +if ~isempty(handles.FLAGS) + chan = handles.FLAGS.f_flag; + if chan + handles.CONST.view.fluorColor{chan} = ... + handles.channel_color.String{handles.channel_color.Value}; + updateImage(hObject, handles); + + end + +end + +function channel_popup_Callback(hObject, eventdata, handles) +if ~isempty(handles.FLAGS) + + nc = intGetChannelNum( handles.data_c ); + + c = handles.channel_popup.Value-1; + + if c == 0 + handles.color_popup.Value = 1; + handles.min_score.String = ''; + + else + handles.channel_color.Value = ... + intGetColorValue(handles.CONST.view.fluorColor{c}, ... + handles.channel_color.String ); + + scoreName = [ 'FLUOR',num2str(c),'_MIN_SCORE']; + + if isfield( handles.CONST.getLocusTracks, scoreName ) + handles.min_score.String = num2str(handles.CONST.getLocusTracks.(scoreName) ); + else + handles.min_score.String = ''; + end + end + + handles.FLAGS.f_flag = c; + updateImage(hObject, handles); +end + +function xy_popup_Callback(hObject, eventdata, handles) +if ~isempty(handles.FLAGS) + ll_ = handles.xy_popup.Value; + dirname0 = handles.dirname0; + if isnumeric(ll_) + + if ~isempty(ll_) && (ll_ >= 1) && (ll_ <= handles.num_xy) + try + clist = handles.clist; + if ~isempty(clist) + save( [dirname0,handles.contents_xy(handles.dirnum).name,filesep,'clist.mat'],'-STRUCT','clist'); + end + catch ME + printError(ME); + handles.message.String = 'Error writing clist file'; + end + handles.dirnum = ll_; + handles.dirname_seg = [dirname0,handles.contents_xy(ll_).name,filesep,'seg',filesep]; + handles.dirname_cell = [dirname0,handles.contents_xy(ll_).name,filesep,'cell',filesep]; + handles.dirname_xy = [dirname0,handles.contents_xy(ll_).name,filesep]; + ixy = sscanf( handles.contents_xy(handles.dirnum).name, 'xy%d' ); + handles.header = ['xy',num2str(ixy),': ']; + handles.contents = dir([handles.dirname_seg, '*seg.mat']); + handles.num_im = numel(handles.contents); + enable_all_panels(hObject,handles) + if exist([dirname0,handles.contents_xy(ll_).name,filesep,'clist.mat']) + handles.clist = load([dirname0,handles.contents_xy(ll_).name,filesep,'clist.mat']); + update_clist_panel(hObject, handles) + else + handles.clist = [] + update_clist_panel(hObject, handles) + end + updateImage(hObject, handles); + else + handles.message.String = 'Incorrect number for xy position'; + end + else + handles.message.String = 'Number of xy position missing'; + end +end +guidata(hObject, handles); + function histogram_clist_CreateFcn(hObject, eventdata, handles) if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) set(hObject,'BackgroundColor','white'); end +function channel_color_CreateFcn(hObject, eventdata, handles) +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + +function channel_popup_CreateFcn(hObject, eventdata, handles) +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + +function xy_popup_CreateFcn(hObject, eventdata, handles) +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + function make_gate_Callback(hObject, eventdata, handles) if ~isempty(handles.FLAGS) figure(2); @@ -1051,7 +1227,8 @@ function phase_flag_Callback(hObject, eventdata, handles) % Hint: get(hObject,'Value') returns toggle state of phase_flag if ~isempty(handles.FLAGS) - handles.FLAGS.phase_flag = get(hObject,'Value'); + chan = handles.FLAGS.f_flag; + handles.FLAGS.phase_flag(chan+1) = get(hObject,'Value'); updateImage(hObject, handles); end @@ -1063,11 +1240,82 @@ function phase_level_txt_Callback(hObject, eventdata, handles) % Hints: get(hObject,'String') returns contents of phase_level_txt as text % str2double(get(hObject,'String')) returns contents of phase_level_txt as a double if ~isempty(handles.FLAGS) - handles.FLAGS.phase_level = str2double(get(hObject,'String')); + handles.FLAGS.level(handles.FLAGS.f_flag+1) = str2double(get(hObject,'String')); updateImage(hObject, handles); end +function lut_min_Callback(hObject, eventdata, handles) +% hObject handle to phase_level_txt (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'String') returns contents of phase_level_txt as text +% str2double(get(hObject,'String')) returns contents of phase_level_txt as a double +if ~isempty(handles.FLAGS) + handles.FLAGS.lut_min(handles.FLAGS.f_flag+1) = str2double(get(hObject,'String')); + updateImage(hObject, handles); +end + +function lut_max_Callback(hObject, eventdata, handles) +% hObject handle to phase_level_txt (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'String') returns contents of phase_level_txt as text +% str2double(get(hObject,'String')) returns contents of phase_level_txt as a double +if ~isempty(handles.FLAGS) + handles.FLAGS.lut_max(handles.FLAGS.f_flag+1) = str2double(get(hObject,'String')); + updateImage(hObject, handles); +end + + +function min_score_Callback(hObject, eventdata, handles) +% hObject handle to phase_level_txt (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'String') returns contents of phase_level_txt as text +% str2double(get(hObject,'String')) returns contents of phase_level_txt as a double +if ~isempty(handles.FLAGS) + + chan = handles.FLAGS.f_flag; + if chan + scoreName = [ 'FLUOR',num2str(chan),'_MIN_SCORE']; + + tmp = str2double(get(hObject,'String')); + handles.CONST.getLocusTracks.(scoreName) = tmp; + updateImage(hObject, handles); + end + +end + +function color_Callback(hObject, ~, handles) +% hObject handle to phase_level_txt (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: get(hObject,'String') returns contents of phase_level_txt as text +% str2double(get(hObject,'String')) returns contents of phase_level_txt as a double +if ~isempty(handles.FLAGS) + + chan = handles.FLAGS.f_flag; + if chan + + tmp = get(hObject,'String'); + + if iscell( tmp ) + tmp = tmp{1}; + end + + if ~isempty( tmp ) && ischar( tmp(1) ) + handles.CONST.view.fluorColor{chan} = tmp(1); + updateImage(hObject, handles); + end + end + +end + % --- Executes during object creation, after setting all properties. function phase_level_txt_CreateFcn(hObject, eventdata, handles) % hObject handle to phase_level_txt (see GCBO) @@ -1094,6 +1342,20 @@ function composite_Callback(hObject, eventdata, handles) end +% --- Executes on button press in composite. +function include_Callback(hObject, eventdata, handles) +% hObject handle to composite (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hint: get(hObject,'Value') returns toggle state of composite +if ~isempty(handles.FLAGS) + handles.FLAGS.include(handles.FLAGS.f_flag+1) = get(hObject,'Value') ; + updateImage(hObject, handles); +end + + + % --- Executes on button press in region_ids. function region_ids_Callback(hObject, eventdata, handles) % hObject handle to region_ids (see GCBO) @@ -1121,7 +1383,9 @@ function region_ids_Callback(hObject, eventdata, handles) {'Field Movie'},0,0; {'Field Mosaic'},0,0; {'Consensus'},1,0; - {'Consensus Kymo'},1,0]; + {'Outline figure'},1,0; + {'Consensus Kymo'},1,0; + {'Cell Info'},1,0]; @@ -1144,7 +1408,7 @@ function output_list_Callback(hObject, eventdata, handles) errordlg('No cell files found'); else figure(2); - im = makeKymoMosaic( handles.dirname_cell, handles.CONST ); + im = makeKymoMosaic( handles.dirname_cell, handles.CONST, handles.FLAGS ); if handles.save_output.Value savename = [handles.dirSave, 'mosaic_kymograph']; save (savename, 'im'); @@ -1153,6 +1417,8 @@ function output_list_Callback(hObject, eventdata, handles) end elseif strcmp('Cell Tower',value) makeCellTower(handles); + elseif strcmp('Outline figure',value) + makeOutlineFigure(handles); elseif strcmp('Cell Tower Mosaic',value) cell_tower_mosaic(handles); elseif strcmp('Lineage',value) @@ -1167,29 +1433,76 @@ function output_list_Callback(hObject, eventdata, handles) makeLineage( handles.clist, ids, min_width ); end elseif strcmp('Field Movie',value) - makeFieldMovie(handles); + makeFieldMovie(hObject,handles); elseif strcmp('Field Mosaic',value) handles = field_mosaic( handles) elseif strcmp('Consensus',value); handles = consensus_image(handles) elseif strcmp('Consensus Kymo',value) handles = consensus_kymo(handles); + elseif strcmp('Cell Info',value) + handles = cell_info(hObject, eventdata, handles); end end set(hObject, 'UserData', get(hObject, 'Value')); % for double click selection -function cell_info_Callback(hObject, eventdata, handles) -global settings; -state = get(hObject,'Value'); -if state == get(hObject,'Max') - settings.hObject = hObject; - settings.handles = handles; - settings.function = 'cell_info'; - settings.eventdata = eventdata; - set(handles.axes1.Children, 'ButtonDownFcn', @clickOnImage); -elseif state == get(hObject,'Min') - updateImage(hObject, handles); +function handles = cell_info(hObject, eventdata, handles) +% global settings; +% state = get(hObject,'Value'); +% if state == get(hObject,'Max') +% settings.hObject = hObject; +% settings.handles = handles; +% settings.function = 'cell_info'; +% settings.eventdata = eventdata; +% set(handles.axes1.Children, 'ButtonDownFcn', @clickOnImage); +% elseif state == get(hObject,'Min') +% updateImage(hObject, handles); +% + ii = []; + +if ~isempty( handles.cell_no.String ) + cell_num = str2num(handles.cell_no.String); + if (cell_num) + if isfield( handles, 'data_c' ) + if isfield( handles.data_c, 'regs' ) + if isfield( handles.data_c.regs, 'ID' ) + reg_num = find( handles.data_c.regs.ID == cell_num ); + + if ~isempty( reg_num ) + ii = reg_num(1); + else + errordlg( 'reg number is empty' ); + end + else + errordlg( 'no ID field' ); + end + else + errordlg( 'no regs field' ); + end + + else + errordlg( 'no data_c field.' ); + end + else + errordlg( 'cell number isnt valid.' ); + end +else + errordlg('Please enter a cell number.' ); +end + +if ~isempty( ii ) + if isfield(handles.data_c,'CellA') + disp(['Pole orientation : ', num2str(handles.data_c.CellA{ii}.pole.op_ori)]); + disp(['BoundingBox : ', num2str(handles.data_c.CellA{ii}.BB)]); + disp(['Axis Lengths : ', num2str(handles.data_c.CellA{ii}.length)]); + disp(['Cell Length : ', num2str(handles.data_c.CellA{ii}.cellLength(1))]); + disp(['Mean Width : ', num2str(handles.data_c.CellA{ii}.cellLength(2))]); + disp(['Cell distance : ', num2str(handles.data_c.CellA{ii}.cell_dist)]); + disp(['Cell Old Pole Age : ', num2str( handles.data_c.CellA{ii}.pole.op_age)]); + disp(['Cell New Pole Age : ', num2str(handles.data_c.CellA{ii}.pole.np_age)]); + end + end function handles = consensus_kymo(handles) @@ -1260,7 +1573,7 @@ function makeCellKymo(handles) if ~isempty( data_cell ) figure(2); clf; - makeKymographC(data_cell, 1, handles.CONST,[]); + makeKymographC(data_cell, 1, handles.CONST,handles.FLAGS); title(cell_name); ylabel('Long Axis (pixels)'); xlabel('Time (frames)' ); @@ -1285,7 +1598,7 @@ function intMakeCellMovie(handles) if ~isempty(data_cell) handles.message.String = ['Movie for cell ', cell_name]; - mov = makeCellMovie(data_cell); + mov = makeCellMovie(data_cell, handles.CONST, handles.FLAGS, handles.clist); choice = questdlg('Save movie?', 'Save movie?', 'Yes', 'No', 'No'); if strcmp(choice, 'Yes') saveFilename = [handles.dirSave,cell_name(1:end-4),'.avi']; @@ -1301,33 +1614,60 @@ function intMakeCellMovie(handles) end -function handles = makeCellTower( handles) -if ~areCellsLoaded(handles) - errordlg('No cell files found'); -else - if ~isempty(handles.FLAGS) - c = str2double(handles.cell_no.String); - if numel(c) > 1 - c = c(1); + + + function hanldes = makeCellTower( handles) + if ~areCellsLoaded(handles) + errordlg('No cell files found'); + else + % if ~isempty(handles.FLAGS) + c = str2num(handles.cell_no.String); + if numel(c) > 1 + c = c(1); + end + if isempty(c) || isnan(c) || c < 1 || c > max(handles.data_c.regs.ID) + handles.message.String = ['Invalid cell number']; + else + + handles.cell_no.String = num2str(c); + xdim = 4; %str2double(handles.no_columns.String); + [data_cell,cell_name] = loadCellData(c, handles.dirname_cell, handles); + if ~isempty( data_cell ) + handles.message.String = ['Cell Tower for cell ', cell_name]; + figure(2); + clf; + %makeFrameMosaic(data_cell, handles.CONST, xdim); + makeFrameMosaic(data_cell, handles.CONST, xdim,[],[],handles.FLAGS); + title(cell_name); + end + end end - if isempty(c) || isnan(c) || c < 1 || c > max(handles.data_c.regs.ID) - handles.message.String = ['Invalid cell number']; + + function hanldes = makeOutlineFigure( handles) + if ~areCellsLoaded(handles) + errordlg('No cell files found'); else - - handles.cell_no.String = num2str(c); - xdim = 4; %str2double(handles.no_columns.String); - [data_cell,cell_name] = loadCellData(c, handles.dirname_cell, handles); - if ~isempty( data_cell ) - handles.message.String = ['Cell Tower for cell ', cell_name]; + % if ~isempty(handles.FLAGS) + + if isfield(handles, 'data_c' ) + + tmp_axis = axis; + figure(2); clf; - makeFrameMosaic(data_cell, handles.CONST, xdim); - title(cell_name); + axis(tmp_axis); + + showSeggerImage( handles.data_c, [], [], handles.FLAGS, handles.clist, handles.CONST, [] ); + + clist_tmp = gate( handles.clist ); + ID_LIST = clist_tmp.data(:,1); + + doDrawCellOutlinePAW( handles.data_c, ID_LIST ); + else + errordlg('No data_c field found'); end end - end -end - + function [startFr,endFr,skip] = dialogBoxStartEndSkip (handles) prompt = {'Start frame:', 'End frame:','Choose Total # frames :','or Skip Frames :'}; @@ -1414,15 +1754,18 @@ function intMakeCellMovie(handles) -function makeFieldMovie(handles) +function makeFieldMovie(hObject,handles) % makes field movie if ~isempty(handles.FLAGS) + tmp = handles.go_to_frame_no.String; + clear mov; [startFr,endFr,skip] = dialogBoxStartEndSkip (handles); if ~isempty(startFr) mov.cdata = []; mov.colormap = []; counter = 1; + for ii = round(startFr:skip: endFr) delete(get(handles.axes1, 'Children')) [data_r, data_c, data_f] = intLoadDataViewer( handles.dirname_seg, ... @@ -1447,6 +1790,9 @@ function makeFieldMovie(handles) end end end + + handles.go_to_frame_no.String = tmp; + updateImage(hObject, handles); end @@ -1454,7 +1800,8 @@ function cell_tower_mosaic(handles) if ~isempty(handles.FLAGS) && areCellsLoaded(handles) figure(2); clf; - imTot = makeFrameStripeMosaic([handles.dirname_cell], handles.CONST, [], true); + imTot = makeFrameStripeMosaic([handles.dirname_cell], ... + handles.CONST, [], true, handles.clist, handles.FLAGS ); if handles.save_output.Value save ([handles.dirSave,'tower_cells'],'imTot'); end @@ -1519,4 +1866,140 @@ function edit_links_Callback(hObject, eventdata, handles) setappdata(0, 'dirname_cell', handles.dirname_cell); setappdata(0, 'nn', str2double(handles.go_to_frame_no.String)); editLinks(); -end \ No newline at end of file +end + +function ind = intGetColorValue( str, lib ); + ind = find(strcmp(lib , str)); + + +function intShowLUT( handles ) + + handles.FLAGS.phase_flag = double(logical(handles.FLAGS.phase_flag)); + + % do the show lut stuff + chan = handles.FLAGS.f_flag; + if chan == 0 + im = handles.data_c.phase; + cc = 'w'; + else + im = handles.data_c.(['fluor',num2str(chan)]); + cc = handles.CONST.view.fluorColor{chan}; + end + + axes(handles.lut_show ) + [y,x] = hist( double(im(:)), 100 ); + plot( x,y, '.', 'Color', cc ); + set(gca, 'Yscale', 'log', 'Color', [0,0,0] ); + + % now set everything in the channel pannel + handles.include.Value = handles.FLAGS.include(chan+1); + handles.level.String = num2str(handles.FLAGS.level(chan+1)); + handles.lut_min.String = num2str(handles.FLAGS.lut_min(chan+1)); + handles.lut_max.String = num2str(handles.FLAGS.lut_max(chan+1)); + handles.manual_lut.Value = handles.FLAGS.manual_lut(chan+1); + handles.phase_flag.Value = handles.FLAGS.phase_flag(chan+1); + handles.gbl_auto.Value = handles.FLAGS.gbl_auto(chan+1); + + + if chan == 0 + makeInactive(handles.channel_color); + makeInactive(handles.phase_flag); + makeInactive(handles.log_view); + makeInactive(handles.false_color); + makeInactive(handles.foci_box); + makeInactive(handles.scores_foci); + makeInactive(handles.min_score); + makeInactive(handles.filt); + + handles.foci_box.Value = 0; + handles.scores_foci.Value = 0; + handles.min_score.String = ''; + handles.log_view.Value = 0; + + else + makeActive(handles.channel_color); + makeActive(handles.phase_flag); + makeActive(handles.log_view); + + handles.log_view.Value = handles.FLAGS.log_view(chan); + + filtname = ['fluor',num2str(chan),'_filtered']; + if isfield( handles.data_c, filtname ); + makeActive(handles.filt); + handles.filt.Value = handles.FLAGS.filt(chan); + else + makeInactive(handles.filt); + handles.filt.Value = 0; + handles.FLAGS.filt(chan) = 0; + end + + + makeActive(handles.false_color); + + filtname = ['locus',num2str(chan)]; + if isfield( handles.data_c.CellA{1}, filtname ); + makeActive(handles.foci_box); + makeActive(handles.scores_foci); + makeActive(handles.min_score); + + handles.channel_color.Value = ... + intGetColorValue(handles.CONST.view.fluorColor{chan}, ... + handles.channel_color.String ); + + handles.foci_box.Value = handles.FLAGS.s_flag(chan); + handles.scores_foci.Value = handles.FLAGS.scores_flag(chan); + + scoreName = [ 'FLUOR',num2str(chan),'_MIN_SCORE']; + + + if ~isfield( handles.CONST.getLocusTracks, scoreName ) + handles.CONST.getLocusTracks.(scoreName) = 0; + end + + handles.min_score.String = num2str(handles.CONST.getLocusTracks.(scoreName)); + else + makeInactive(handles.foci_box); + handles.foci_box.Value = 0; + handles.FLAGS.s_flag(chan) = 0; + + makeInactive(handles.scores_foci); + handles.scores_foci.Value = 0; + handles.FLAGS.scores_flag(chan) = 0; + + makeInactive(handles.min_score); + handles.min_score.String = ''; + end + + end + + + +function ImageClickCallback ( objectHandle , eventData ) + axesHandle = get(objectHandle,'Parent'); + coordinates = get(axesHandle,'CurrentPoint'); + coordinates = coordinates(1,1:2); + message = sprintf('x: %.1f , y: %.1f',coordinates (1) ,coordinates (2)); + helpdlg(message); + + +function clickOnImageInfo(hObject, eventdata, handles) + point = round(eventdata.IntersectionPoint(1:2)); + + reg_num = handles.data_c.regs.regs_label( point(2), point(1) ); + + if reg_num + cell_num = handles.data_c.regs.ID( reg_num ); + else + cell_num = 0; + end + + handles.message.String = ['Cell number: ',num2str(cell_num),... + ' Region number: ',num2str(reg_num)]; + + if cell_num + handles.cell_no.String = num2str( cell_num ); + end + + + +