Home > SuperSegger > cell > trackOptiMakeCell.m

trackOptiMakeCell

PURPOSE ^

trackOptiMakeCell : generates the CellA field indexed by the region number

SYNOPSIS ^

function trackOptiMakeCell(dirname,CONST,header)

DESCRIPTION ^

 trackOptiMakeCell : generates the CellA field indexed by the region number
 which contains information about each cell in each region in each frame.

 It goes through the dirname/*err.mat files and computes the characteristics of the
 cells in each frame and puts them in the CellA structure that is indexed
 by the region number, not the cell ID. This code figures out the pole
 age and also computes statistics on the fluorescence channels as
 well as fitting the locus positions. These last two features are
 controlled by parameters set in the loadConstants.m or
 loadConstantsMine.m files.

 data.CellA{1}.
           mask        : logical (1 and 0) cell mask, unoriented
             r_offset    : location of cell in full image from top left corner
             BB          : coordinates of cell bounding box, containing the
             cell and the pad
             edgeFlag    : if the cell is on the edge of the image (bad)
             phase        : the cropped phase image of the cell
             coord        : coordinates, area, and orientation, see below
             length        : (1) length and (2) width of the cell
             pole        : orientation of the cell pole, see below
             fluor1        : the 1st fluor channel image
             fuor1mm     : min and max of fluor1
             fl1         : statistics of fluor1, e.g. background level
             fluor2        : the 2nd fluor channel image
             fluor2mm    : min and max of fluor2
             fl2         : statistics of fluor2
             cell_dist    : distance to the edge of the colony
             gray        : average phase gray value in cell region
             locus1        : If focus fitting was run, data on the fit
             (locations, score..), see below
             locus2        : Same as above for channel 2
             r           : global coordinates of cell centroid (mid-point of cell)
             error        : segmentation error list
             ehist        : ehist is the sum of all errors in the region?s history
           contactHist    : ?
           stat0        : stat0 flag that is true if the cell is born without error
 
 The coord field contains a lot of cell specific info:
 data.CellA{1}.coord =
         A: Area of cell mask
         r_center: geometrical center of the cell
         box: coordinates of box surrounding cell
         xaxis: coordinates of major axis
         yaxis: coordinates of minor axis
         I: Moment of inertia of cell mask
         e1: priniple axis (major) unit vector
         e2: priniple axis (minor) unit vector
         rcm: center of mass position of mask
 
 The pole field contains info pertaining to the cell pole and pole ages:
 data.CellA{1}.pole =
        e1: major axis direction.
        op_ori: 1 if old pole is in direction of e1
             -1 if old pole is in opposite e1
        op_age: age of old pole in cell cycles
             NaN if no birth is observed
        np_age: age of new pole in cell cycles
 
 The locus field contains info from locus fitting - if it ran.
 data.CellA{1}.locus1(1) =
       r: Spot position in global coords
       score: score from spot fit.
       intensity: raw intensity
       b: spot width from fit
       shortaxis: Locus position in local coords (short axis)
       longaxis: Spot position in local coords (long axis)

 INPUT :
       dirname: seg folder eg. maindirectory/xy1/seg
       CONST: are the segmentation constants.
       header : string displayed with information

 Copyright (C) 2016 Wiggins Lab 
 Written by Stella Stylianidou & 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 <http://www.gnu.org/licenses/>.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function trackOptiMakeCell(dirname,CONST,header)
0002 % trackOptiMakeCell : generates the CellA field indexed by the region number
0003 % which contains information about each cell in each region in each frame.
0004 %
0005 % It goes through the dirname/*err.mat files and computes the characteristics of the
0006 % cells in each frame and puts them in the CellA structure that is indexed
0007 % by the region number, not the cell ID. This code figures out the pole
0008 % age and also computes statistics on the fluorescence channels as
0009 % well as fitting the locus positions. These last two features are
0010 % controlled by parameters set in the loadConstants.m or
0011 % loadConstantsMine.m files.
0012 %
0013 % data.CellA{1}.
0014 %           mask        : logical (1 and 0) cell mask, unoriented
0015 %             r_offset    : location of cell in full image from top left corner
0016 %             BB          : coordinates of cell bounding box, containing the
0017 %             cell and the pad
0018 %             edgeFlag    : if the cell is on the edge of the image (bad)
0019 %             phase        : the cropped phase image of the cell
0020 %             coord        : coordinates, area, and orientation, see below
0021 %             length        : (1) length and (2) width of the cell
0022 %             pole        : orientation of the cell pole, see below
0023 %             fluor1        : the 1st fluor channel image
0024 %             fuor1mm     : min and max of fluor1
0025 %             fl1         : statistics of fluor1, e.g. background level
0026 %             fluor2        : the 2nd fluor channel image
0027 %             fluor2mm    : min and max of fluor2
0028 %             fl2         : statistics of fluor2
0029 %             cell_dist    : distance to the edge of the colony
0030 %             gray        : average phase gray value in cell region
0031 %             locus1        : If focus fitting was run, data on the fit
0032 %             (locations, score..), see below
0033 %             locus2        : Same as above for channel 2
0034 %             r           : global coordinates of cell centroid (mid-point of cell)
0035 %             error        : segmentation error list
0036 %             ehist        : ehist is the sum of all errors in the region?s history
0037 %           contactHist    : ?
0038 %           stat0        : stat0 flag that is true if the cell is born without error
0039 %
0040 % The coord field contains a lot of cell specific info:
0041 % data.CellA{1}.coord =
0042 %         A: Area of cell mask
0043 %         r_center: geometrical center of the cell
0044 %         box: coordinates of box surrounding cell
0045 %         xaxis: coordinates of major axis
0046 %         yaxis: coordinates of minor axis
0047 %         I: Moment of inertia of cell mask
0048 %         e1: priniple axis (major) unit vector
0049 %         e2: priniple axis (minor) unit vector
0050 %         rcm: center of mass position of mask
0051 %
0052 % The pole field contains info pertaining to the cell pole and pole ages:
0053 % data.CellA{1}.pole =
0054 %        e1: major axis direction.
0055 %        op_ori: 1 if old pole is in direction of e1
0056 %             -1 if old pole is in opposite e1
0057 %        op_age: age of old pole in cell cycles
0058 %             NaN if no birth is observed
0059 %        np_age: age of new pole in cell cycles
0060 %
0061 % The locus field contains info from locus fitting - if it ran.
0062 % data.CellA{1}.locus1(1) =
0063 %       r: Spot position in global coords
0064 %       score: score from spot fit.
0065 %       intensity: raw intensity
0066 %       b: spot width from fit
0067 %       shortaxis: Locus position in local coords (short axis)
0068 %       longaxis: Spot position in local coords (long axis)
0069 %
0070 % INPUT :
0071 %       dirname: seg folder eg. maindirectory/xy1/seg
0072 %       CONST: are the segmentation constants.
0073 %       header : string displayed with information
0074 %
0075 % Copyright (C) 2016 Wiggins Lab
0076 % Written by Stella Stylianidou & Paul Wiggins.
0077 % University of Washington, 2016
0078 % This file is part of SuperSegger.
0079 %
0080 % SuperSegger is free software: you can redistribute it and/or modify
0081 % it under the terms of the GNU General Public License as published by
0082 % the Free Software Foundation, either version 3 of the License, or
0083 % (at your option) any later version.
0084 %
0085 % SuperSegger is distributed in the hope that it will be useful,
0086 % but WITHOUT ANY WARRANTY; without even the implied warranty of
0087 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0088 % GNU General Public License for more details.
0089 %
0090 % You should have received a copy of the GNU General Public License
0091 % along with SuperSegger.  If not, see <http://www.gnu.org/licenses/>.
0092 
0093 if ~exist('header','var')
0094     header = [];
0095 end
0096 
0097 if(nargin<1 || isempty(dirname))
0098     dirname = '.';
0099 end
0100 dirname = fixDir(dirname);
0101 
0102 verbose = CONST.parallel.verbose;
0103 
0104 % Get the track/error file names
0105 contents=dir([dirname '*_err.mat']);
0106 num_im = numel(contents);
0107 
0108 if CONST.parallel.show_status
0109     h = waitbar( 0, 'Making Cells.');
0110     cleanup = onCleanup( @()( delete( h ) ) );
0111 else
0112     h = [];
0113 end
0114 
0115 % loop through all the cells.
0116 for i = 1:num_im;
0117     
0118     if (i ==1) && (1 == num_im) % snapshots
0119         data_r = [];
0120         data_c = loaderInternal([dirname,contents(i).name]);
0121         data_f = [];
0122     elseif i == 1; % first frame
0123         data_r = [];
0124         data_c = loaderInternal([dirname,contents(i).name]);
0125         data_f = loaderInternal([dirname,contents(i+1).name]);        
0126     elseif i==num_im; % last frame
0127         data_r = loaderInternal([dirname,contents(i-1).name]);
0128         data_c = loaderInternal([dirname,contents(i).name]);        
0129         data_f = [];
0130     else
0131         data_r = loaderInternal([dirname,contents(i-1).name]);
0132         data_c = loaderInternal([dirname,contents(i).name]);
0133         data_f = loaderInternal([dirname,contents(i+1).name]);
0134     end
0135     
0136     % first frame, find the total number of channels
0137     if i==1
0138         nc = 0;
0139         tmp_fn = fieldnames( data_c );
0140         nf = numel( tmp_fn );
0141         for j = 1:nf;
0142             if numel(strfind(tmp_fn{j},'fluor')==1)&& ~numel((strfind(tmp_fn{j},'fluor0')))
0143                 nc = nc+1;
0144             end
0145         end
0146     end
0147     
0148     % set min max of fluorescence
0149     for j = 1:nc
0150         tmp = getfield( data_c,['fluor',num2str(j)]);
0151         ff(j,:) = [min(tmp(:)),max(tmp(:))];
0152     end
0153     
0154     % make the cell array holding the cells that has one element for each
0155     % region.
0156     data_c.CellA = cell(1,data_c.regs.num_regs);
0157     dist_mask = makeColonyDist( data_c.mask_bg );
0158     
0159     for ii = 1:data_c.regs.num_regs
0160         % Cut out a region with pixel pad size PAD_SIZE.
0161         celld = struct();
0162         PAD_SIZE = 5;
0163         ss = size(data_c.phase);
0164         
0165         celld.cellLength = [data_c.regs.L1(ii),data_c.regs.L2(ii)];
0166         [xx,yy]  = getBBpad( data_c.regs.props(ii).BoundingBox, ss, PAD_SIZE);
0167         celld.xx = xx;
0168         celld.yy = yy;
0169         celld.mask  = logical(data_c.regs.regs_label(yy,xx)==ii);
0170         celld.r_offset = [xx(1),yy(1)];
0171         celld.BB  = [xx(1),yy(1),xx(end)-xx(1),yy(end)-yy(1)];
0172         tmpEdge = [ ceil(data_c.regs.props(ii).BoundingBox(1)),...
0173             ceil(data_c.regs.props(ii).BoundingBox(2)),...
0174             floor(sum(data_c.regs.props(ii).BoundingBox([1,3]))),...
0175             floor(sum(data_c.regs.props(ii).BoundingBox([2,4])))];
0176         celld.edgeFlag = any( tmpEdge == [1,1,ss(2),ss(1)]);
0177         
0178         % copy information from regions
0179         if CONST.trackOpti.NEIGHBOR_FLAG
0180             celld.contactHist = data_c.regs.contactHist(ii);
0181         end
0182         
0183         
0184         % record the number of cell neighbors
0185         if CONST.trackOpti.NEIGHBOR_FLAG
0186             nei_ = numel(trackOptiNeighbors(data_c,ii));
0187             data_c.regs.numNeighbors{ii} = nei_ ;
0188             celld.numNeighbors = nei_ ;
0189         end
0190         
0191         celld.phase     = data_c.phase(yy,xx);
0192         
0193         % Keep track of pole age and what direction the old pole is in.
0194         if isempty(data_r) || isempty(data_c.regs.map.r{ii})
0195             celld             = toMakeCell(celld,[],data_c.regs.props(ii));
0196             celld.pole.e1     = celld.coord.e1;            
0197             celld.pole.op_ori =   0;
0198             celld.pole.op_age = NaN;
0199             celld.pole.np_age = NaN;
0200         else
0201             if data_c.regs.error.r(ii)
0202                 try
0203                     celld = toMakeCell(celld, data_r.CellA{data_c.regs.map.r{ii}(1)}.pole.e1,data_c.regs.props(ii));
0204                 catch ME
0205                     printError(ME);
0206                 end
0207                 celld.pole.e1     = celld.coord.e1;
0208                 celld.pole.op_ori =   0;
0209                 celld.pole.op_age = NaN;
0210                 celld.pole.np_age = NaN;
0211                 
0212             elseif data_c.regs.birthF(ii) && ( data_c.regs.sisterID(ii) ) && ~isempty(find( data_c.regs.sisterID(ii) == data_c.regs.ID ))
0213                 
0214                 cell_old = data_r.CellA{data_c.regs.map.r{ii}(1)};                
0215                 celld  = toMakeCell(celld, cell_old.pole.e1,data_c.regs.props(ii));
0216                 celld.pole.e1 = celld.coord.e1;
0217                 e1 = celld.pole.e1;
0218                 op_ori = cell_old.pole.op_ori;
0219 
0220                 jj = find( data_c.regs.sisterID(ii) == data_c.regs.ID );
0221                 jj = jj(1);
0222                 rs = data_c.regs.props(jj).Centroid;
0223                 r0 = data_c.regs.props(ii).Centroid;
0224                 
0225                 dr = (r0-rs)*e1;                
0226                 celld.pole.op_ori = sign(dr);
0227                 
0228                 if celld.pole.op_ori == cell_old.pole.op_ori
0229                     celld.pole.op_age = cell_old.pole.op_age+1;
0230                 else
0231                     celld.pole.op_age = cell_old.pole.np_age+1;
0232                 end
0233                 
0234                 celld.pole.np_age = 1;
0235                 
0236                 debug_flag = 0;
0237                 if debug_flag
0238                     clf;
0239                     kk = find( data_c.regs.motherID(ii) == data_r.ID );
0240                     imshow( 0.5*cat(3, ag(data_c.regs.regs_label==jj), ag(data_c.regs.regs_label==ii),ag(data_r.regs_label==kk)));
0241                     hold on;
0242                     
0243                     tmp = celld;
0244                     r = tmp.coord.r_center;
0245                     xaxisx = r(1) + [0,tmp.length(1)*tmp.coord.e1(1)]/2;
0246                     xaxisy = r(2) + [0,tmp.length(1)*tmp.coord.e1(2)]/2;
0247                     yaxisx = r(1) + [0,tmp.length(2)*tmp.coord.e2(1)]/2;
0248                     yaxisy = r(2) + [0,tmp.length(2)*tmp.coord.e2(2)]/2;
0249                     old_pole = r + tmp.length(1)*tmp.coord.e1'*tmp.pole.op_ori/2;
0250                     new_pole = r - tmp.length(1)*tmp.coord.e1'*tmp.pole.op_ori/2;
0251                     
0252                     plot( r(1), r(2), 'g.');
0253                     plot( xaxisx, xaxisy, 'g-');
0254                     plot( yaxisx, yaxisy, 'g-');
0255                     plot( old_pole(1), old_pole(2), 'r.');
0256                     plot( new_pole(1), new_pole(2), 'w.');
0257                     
0258                     tmp = data_r.CellA{kk};
0259                     r = tmp.coord.r_center;
0260                     r = tmp.coord.r_center;
0261                     xaxisx = r(1) + [0,tmp.length(1)*tmp.coord.e1(1)]/2;
0262                     xaxisy = r(2) + [0,tmp.length(1)*tmp.coord.e1(2)]/2;
0263                     yaxisx = r(1) + [0,tmp.length(2)*tmp.coord.e2(1)]/2;
0264                     yaxisy = r(2) + [0,tmp.length(2)*tmp.coord.e2(2)]/2;
0265                     old_pole = r + tmp.length(1)*tmp.coord.e1'*tmp.pole.op_ori/2;
0266                     new_pole = r - tmp.length(1)*tmp.coord.e1'*tmp.pole.op_ori/2;
0267                     
0268                     plot( r(1), r(2), 'g.');
0269                     plot( xaxisx, xaxisy, 'g-');
0270                     plot( yaxisx, yaxisy, 'g-');
0271                     if ~tmp.pole.op_ori
0272                         plot( old_pole(1), old_pole(2), 'r.');
0273                         plot( new_pole(1), new_pole(2), 'w.');
0274                     end
0275                 end
0276             else
0277                 if (data_c.regs.map.r{ii}(1) == 0)
0278                     data_c.regs.map.r{ii}(1) = [];
0279                 end
0280                 celld  = toMakeCell(celld, data_r.CellA{data_c.regs.map.r{ii}(1)}.pole.e1,data_c.regs.props(ii));
0281                 celld.pole = data_r.CellA{data_c.regs.map.r{ii}(1)}.pole;
0282                 celld.pole.e1 = celld.coord.e1;
0283             end
0284         end
0285         
0286         
0287         % copy fluorescence fields, compute fluorescence statistics and find loci
0288         for j = 1:nc
0289             tmp   = data_c.(['fluor',num2str(j)]);
0290             celld.(['fluor',num2str(j)]) = tmp(yy,xx);
0291             celld.(['fluor',num2str(j),'mm']) = ff(j,:) ;
0292             
0293             if isfield( CONST.trackLoci, 'fluorFlag' ) && CONST.trackLoci.fluorFlag
0294                 tmp = trackOptiCellFluor( tmp(yy,xx), celld.mask, celld.r_offset);
0295             else
0296                 tmp = [];
0297             end       
0298             tmp.bg = data_c.(['fl',num2str(j),'bg']);
0299             celld.(['fl',num2str(j)]) = tmp;
0300             
0301         end
0302         
0303         % compute the distance to the edge of the colony
0304         if data_c.regs.ID(ii)
0305             
0306             [xx,yy]        = getBBpad( data_c.regs.props(ii).BoundingBox, ss, 0);
0307             mask_cell      = logical(data_c.regs.regs_label(yy,xx)==ii);
0308             dist_mask_crop = dist_mask(yy,xx);
0309             cell_dist      = min(dist_mask_crop(mask_cell));
0310             celld.cell_dist = cell_dist;
0311             
0312             % calculate average phase gray value in cell region
0313             celld.gray = mean(double(celld.phase(celld.mask)));
0314             
0315         end
0316         
0317         data_c.CellA{ii} = celld;
0318         
0319     end
0320     
0321     % save the updated err files.
0322     dataname = [dirname,contents(i).name];
0323     save(dataname,'-STRUCT','data_c');
0324     
0325     if CONST.parallel.show_status
0326         waitbar(i/num_im,h,['Making Cells--Frame: ',num2str(i),'/',num2str(num_im)]);
0327     elseif verbose
0328         disp([header, 'MakeCell frame: ',num2str(i),' of ',num2str(num_im)]);
0329     end
0330 end
0331 
0332 if CONST.parallel.show_status
0333     close(h);
0334 end
0335 
0336 end
0337 
0338 function data = loaderInternal(filename)
0339 data = load( filename );
0340 end

Generated on Thu 19-Jan-2017 13:55:21 by m2html © 2005