Hi-
I study polarized cells that form a pseudostratified epithelial layer on filters. I am trying to make a plugin that will count the # of nuclei present in a stack. Because the cells are not a monolayer, I cannot accurately count them by making an zprojection and then do standard automated counting (the nuclei are occasionally on top of each other). It seems that it "should" be possible to make a plugin to analyze the nuclei in 3D and then count the number within a stack. Has something like this already been made? Any suggestions? Cheers, Mike |
On 11 Apr 2008, at 19:54, Mike Myerburg wrote:
> Hi- > > I study polarized cells that form a pseudostratified epithelial > layer on filters. I am trying to make a plugin that will count the > # of nuclei present in a stack. Because the cells are not a > monolayer, I cannot accurately count them by making an zprojection > and then do standard automated counting (the nuclei are > occasionally on top of each other). It seems that it "should" be > possible to make a plugin to analyze the nuclei in 3D and then > count the number within a stack. I've got a plugin which detects objects in 3D which might work for this purpose. It's designed to measure 3D distances between objects, but should be able to be used to simply count objects if that's all you wanted to do. It doesn't have any special facility for identifying nuclei but just builds features out of groups of voxels which are sufficiently bright. It's not quite yet at a stage where I'm ready to make a public release, but if you want to try it send me a mail off list and I'll send you a copy. If you want to you can send me an example image stack and I can run the plugin on it here to see if I can get it to do what you want. TTFN Simon. |
In reply to this post by Mike Myerburg
Mike,
if you have a program that segments and identify the cells in each slice of the stack, you can generate a binary mask and count the number of "islands" of white pixels (suppose that the cells are white and the backgroung is black). I've developed a plugin which implements a labelling algorithm to identify different objects in a binary scene. Then, this way you can count the number of cells slice by slice. Cheers, Fernando On Fri, Apr 11, 2008 at 3:54 PM, Mike Myerburg <[hidden email]> wrote: > Hi- > > I study polarized cells that form a pseudostratified epithelial layer on > filters. I am trying to make a plugin that will count the # of nuclei > present in a stack. Because the cells are not a monolayer, I cannot > accurately count them by making an zprojection and then do standard > automated counting (the nuclei are occasionally on top of each other). It > seems that it "should" be possible to make a plugin to analyze the nuclei in > 3D and then count the number within a stack. > > Has something like this already been made? Any suggestions? > > Cheers, Mike > -- ************************************************** Fernando José Ribeiro Sales ************************************************** Email: [hidden email] Tel: (11) 82020303 ************************************************** |
Dear all,
The 3-D objects counter plugin does a good job for isolated objects (defined by threshold), but lacks a 3D watershed routine. The existing watershed routines either don't work well in 3D or take too long. Uneven heterochromatin staining poses another difficulty. I wrote this macro to separate most nuclei based on XY and resampled XZ 2D watershedding, plus refinement of identities by Euclidean distances. It's not perfect, but seems to do a good job with a few sample data sets I collected. It doesn't overcount as far as tested. It background corrects and outputs a labeled RGB map (plus the text stats from 3D objects counter plugin). Default values work for 20-30 pixel-diameter nuclei sampled is 1-2 um Zstacks. Yu may need to tune rolling ball diameter, smoothing, thresholds, etc. (it's a brute-force approach, so I'd be interested in improvements/comments) I include the text here (watch for broken code lines), or you can download it from our macro site (sample data should be posted today). http://digital.bsd.uchicago.edu/imagejmacros.html _________cut below for 3D_nuclei_counter.txt _____________________ //macro to count DAPI nuclei in confocal Z stack (16bit) //it reduces the image to the object centers then counts those by means of the // 3D_object_counter plugin (required), and that takes care of merging overlapped objects // http://rsb.info.nih.gov/ij/plugins/track/objects.html // Final output is a numbered red-green stack plus the report // tuning steps would be the median radii and the expand diameters (decr both for low magnification) // Vytas Bindokas, Univ of Chicago, Apr 2008 // this uses distance maps plus XY and XZ watershed steps to split objects "3D"; action is not perfect ! // tuning steps are the rolling ball diam, the remove outlier diams; use smaller for low magnification input run("Colors...", "foreground=white background=black selection=yellow"); t1=getTitle(); run("Set Measurements...", " mean centroid redirect=None decimal=6"); n0=nSlices; h=getHeight(); w=getWidth(); getVoxelSize(width, height, depth, unit); wi=width; hei=height; d=depth; u=unit; run("Subtract Background...", "rolling=25 stack"); //try diameter of nucleus run("Duplicate...", "title=countme duplicate"); run("Set Scale...", "distance=0 known=1 pixel=1 unit=pixel"); setSlice(n0/2); run("Enhance Contrast", "saturated=0.1 normalize normalize_all "); //correct for Z intensity loss run("Remove Outliers...", "radius=7 threshold=0 which=Bright stack"); //this smooths DAPI heterochromatin staining patterns run("Remove Outliers...", "radius=2 threshold=0 which=Dark stack"); //smooths background // tuning point below setAutoThreshold(); //you can set a fixed range, if needed, by activating next line... //setThreshold(9500, 65535); //goal is to pick up entire nucleus (vs uneven bits) run("Make Binary", " "); run("Median...", "radius=3 stack"); //to smooth and fill some holes run("Watershed", "stack"); run("Distance Map", "stack"); // "find" centers for next steps (seems to aid splitting XY and XZ) run("Grays"); mo=1; //this is noise tolerance, lower = finds more maxima (tune as needed); values are DISTANCE TO EDGE for (i=1; i<=nSlices; i++){ setSlice(i); getStatistics(area, mean, min, max); if (max>min){ //skip if frame blank... run("Find Maxima...", "noise="+mo+" output=[Point Selection]"); run("Enlarge...", "enlarge=4"); //pad around each maximum; tune if need be run("Clear Outside", "slice"); } run("Select None"); } makeLine(0, 0, w, 0); run("Reslice [/]...", "input=1 output=1 slice="+h+""); //repeat watershedding and localization in Z axis rename("xz"); run("Enhance Contrast", "saturated=0.1"); run("Median...", "radius=1 stack"); run("Convert to Mask", " black"); run("Watershed", "stack"); run("Distance Map", "stack"); for (i=1; i<=nSlices; i++){ setSlice(i); getStatistics(area, mean, min, max); if (max>min){ run("Find Maxima...", "noise=0 output=[Point Selection]"); //since this is pixels, not true Z, I suggest keeping these values LOW run("Enlarge...", "enlarge=1"); //run("Fill", "slice"); } run("Select None"); } n1=nSlices; h1=getHeight(); w1=getWidth(); makeLine(0, 0, w1, 0); // run("Set Scale...", "distance=0 known=1 pixel=1 unit=pixel"); run("Reslice [/]...", "input="+1+" output="+1+" slice="+h1); //return to XY view rename("zvu"); setVoxelSize(wi, hei, d, u); setSlice(nSlices/2); run("Grays"); run("Despeckle", "stack"); // 3D counts can take much memory! consider going 8-bit here if it can't run in OS limits //the min & max size below can select what to 3D count run(" 3D objects counter", "threshold=1 slice=25 min=6 max=13107200 particles dot=3 numbers font=12"); run("8-bit"); //the next few lines build the red map data for overlays setMinAndMax(0, 1); run("Apply LUT", "stack"); selectWindow("xz"); close(); selectWindow("countme"); close(); selectWindow("zvu"); close(); selectWindow(t1); run("Enhance Contrast", "saturated=0.5 normalize normalize_all"); run("Despeckle", "stack"); run("RGB Merge...", "red=[Particles zvu] green=["+t1+"] blue=*None* gray=*None*"); rename("counted"+t1); ______________ end cut ___________________________ Fernando Sales wrote: > Mike, > > if you have a program that segments and identify the cells in each slice of > the stack, you can generate a binary mask and count the number of "islands" > of white pixels (suppose that the cells are white and the backgroung is > black). I've developed a plugin which implements a labelling algorithm to > identify different objects in a binary scene. Then, this way you can count > the number of cells slice by slice. > > Cheers, > Fernando > On Fri, Apr 11, 2008 at 3:54 PM, Mike Myerburg <[hidden email]> wrote: > > >> Hi- >> >> I study polarized cells that form a pseudostratified epithelial layer on >> filters. I am trying to make a plugin that will count the # of nuclei >> present in a stack. Because the cells are not a monolayer, I cannot >> accurately count them by making an zprojection and then do standard >> automated counting (the nuclei are occasionally on top of each other). It >> seems that it "should" be possible to make a plugin to analyze the nuclei in >> 3D and then count the number within a stack. >> >> Has something like this already been made? Any suggestions? >> >> Cheers, Mike >> >> > > > > -- __ Vytas Bindokas, Ph.D. Research Assoc. / Assoc. Prof., Director, BSD Light Microscopy Core Facility Dept Neurobiol Pharmacol Physiol MC0926 947 E 58th Street The University of Chicago Chicago IL 60637 Room Abbott 120 773-702-4875 email [hidden email] web site for LMCF: http://digital.bsd.uchicago.edu/index.html This email is intended only for the use of the individual or entity to which it is addressed and may contain information that is privileged and confidential. If the reader of this email message is not the intended recipient, you are hereby notified that any dissemination, distribution, or copying of this communication is prohibited. If you have received this email in error, please notify the sender and destroy/delete all copies of the transmittal. Thank you. |
Thanks-
This looks to be what I am looking for. I have been trying a similiar approach, but have stumbled up on the 3D watershedding. I will give this a try and let you know of any changes that work well for me. Cheers, Mike vbindoka wrote: > Dear all, > The 3-D objects counter plugin does a good job for isolated objects > (defined by threshold), but lacks a 3D watershed routine. The existing > watershed routines either don't work well in 3D or take too long. > Uneven heterochromatin staining poses another difficulty. I wrote this > macro to separate most nuclei based on XY and resampled XZ 2D > watershedding, plus refinement of identities by Euclidean distances. > It's not perfect, but seems to do a good job with a few sample data sets > I collected. It doesn't overcount as far as tested. It background > corrects and outputs a labeled RGB map (plus the text stats from 3D > objects counter plugin). Default values work for 20-30 pixel-diameter > nuclei sampled is 1-2 um Zstacks. Yu may need to tune rolling ball > diameter, smoothing, thresholds, etc. (it's a brute-force approach, so > I'd be interested in improvements/comments) > I include the text here (watch for broken code lines), or you can > download it from our macro site (sample data should be posted today). > http://digital.bsd.uchicago.edu/imagejmacros.html > _________cut below for 3D_nuclei_counter.txt _____________________ > > //macro to count DAPI nuclei in confocal Z stack (16bit) > //it reduces the image to the object centers then counts those by means > of the > // 3D_object_counter plugin (required), and that takes care of merging > overlapped objects > // http://rsb.info.nih.gov/ij/plugins/track/objects.html > // Final output is a numbered red-green stack plus the report > // tuning steps would be the median radii and the expand diameters (decr > both for low magnification) > // Vytas Bindokas, Univ of Chicago, Apr 2008 > // this uses distance maps plus XY and XZ watershed steps to split > objects "3D"; action is not perfect ! > // tuning steps are the rolling ball diam, the remove outlier diams; > use smaller for low magnification input > > run("Colors...", "foreground=white background=black selection=yellow"); > t1=getTitle(); > run("Set Measurements...", " mean centroid redirect=None decimal=6"); > n0=nSlices; > h=getHeight(); > w=getWidth(); > getVoxelSize(width, height, depth, unit); > wi=width; > hei=height; > d=depth; > u=unit; > run("Subtract Background...", "rolling=25 stack"); //try diameter of > nucleus > run("Duplicate...", "title=countme duplicate"); > run("Set Scale...", "distance=0 known=1 pixel=1 unit=pixel"); > setSlice(n0/2); > run("Enhance Contrast", "saturated=0.1 normalize normalize_all "); > //correct for Z intensity loss > run("Remove Outliers...", "radius=7 threshold=0 which=Bright stack"); > //this smooths DAPI heterochromatin staining patterns > run("Remove Outliers...", "radius=2 threshold=0 which=Dark stack"); > //smooths background > > // tuning point below > > setAutoThreshold(); //you can set a fixed range, if needed, > by activating next line... > //setThreshold(9500, 65535); //goal is to pick up entire nucleus > (vs uneven bits) > run("Make Binary", " "); run("Median...", "radius=3 stack"); > //to smooth and fill some holes > run("Watershed", "stack"); > run("Distance Map", "stack"); // "find" centers for next steps > (seems to aid splitting XY and XZ) > run("Grays"); > > mo=1; //this is noise tolerance, lower = finds more > maxima (tune as needed); values are DISTANCE TO EDGE > for (i=1; i<=nSlices; i++){ > setSlice(i); getStatistics(area, mean, min, max); if > (max>min){ //skip if frame blank... > run("Find Maxima...", "noise="+mo+" output=[Point Selection]"); > run("Enlarge...", "enlarge=4"); //pad around each > maximum; tune if need be > run("Clear Outside", "slice"); > } > run("Select None"); > } > > makeLine(0, 0, w, 0); > run("Reslice [/]...", "input=1 output=1 slice="+h+""); //repeat > watershedding and localization in Z axis > rename("xz"); > run("Enhance Contrast", "saturated=0.1"); > run("Median...", "radius=1 stack"); > run("Convert to Mask", " black"); > run("Watershed", "stack"); > run("Distance Map", "stack"); > > for (i=1; i<=nSlices; i++){ > setSlice(i); > getStatistics(area, mean, min, max); > if (max>min){ run("Find Maxima...", "noise=0 output=[Point > Selection]"); //since this is pixels, not true Z, I suggest keeping > these values LOW > run("Enlarge...", "enlarge=1"); > //run("Fill", "slice"); > } > run("Select None"); > } > n1=nSlices; > h1=getHeight(); > w1=getWidth(); > makeLine(0, 0, w1, 0); > // run("Set Scale...", "distance=0 known=1 pixel=1 unit=pixel"); > run("Reslice [/]...", "input="+1+" output="+1+" slice="+h1); > //return to XY view > rename("zvu"); > setVoxelSize(wi, hei, d, u); > setSlice(nSlices/2); > run("Grays"); > run("Despeckle", "stack"); > > // 3D counts can take much memory! consider going 8-bit here if it > can't run in OS limits > //the min & max size below can select what to 3D count > run(" 3D objects counter", "threshold=1 slice=25 min=6 max=13107200 > particles dot=3 numbers font=12"); > > run("8-bit"); //the next few lines build the red map data > for overlays > setMinAndMax(0, 1); > run("Apply LUT", "stack"); > selectWindow("xz"); > close(); > selectWindow("countme"); > close(); > selectWindow("zvu"); > close(); > selectWindow(t1); > run("Enhance Contrast", "saturated=0.5 normalize normalize_all"); > run("Despeckle", "stack"); > run("RGB Merge...", "red=[Particles zvu] green=["+t1+"] blue=*None* > gray=*None*"); > rename("counted"+t1); > > ______________ end cut ___________________________ > > > > Fernando Sales wrote: >> Mike, >> >> if you have a program that segments and identify the cells in each >> slice of >> the stack, you can generate a binary mask and count the number of >> "islands" >> of white pixels (suppose that the cells are white and the backgroung is >> black). I've developed a plugin which implements a labelling algorithm to >> identify different objects in a binary scene. Then, this way you can >> count >> the number of cells slice by slice. >> >> Cheers, >> Fernando >> On Fri, Apr 11, 2008 at 3:54 PM, Mike Myerburg >> <[hidden email]> wrote: >> >> >>> Hi- >>> >>> I study polarized cells that form a pseudostratified epithelial layer on >>> filters. I am trying to make a plugin that will count the # of nuclei >>> present in a stack. Because the cells are not a monolayer, I cannot >>> accurately count them by making an zprojection and then do standard >>> automated counting (the nuclei are occasionally on top of each >>> other). It >>> seems that it "should" be possible to make a plugin to analyze the >>> nuclei in >>> 3D and then count the number within a stack. >>> >>> Has something like this already been made? Any suggestions? >>> >>> Cheers, Mike >>> >>> >> >> >> >> |
In reply to this post by vbindokas
This plugin is working very well for me. Thanks so much for your work
and sharing. I still need to tweak it a bit as it misses a few in stacks with tightly packed cells. But it is quite close. Thanks for the help, Mike vbindoka wrote: > Dear all, > The 3-D objects counter plugin does a good job for isolated objects > (defined by threshold), but lacks a 3D watershed routine. The existing > watershed routines either don't work well in 3D or take too long. > Uneven heterochromatin staining poses another difficulty. I wrote this > macro to separate most nuclei based on XY and resampled XZ 2D > watershedding, plus refinement of identities by Euclidean distances. > It's not perfect, but seems to do a good job with a few sample data sets > I collected. It doesn't overcount as far as tested. It background > corrects and outputs a labeled RGB map (plus the text stats from 3D > objects counter plugin). Default values work for 20-30 pixel-diameter > nuclei sampled is 1-2 um Zstacks. Yu may need to tune rolling ball > diameter, smoothing, thresholds, etc. (it's a brute-force approach, so > I'd be interested in improvements/comments) > I include the text here (watch for broken code lines), or you can > download it from our macro site (sample data should be posted today). > http://digital.bsd.uchicago.edu/imagejmacros.html > _________cut below for 3D_nuclei_counter.txt _____________________ > > //macro to count DAPI nuclei in confocal Z stack (16bit) > //it reduces the image to the object centers then counts those by means > of the > // 3D_object_counter plugin (required), and that takes care of merging > overlapped objects > // http://rsb.info.nih.gov/ij/plugins/track/objects.html > // Final output is a numbered red-green stack plus the report > // tuning steps would be the median radii and the expand diameters (decr > both for low magnification) > // Vytas Bindokas, Univ of Chicago, Apr 2008 > // this uses distance maps plus XY and XZ watershed steps to split > objects "3D"; action is not perfect ! > // tuning steps are the rolling ball diam, the remove outlier diams; > use smaller for low magnification input > > run("Colors...", "foreground=white background=black selection=yellow"); > t1=getTitle(); > run("Set Measurements...", " mean centroid redirect=None decimal=6"); > n0=nSlices; > h=getHeight(); > w=getWidth(); > getVoxelSize(width, height, depth, unit); > wi=width; > hei=height; > d=depth; > u=unit; > run("Subtract Background...", "rolling=25 stack"); //try diameter of > nucleus > run("Duplicate...", "title=countme duplicate"); > run("Set Scale...", "distance=0 known=1 pixel=1 unit=pixel"); > setSlice(n0/2); > run("Enhance Contrast", "saturated=0.1 normalize normalize_all "); > //correct for Z intensity loss > run("Remove Outliers...", "radius=7 threshold=0 which=Bright stack"); > //this smooths DAPI heterochromatin staining patterns > run("Remove Outliers...", "radius=2 threshold=0 which=Dark stack"); > //smooths background > > // tuning point below > > setAutoThreshold(); //you can set a fixed range, if needed, > by activating next line... > //setThreshold(9500, 65535); //goal is to pick up entire nucleus > (vs uneven bits) > run("Make Binary", " "); run("Median...", "radius=3 stack"); > //to smooth and fill some holes > run("Watershed", "stack"); > run("Distance Map", "stack"); // "find" centers for next steps > (seems to aid splitting XY and XZ) > run("Grays"); > > mo=1; //this is noise tolerance, lower = finds more > maxima (tune as needed); values are DISTANCE TO EDGE > for (i=1; i<=nSlices; i++){ > setSlice(i); getStatistics(area, mean, min, max); if > (max>min){ //skip if frame blank... > run("Find Maxima...", "noise="+mo+" output=[Point Selection]"); > run("Enlarge...", "enlarge=4"); //pad around each > maximum; tune if need be > run("Clear Outside", "slice"); > } > run("Select None"); > } > > makeLine(0, 0, w, 0); > run("Reslice [/]...", "input=1 output=1 slice="+h+""); //repeat > watershedding and localization in Z axis > rename("xz"); > run("Enhance Contrast", "saturated=0.1"); > run("Median...", "radius=1 stack"); > run("Convert to Mask", " black"); > run("Watershed", "stack"); > run("Distance Map", "stack"); > > for (i=1; i<=nSlices; i++){ > setSlice(i); > getStatistics(area, mean, min, max); > if (max>min){ run("Find Maxima...", "noise=0 output=[Point > Selection]"); //since this is pixels, not true Z, I suggest keeping > these values LOW > run("Enlarge...", "enlarge=1"); > //run("Fill", "slice"); > } > run("Select None"); > } > n1=nSlices; > h1=getHeight(); > w1=getWidth(); > makeLine(0, 0, w1, 0); > // run("Set Scale...", "distance=0 known=1 pixel=1 unit=pixel"); > run("Reslice [/]...", "input="+1+" output="+1+" slice="+h1); > //return to XY view > rename("zvu"); > setVoxelSize(wi, hei, d, u); > setSlice(nSlices/2); > run("Grays"); > run("Despeckle", "stack"); > > // 3D counts can take much memory! consider going 8-bit here if it > can't run in OS limits > //the min & max size below can select what to 3D count > run(" 3D objects counter", "threshold=1 slice=25 min=6 max=13107200 > particles dot=3 numbers font=12"); > > run("8-bit"); //the next few lines build the red map data > for overlays > setMinAndMax(0, 1); > run("Apply LUT", "stack"); > selectWindow("xz"); > close(); > selectWindow("countme"); > close(); > selectWindow("zvu"); > close(); > selectWindow(t1); > run("Enhance Contrast", "saturated=0.5 normalize normalize_all"); > run("Despeckle", "stack"); > run("RGB Merge...", "red=[Particles zvu] green=["+t1+"] blue=*None* > gray=*None*"); > rename("counted"+t1); > > ______________ end cut ___________________________ > > > > Fernando Sales wrote: >> Mike, >> >> if you have a program that segments and identify the cells in each >> slice of >> the stack, you can generate a binary mask and count the number of >> "islands" >> of white pixels (suppose that the cells are white and the backgroung is >> black). I've developed a plugin which implements a labelling algorithm to >> identify different objects in a binary scene. Then, this way you can >> count >> the number of cells slice by slice. >> >> Cheers, >> Fernando >> On Fri, Apr 11, 2008 at 3:54 PM, Mike Myerburg >> <[hidden email]> wrote: >> >> >>> Hi- >>> >>> I study polarized cells that form a pseudostratified epithelial layer on >>> filters. I am trying to make a plugin that will count the # of nuclei >>> present in a stack. Because the cells are not a monolayer, I cannot >>> accurately count them by making an zprojection and then do standard >>> automated counting (the nuclei are occasionally on top of each >>> other). It >>> seems that it "should" be possible to make a plugin to analyze the >>> nuclei in >>> 3D and then count the number within a stack. >>> >>> Has something like this already been made? Any suggestions? >>> >>> Cheers, Mike >>> >>> >> >> >> >> > |
Hi!
I am working with a similar problem as you (counting DAPI stained nuclei in a Z-stack... in my case, it is germ cells in the C.elegans gonad). The plugin "count 3D nuclei" is great, but I find that it misses a few when cells are tightly packed (for me, this is most of the time). In order to work around this, I am using the stack generated with the "count 3D nuclei plugin" (green cells w/ red numbered dots) and then manually adding the couple cells it missed using the "Cell Counter" plugin. However, I find that it would be helpful if there was an option to have the numbers propagated through all the stacks (similar to the "Show All" option on "Cell Counter"). Have you by chance figured out how to do this? Also, it would be nice to have the option to hide the numbers (so that I have only red dots propaged throughout the stacks, without the numbers). Do you know how to do this? I am not a pro with Java! Thanks so much!!! Dorota
|
Free forum by Nabble | Edit this page |