DanuserLab / u-segment3D

Generate consensus 3D cells segmentations by combining 2D cell segmentations from any combination of xy, xz, yz views, compatible with outputs of any 2D segmentation method.
https://www.biorxiv.org/content/10.1101/2024.05.03.592249v2
GNU General Public License v3.0
8 stars 2 forks source link

Additional Details and Recommendations for Segmentation #3

Open NickDiNapoli opened 1 month ago

NickDiNapoli commented 1 month ago

Hi there,

After reading your BioArxiv paper I was excited to try out the technique on our microscopy data. I was able to dissect and reassemble the relevant parts of one of your tutorials to try on our datasets but the output was pretty rough. I attribute this to the anisotropy of our data (.108 um/px in xy versus 1.5 um/px in z) and the fact that Cellpose never does a great job when the anisotopy factor is high (in my experience). This seems to be what you guys call the "Direct Method" where Cellpose essentially runs on xy, xz, and yz views but it appears that you guys support the "Indirect Method" too. I think the latter would work best on our data as the 2D segmentation via Cellpose works quite well. The dataset I am using is MsBrain with PolyT and DAPI stain.

Fom what I am seeing in your tutorials, all methods either use the direct method or require xy, xz, and yz labels whereas I would like to just use my stack of 2D images/labels. Can someone point me in the direction of how to take my pervious serial 2D segmentations and using your indirect method to obtain a 3D segmentation output? I think this will likely be much better than running Cellpose in all planes.

Thank you.

DanuserLab commented 1 month ago

Hi, thanks for your message. The script in the 'tutorials/technical' folder uses the indirect method. Please let us know if you have more questions. Thank you.

NickDiNapoli commented 1 month ago

Thanks for your prompt reply and thanks for pointing me in the right direction. I'll give that one a try and report back with any additional questions.

fyz11 commented 1 month ago

Hiya,

Several options:

  1. Aggregate existing 2D xy direction segmentation into 3D: see in addition to above: https://github.com/DanuserLab/u-segment3D/blob/master/tutorials/anisotropic/segment_epithelial_organoid_2D_stacks.py

In this example I run first the cellpose 2D slice by slice to get a stack of 2D segmentations. Then apply the indirect method to only these xy-slice segmentations to make them 3D.

  1. Run direct method in xy slices only (you do not need all three views). https://github.com/DanuserLab/u-segment3D/blob/master/tutorials/anisotropic/segment_unwrapped_drosophila_2D_stacks.py

Here i apply direct method in xy only then generate the segmentation. If there is significant anisotropy, you cannot run cellpose on the side views. Then you will get the optimum segmentation just using xy slices in direct method.

3: Run direct method in xy, xz, yz
you must make sure to resize the volume so that it is isotropic i.e. increase 1st z dimension by factor 1.5 / 0.108 or else downsample xy slices.

You can do all this by setting the appropriate preprocessing parameters, using the isotropic factor to ensure things aren't too small or too large....

preprocess_params['voxel_res'] = [1.5 / 0.108, 1., 1.] # scale up the z slices so dimensions are isotropic preprocess_params['factor'] = 0.25 # simultaneously isotropically downscale in all dimensions so that you don't have a crazy large volume.

then proceeding as normal

Hope these help , if not, if you provide a link to an example data, i can try out some parameters for you.

NickDiNapoli commented 1 month ago

Hi @fyz11,

Thanks so much for chiming in. As recommended, I was able to run the indirect method by first generating segmentation for each z slice in 2D and then following 'tutorials/technical'. However, I found that the output of uSegment3D.aggregate_2D_to_3D_segmentation_indirect_method() is essentially just a copy of the Cellpose segmentation once I overlaid the two. I poked around your recommendations and it seems like trying 'tutorials/anisotropic/segment_epithelial_organoid_2D_stacks.py' is s reasonable next thing to attempt so I will implement that method and report back with any additional issues.

fyz11 commented 1 month ago

Hiya,

Hm..... I would expect uSegment3D.aggregate_2D_to_3D_segmentation_indirect_method() to return back the same 2D segmentations when viewed slice-by-slice through xy, but the colors should look now consistent as opposed to random labeling. The key would be if you reslice the image in ImageJ, the sideview should now have consistent labeling as in Fig. 5.

look forward to see if 'tutorials/anisotropic/segment_epithelial_organoid_2D_stacks.py' works for you.

Thanks!

NickDiNapoli commented 1 month ago

I wanted to follow up and say I was able to get the 'tutorials/anisotropic/segment_epithelial_organoid_2D_stacks.py' running decently well to the point where it is not just a copy of the cellpose segmentation. Now it's just a parameter tuning problem.

I also wanted to ask a follow up question. Is there a particular reason you guys named your project u-Segment3D in your setup.py? When you include dashes like that it makes the dependency unimportable into a Python module. I.e. I am building a project based on this repo but because the name in the environment is u-Segment3D I either need to go in and manually change the name of the package to something else or fork and create a branch of your repo with a compatible name in the setup.py. One cannot do an import u-Segment3D. In our work we always specify the project names with underscores so they can be imported by others in the open source community. If I am missing something here I would love to know.

fyz11 commented 1 month ago

Hi Nick,

thanks for getting back to us - that sounds great!

thanks for the tip on the import. I had not realized this effect the name would have, since I specified packages=['segment3D'] and we could do the import with import segment3D.

We will commit a change in the setup.py changing the name from 'u-Segment3D' to 'u_Segment3D'. The only reason for the previous naming was to be same with the written name in the paper.

NickDiNapoli commented 1 month ago

Hi @fyz11,

I really appreciate how prompt your replies are. No problem at all. So when you use packages=['segment3D'] that is the directory/code that gets built into your project but the project name is always what is specified in setup(name='u-Segment3D', It makes sense that import segment3D works in your Python modules as you are already operating in the project itself. Thank you for that explanation; I certainly would want to match the paper too. An example I can make is famous libraries like scikit-learn, they have dashes too and are shown as dashes in one's enviroment but the maintainers named the importable module sklearn so folks can import it. You guys could also do something like this but as it stands it'll be very hard for the community to use your project.

fyz11 commented 1 month ago

Thanks for the explanation ! The github is now updated so that its setup(name='u_Segment3D'

NickDiNapoli commented 1 month ago

I wanted to follow up again here because I was not totally right in my correspondence above. I forked the repo today to test out in my project environment. I discovered when using setuptools, the project name is in fact just the name of the project for purposes of installation i.e. pip install u_Segment3D and the name of the whl file but because you include packages=['segment3D'] and you have your __init__.py file within that package, the importable name in my environment's site-packages is segment3D. I want to apologize, I usually use poetry to build projects. You should be totally fine to keep the project name as u-Segment3D. The reason I couldn't import the project was not due to the dash, it was due to the dependencies. Once I forked your repo and nixed those troublesome dependencies, the package was built fine as segment3D.

fyz11 commented 1 month ago

Thanks so much for testing this and feeding back! This is great to know for future.