diff --git a/matlab/+Batch/batchFeatures.m b/matlab/+Batch/batchFeatures.m new file mode 100644 index 0000000000000000000000000000000000000000..623c22e5bbfbed6b583edad4f150b1b0b93f3f4d --- /dev/null +++ b/matlab/+Batch/batchFeatures.m @@ -0,0 +1,47 @@ +function batchFeatures(conn,CONSTANTS,nProcessors) + +algorithms=Read.getAlgorithms(conn,'feature'); +if isempty(algorithms) + return +end +segParams=Read.getSegmentationParams(conn); +CONSTANTS=CellFeatures.resetFeatures(conn,CONSTANTS,algorithms); + +if ~exist('nProcessors','var') || isempty(nProcessors) + nProcessors=feature('numcores'); +end +p=gcp('nocreate'); +if isempty(p) || p.NumWorkers~=nProcessors + delete(p); + p=[]; +end +if isempty(p) + p=parpool(nProcessors); +end + +strDB=conn.DataSource; +for iAlgorithm=1:length(algorithms) + tNext=1; + for idp=1:ceil(CONSTANTS.imageData.NumberOfFrames/p.NumWorkers) + featureTable=Composite(); + spmd + tTarget=tNext+labindex-1; % labIndex is 1 based + if tTarget<=CONSTANTS.imageData.NumberOfFrames + cx=openDB(strDB); + featureTable=algorithms(iAlgorithm).function(cx,tTarget,CONSTANTS,algorithms(iAlgorithm).params,segParams); + close(cx); + else + featureTable=[]; + end + end + for i=1:length(featureTable) + if ~isempty(featureTable{i}) + CellFeatures.writeFeatureTable(conn,featureTable{i}); + end + end + tNext=tNext+p.NumWorkers; + end + +end + +4; \ No newline at end of file diff --git a/matlab/+Batch/processMovie.m b/matlab/+Batch/processMovie.m index 5e342bef44bb4959cb98abb0085b8c7495c9d8e1..a2ccae63f9d6677cce4f03a1135b15608f584021 100644 --- a/matlab/+Batch/processMovie.m +++ b/matlab/+Batch/processMovie.m @@ -22,5 +22,8 @@ tx=tic(); Smooth.Classify.goClassifyMitosis(conn,CONSTANTS); Smooth.extFamily(conn); tProcess.tClassify=toc(tx); +tx=tic(); +Batch.batchFeatures(conn,CONSTANTS); +tProcess.tFeatures=toc(); close(conn) diff --git a/matlab/+CellFeatures/cytoToNuclearRatio.m b/matlab/+CellFeatures/cytoToNuclearRatio.m index c589c19762cbf643481ef4fc3660ab1bb159f137..a80c2d40d3489f43eab67efdb9f18b9b13571b4e 100644 --- a/matlab/+CellFeatures/cytoToNuclearRatio.m +++ b/matlab/+CellFeatures/cytoToNuclearRatio.m @@ -1,105 +1,57 @@ -function cytoToNuclearRatio(conn,CONSTANTS,args,t) +function tblCellFeatures=cytoToNuclearRatio(conn,t,CONSTANTS,featureParams,segParams) + +tblCellFeatures=table(); params.channel=1; params.name='CytoToNuclearRatio'; params.color="#00ffff"; % check for param override -params=Segment.getParams(params,args); - -% segmentation params -- for min radius -algs=Read.getAlgorithms(conn,'segment'); -args=algs.params; -segParams=Segment.getDefaultSegParams(); -segParams=Segment.getParams(segParams,args); - -rgRadius=Ensemble.getEnsembleRadius(segParams.minimumRadius_um); -resolution_um=CONSTANTS.imageData.PixelPhysicalSize; % um per pixel -min_radius_pixels = rgRadius ./ resolution_um(1); - -% todo -- handle anistropy in 3d! +featureParams=Segment.getParams(params,featureParams); -cmd=['select cellID from tblCells where time=' num2str(t)]; -q=ljsFetch(conn,cmd); -cellIDs=cell2mat(q); -if isempty(cellIDs) - return +cellFeatures=[]; +cellList=Read.getCellsTime(conn,t); +if isempty(cellList) + return; end +cellList=Read.setCellsIdxPts(cellList,CONSTANTS); + im = MicroscopeData.Reader('imageData',CONSTANTS.imageData, 'chanList',... - params.channel,'timeRange',[t t], 'outType','single','prompt',false); + featureParams.channel,'timeRange',[t t], 'outType','single','prompt',false); if all(isnan(im(:))) return; end is3d=size(im,3)>1; labelCells=0*im; dInterior=labelCells; -for i=1:length(cellIDs) - if is3d - c=Read.getCell3D(conn,cellIDs(i)); - idx=sub2ind(size(im),c.pts(:,2),c.pts(:,1),c.pts(:,3)); - else - c=Read.getCell(conn,cellIDs(i)); - idx=sub2ind(size(im),c.pts(:,2),c.pts(:,1)); - end +for i=1:length(cellList) + idx=cellList(i).idxPts; bwInterior=logical(0*im); bwInterior(idx)=1; + % we need bwdist for just this cell bwd=bwdist(~bwInterior); + % isolated bwdist put in combo image, indexed by labelCells dInterior=dInterior+bwd; - labelCells(idx)=c.cellID; + labelCells(idx)=cellList(i).cellID; end % find region surrounding segmentation [dExterior,idxd]=bwdist(labelCells); - -for i=1:length(rgRadius) - li=labelCells; - lo=labelCells(idxd); - radius=rgRadius(i); - lo(dExterior>radius)=0; - % should this be 0, or min_radius_pixels? i.e. buffer between? - lo(dInterior>=radius)=0; - li(dInterior<radius)=0; - - labelOuter(:,:,:,i)=lo; - labelInner(:,:,:,i)=li; -end - -for i=1:length(cellIDs) - if is3d - c=Read.getCell3D(conn,cellIDs(i)); - else - c=Read.getCell(conn,cellIDs(i)); - end - if isfield(c,'segCC') - iRadius=c.segCC-floor(c.segCC); - if 0==iRadius - iRadius=1; - else - prec=ceil(log10(length(rgRadius)+1));% # of digits in the radius tag - iRadius=iRadius*10^prec; - iRadius=int32(iRadius); - end - else - iRadius=1; - end +% +for i=1:length(cellList) - idxInner=find(labelInner(:,:,:,iRadius)==c.cellID); - idxOuter=find(labelOuter(:,:,:,iRadius)==c.cellID); + % interior pixels > 2 pixels from cell surface + idxInner = find( labelCells==cellList(i).cellID & dInterior>=2); + % pixels <=2 pixels from cell surface + idxInteriorBoundary=find( labelCells==cellList(i).cellID & dInterior<2); + % exterior pixels nearest to this cell + idxExterior=idxd(find( labelCells(idxd)==cellList(i).cellID & dExterior<=3 & dExterior>0)); + idxOuter=[idxInteriorBoundary;idxExterior]; ratio=getErkRatio(im,idxOuter,idxInner); - if isnan(ratio) - cmd=['delete from tblCellFeatures where cellID=' num2str(cellIDs(i))]; - exec(conn,cmd); - else - ratio=round(ratio,4); - cmd=['insert or ignore into tblCellFeatures(cellID) values (' ... - num2str(cellIDs(i)) ')']; - exec(conn,cmd); - cmd=['update tblCellFeatures set ' params.name '=' num2str(ratio) ... - ' where cellID=' num2str(cellIDs(i))]; - exec(conn,cmd); - end - + cellFeatures=[cellFeatures;cellList(i).cellID,ratio]; end - +tblCellFeatures.cellID=cellFeatures(:,1); +tblCellFeatures.(featureParams.name)=cellFeatures(:,2); +4; function ratio=getErkRatio(im,idxOuter,idxInner) ratio=NaN; diff --git a/matlab/+CellFeatures/netIntensity.m b/matlab/+CellFeatures/netIntensity.m index a8cff5b68f015a486288f4fe04fb8b1bd55b4d21..528fc86a1c67576c1a881e3c02e49bf871d8871b 100644 --- a/matlab/+CellFeatures/netIntensity.m +++ b/matlab/+CellFeatures/netIntensity.m @@ -1,30 +1,31 @@ -function netIntensity(conn,CONSTANTS,args,t) + +function tblCellFeatures=netIntensity(conn,t,CONSTANTS,featureParams,segParams) + +tblCellFeatures=table(); +cellFeatures=[]; params.channel=1; params.name='NetIntensity'; params.color="#ff0000"; % check for param override -params=Segment.getParams(params,args); +featureParams=Segment.getParams(params,featureParams); -cmd=['select cellID from tblCells where time=' num2str(t)]; -q=ljsFetch(conn,cmd); -cellIDs=cell2mat(q); +cellList=Read.getCellsTime(conn,t); +if isempty(cellList) + return; +end +cellList=Read.setCellsIdxPts(cellList,CONSTANTS); im = MicroscopeData.Reader('imageData',CONSTANTS.imageData, 'chanList',... - params.channel,'timeRange',[t t], 'outType','single','prompt',false); + featureParams.channel,'timeRange',[t t], 'outType','single','prompt',false); if all(im(:)==0) return end bias=median(im(:)); -for i=1:length(cellIDs) - c=Read.getCell(conn,cellIDs(i)); - idxSegmentation=sub2ind(size(im),c.pts(:,2),c.pts(:,1)); - - net=sum(im(idxSegmentation)-bias); - cmd=['insert or ignore into tblCellFeatures(cellID) values (' ... - num2str(cellIDs(i)) ')']; - exec(conn,cmd); - cmd=['update tblCellFeatures set ' params.name '=' num2str(net) ... - ' where cellID=' num2str(cellIDs(i))]; - exec(conn,cmd); +for i=1:length(cellList) + net=sum(im(cellList(i).idxPts)-bias); + cellFeatures=[cellFeatures;cellList(i).cellID,net]; end +tblCellFeatures.cellID=cellFeatures(:,1); +tblCellFeatures.(featureParams.name)=cellFeatures(:,2); +4; diff --git a/matlab/+CellFeatures/netNuclearEnvelope.m b/matlab/+CellFeatures/netNuclearEnvelope.m index 1f249b1e04b86df658fd44ad833e7631daf2a1bd..fb26140c95958aa39cd7c00b8dab8c75fe869033 100644 --- a/matlab/+CellFeatures/netNuclearEnvelope.m +++ b/matlab/+CellFeatures/netNuclearEnvelope.m @@ -1,109 +1,49 @@ -function netNuclearEnvelope(conn,CONSTANTS,args,t) + +function tblCellFeatures=netNuclearEnvelope(conn,t,CONSTANTS,featureParams,segParams) + +tblCellFeatures=table(); params.channel=1; params.name='netNuclearEnvelope'; params.color="#ff0000"; % check for param override -params=Segment.getParams(params,args); - -% segmentation params -- for min radius -algs=Read.getAlgorithms(conn,'segment'); -args=algs.params; -segParams=Segment.getDefaultSegParams(); -segParams=Segment.getParams(segParams,args); - -rgRadius=Ensemble.getEnsembleRadius(segParams.minimumRadius_um); -resolution_um=CONSTANTS.imageData.PixelPhysicalSize; % um per pixel -min_radius_pixels = rgRadius ./ resolution_um(1); +featureParams=Segment.getParams(params,featureParams); -% todo -- handle anistropy in 3d! - -cmd=['select cellID from tblCells where time=' num2str(t)]; -q=ljsFetch(conn,cmd); -cellIDs=cell2mat(q); +cellList=Read.getCellsTime(conn,t); +if isempty(cellList) + return; +end +cellList=Read.setCellsIdxPts(cellList,CONSTANTS); im = MicroscopeData.Reader('imageData',CONSTANTS.imageData, 'chanList',... - params.channel,'timeRange',[t t], 'outType','single','prompt',false); + featureParams.channel,'timeRange',[t t], 'outType','single','prompt',false); if any(isnan(im)) return; end -is3d=size(im,3)>1; labelCells=0*im; dInterior=labelCells; -for i=1:length(cellIDs) - if is3d - c=Read.getCell3D(conn,cellIDs(i)); - idx=sub2ind(size(im),c.pts(:,2),c.pts(:,1),c.pts(:,3)); - else - c=Read.getCell(conn,cellIDs(i)); - idx=sub2ind(size(im),c.pts(:,2),c.pts(:,1)); - end +% get separate distance transform for each cell +for i=1:length(cellIDs) bwInterior=logical(0*im); - bwInterior(idx)=1; + bwInterior(cellList(i).idxPts)=1; bwd=bwdist(~bwInterior); dInterior=dInterior+bwd; - labelCells(idx)=c.cellID; + labelCells(idx)=cellList(i).cellID; end % find region surrounding segmentation [dExterior,idxd]=bwdist(labelCells); -for i=1:length(rgRadius) - li=labelCells; - lo=labelCells(idxd); - radius=rgRadius(i); - lo(dExterior>radius)=0; - % should this be 0, or min_radius_pixels? i.e. buffer between? - lo(dInterior>=radius)=0; - li(dInterior>=radius)=0; - - labelOuter(:,:,:,i)=lo; - labelInner(:,:,:,i)=li; -end bias=median(im(:)); for i=1:length(cellIDs) - if is3d - c=Read.getCell3D(conn,cellIDs(i)); - else - c=Read.getCell(conn,cellIDs(i)); - end - if isfield(c,'segCC') - iRadius=c.segCC-floor(c.segCC); - if 0==iRadius - iRadius=1; - else - prec=ceil(log10(length(rgRadius)+1));% # of digits in the radius tag - iRadius=iRadius*10^prec; - iRadius=int32(iRadius); - end - else - iRadius=1; - end - - idxInner=find(labelInner(:,:,:,iRadius)==c.cellID); - idxOuter=find(labelOuter(:,:,:,iRadius)==c.cellID); - net=mean( [im(idxInner)-bias;im(idxOuter)-bias]); - - net=round(net,4); - cmd=['insert or ignore into tblCellFeatures(cellID) values (' ... - num2str(cellIDs(i)) ')']; - exec(conn,cmd); - cmd=['update tblCellFeatures set ' params.name '=' num2str(net) ... - ' where cellID=' num2str(cellIDs(i))]; - exec(conn,cmd); -end - -function ratio=getErkRatio(im,idxOuter,idxInner) -ratio=NaN; -imOuter=im(idxOuter); -imOuter(0==imOuter)=[]; -if length(imOuter)<5 - return -end -imInner=im(idxInner); -imInner(0==imInner)=[]; -if length(imInner)/length(idxInner)<0.1 - return + % read signal within 2 pixels on either side of the boundary + idxInner = find( labelCells==cellList(i).cellID & dInterior<=2); + idxOuter = idxd(find( labelCells(idxd)==cellList(i).cellID & dExterior<=2 & dExterior>0)); + net=mean( [im(idxInner)-bias;im(idxOuter)-bias]); + net=round(net,4); + cellFeatures=[cellFeatures;cellList(i).cellID,net]; end -ratio=median(imOuter)/median(imInner); +tblCellFeatures.cellID=cellFeatures(:,1); +tblCellFeatures.(featureParams.name)=cellFeatures(:,2); +4; diff --git a/matlab/+CellFeatures/writeFeatureTable.m b/matlab/+CellFeatures/writeFeatureTable.m new file mode 100644 index 0000000000000000000000000000000000000000..5183cd0ac96a4e932f054f482a790254e859f01f --- /dev/null +++ b/matlab/+CellFeatures/writeFeatureTable.m @@ -0,0 +1,42 @@ +% should be cellID and 1 feature. write to db. +function writeFeatureTable(conn,featureTable) + +if size(featureTable,2)~=2 || ~strcmp(featureTable.Properties.VariableNames{1},'cellID') + fprintf(2,'writeFeatureTable - invalid table format\n'); + return; +end + +% if isnan(ratio) +% cmd=['delete from tblCellFeatures where cellID=' num2str(cellIDs(i))]; +% exec(conn,cmd); +% else +% ratio=round(ratio,4); +% cmd=['insert or ignore into tblCellFeatures(cellID) values (' ... +% num2str(cellIDs(i)) ')']; +% exec(conn,cmd); +% cmd=['update tblCellFeatures set ' params.name '=' num2str(ratio) ... +% ' where cellID=' num2str(cellIDs(i))]; +% exec(conn,cmd); +% end +cmdDelete='delete from tblCellFeatures where cellID=?'; +psDelete=conn.handle.prepareStatement(cmdDelete); +cmdInsert='insert or ignore into tblCellFeatures(cellID) values (?)'; +psInsert=conn.handle.prepareStatement(cmdInsert); +cmdUpdate=['update tblCellFeatures set ' featureTable.Properties.VariableNames{2}... + '=? where cellID=?']; +psUpdate=conn.handle.prepareStatement(cmdUpdate); + +for i=1:size(featureTable,1) + if isnan(featureTable{i,2}) + psDelete.setDouble(1,featureTable{i,1}); + Write.tryUpdateDB(psDelete); + else + psInsert.setDouble(1,featureTable{i,1}); + Write.tryUpdateDB(psInsert); + % set feature value + psUpdate.setDouble(1,featureTable{i,2}); + % set cellID + psUpdate.setDouble(2,featureTable{i,1}); + Write.tryUpdateDB(psUpdate); + end +end diff --git a/matlab/+Segment/thresholdImages.m b/matlab/+Segment/thresholdImages.m index f094a6a05c4aa2bd8c1165326ddb878f0c5be16a..95c1994879f0b61677bd1c03eb9d62e18eae994b 100644 --- a/matlab/+Segment/thresholdImages.m +++ b/matlab/+Segment/thresholdImages.m @@ -107,6 +107,7 @@ else pixelIdxList={rp.PixelIdxList}; end idxReset=find(convDef<1.1); -pixelIdxReset=vertcat(pixelIdxList{idxReset}); -bwLoG(pixelIdxReset)=0; - +if ~isempty(idxReset) + pixelIdxReset=vertcat(pixelIdxList{idxReset}); + bwLoG(pixelIdxReset)=0; +end diff --git a/matlab/+Smooth/+Classify/goClassifyMitosis.m b/matlab/+Smooth/+Classify/goClassifyMitosis.m index a1180366c2c1424dd2d23c7cb0d9b7c43a134b0f..81e8f5d7b5aba99584f172bb9ed976b51a463b50 100644 --- a/matlab/+Smooth/+Classify/goClassifyMitosis.m +++ b/matlab/+Smooth/+Classify/goClassifyMitosis.m @@ -2,6 +2,11 @@ % pass in [conn,CONSTANTS] (from openDB) or strDB (full path to .LEVER) function classifyMitosis(conn,CONSTANTS) +reseg=Read.getAlgorithms(conn,'reseg'); +if isempty(reseg) || ~strcmp(reseg.params.mitosisDetection,'true') + return; +end + mParams=Read.getMitosisParams(conn); targetTracks=Smooth.getTargetTracks(conn,5); strDB=conn.DataSource;