Closed jluethi closed 1 year ago
This is actually an example of hitting this issue here: https://github.com/fractal-analytics-platform/fractal-tasks-core/issues/150 Specifically point 3: Make sure that the relevant functions/tasks are capable of handling arrays of different shapes.
The issue arises primarily because we have 3D ROIs & 2D images. But even if our ROIs would be 2D as well (=> the indexing would work if we also handle that case), the cellpose function would still always return a 3D output image (the way it's currently programmed) and we have some other 3D assumptions in its code.
2 takeaways: 1) We should pursue the flexible dimensionality handling (i.e. I think illumination correction will potentially also run into some issues here on actual 2D inputs where images should be overwritten) 2) I want to test whether we can store our resulting labels in our current 3D mode (if yes, then we just need to handle loading of 2D data correctly).
To attempt 2: I think we can make this work by adding a check during ROI loading. That would probably mean having a library function for ROI loading which would handle the 2D case differently (checking for it and still returning a 3D array with dim0 = 1). I'll investigate whether this is works and whether we have downstream issues when saving the labels in this 3D mode (I think not, but maybe there would be issues with the viewer?)
How would one of the 2D-only input OME-Zarrs that we'd like to support look like? Would it be fully CYX like the one below?
I'm trying to write a test with this kind of input, but I'm not sure this was your intended goal @jluethi, nor I'm sure that #403 is enough (I'm still reviewing..).
'multiscales': [
{
'axes': [ ############### NOTE: There is no Z
{
'name': 'c',
'type': 'channel',
},
{
'name': 'y',
'type': 'space',
'unit': 'micrometer',
},
{
'name': 'x',
'type': 'space',
'unit': 'micrometer',
},
],
'datasets': [
{
'coordinateTransformations': [
{
'scale': [ ############## NOTE: CYX
1.0,
0.1625,
0.1625,
],
'type': 'scale',
},
],
'path': '0',
},
{
'coordinateTransformations': [
{
'scale': [
1.0,
0.325,
0.325,
],
'type': 'scale',
},
],
'path': '1',
},
{
'coordinateTransformations': [
{
'scale': [
1.0,
0.65,
0.65,
],
'type': 'scale',
},
],
'path': '2',
},
{
'coordinateTransformations': [
{
'scale': [
1.0,
1.3,
1.3,
],
'type': 'scale',
},
],
'path': '3',
},
{
'coordinateTransformations': [
{
'scale': [
1.0,
2.6,
2.6,
],
'type': 'scale',
},
],
'path': '4',
},
],
'version': '0.4',
},
],
'omero': {
'channels': [
{
'active': True,
'coefficient': 1,
'color': '00FFFF',
'family': 'linear',
'inverted': False,
'label': 'DAPI',
'wavelength_id': 'A01_C01',
'window': {
'end': 800,
'max': 65535,
'min': 0,
'start': 110,
},
},
],
'id': 1,
'name': 'TBD',
'version': '0.4',
},
}
How would one of the 2D-only input OME-Zarrs that we'd like to support look like? Would it be fully CYX like the one below? I'm trying to write a test with this kind of input, but I'm not sure this was your intended goal @jluethi, nor I'm sure that https://github.com/fractal-analytics-platform/fractal-tasks-core/pull/403 is enough (I'm still reviewing..).
I'm still not convinced that #403 would not work for this kind of OME-Zarr input. In fact it may be that it does, by accident, by interpreting the C dimension as a Z dimension - when parsing the ZYX pixel sizes (via extract_zyx_pixel_sizes
). But this only works if the scale transformation has value 1 for both the C and Z axis (which is not necessarily true).
With https://github.com/fractal-analytics-platform/fractal-tasks-core/commit/bad56c4cbe82177f392dd6bc9a1f389963f47f3c, I added a test that runs the Cellpose task on a true CZY OME-Zarr array. The test actually passes, and it produces labels, but I think this is again not working correctly. This is clear by looking at the logs
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:296 zarrurl='/tmp/pytest-of-tommaso/pytest-93/test_CYX_input0/tmp_out_mip/plate_mip.zarr/B/03/0'
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:364 data_zyx.shape=(540, 1280)
INFO fractal_tasks_core.lib_regions_of_interest:lib_regions_of_interest.py:400 ROI table at /tmp/pytest-of-tommaso/pytest-93/test_CYX_input0/tmp_out_mip/plate_mip.zarr/B/03/0/tables/FOV_ROI_table has attrs: {'encoding-type': 'anndata', 'encoding-version': '0.1.0'}
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:378 ROI table at /tmp/pytest-of-tommaso/pytest-93/test_CYX_input0/tmp_out_mip/plate_mip.zarr/B/03/0/tables/FOV_ROI_table cannot be used for masked loading. Set use_masks=False.
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:383 use_masks=False
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:389 full_res_pxl_sizes_zyx=[1.0, 0.1625, 0.1625]
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:393 actual_res_pxl_sizes_zyx=[1.0, 0.65, 0.65]
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:400 reset_origin=True
INFO fractal_tasks_core.lib_regions_of_interest:lib_regions_of_interest.py:226 full_res_pxl_sizes_zyx=[1.0, 0.1625, 0.1625]
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:471 new_labels=['label_DAPI']
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:472 existing_labels=[]
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:496 Output label path: /tmp/pytest-of-tommaso/pytest-93/test_CYX_input0/tmp_out_mip/plate_mip.zarr/B/03/0/labels/label_DAPI/0
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:517 mask will have shape (540, 1280) and chunks ((540,), (1280,))
test_workflows_cellpose_segmentation.py:161 patched_cellpose_core_use_gpu
'WARNING: using patched_cellpose_core_use_gpu' (str) len=44
INFO cellpose.models:models.py:338 >> cyto2 << model set to be used
INFO cellpose.core:core.py:90 >>>> using CPU
INFO cellpose.models:models.py:372 >>>> model diam_mean = 30.000 (ROIs rescaled to this size during training)
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:532 Start cellpose_segmentation task for /tmp/pytest-of-tommaso/pytest-93/test_CYX_input0/tmp_out_mip/plate_mip.zarr/B/03/0
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:533 relabeling: True
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:534 do_3D: False
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:535 use_gpu: False
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:536 level: 2
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:537 model_type: cyto2
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:538 pretrained_model: None
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:539 anisotropy: None
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:540 Total well shape/chunks:
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:541 (540, 1280)
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:542 ((540,), (1280,))
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:558 Now starting loop over 2 ROIs
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:567 Now processing ROI 1/2
INFO cellpose_segmentation.py:test_workflows_cellpose_segmentation.py:119 [None][patched_segment_ROI] START
INFO cellpose_segmentation.py:test_workflows_cellpose_segmentation.py:132 [None][patched_segment_ROI] END
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:636 ROI [0, 1, 0, 540, 0, 640], num_labels_roi=2, num_labels_tot=2
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:567 Now processing ROI 2/2
INFO cellpose_segmentation.py:test_workflows_cellpose_segmentation.py:119 [None][patched_segment_ROI] START
INFO cellpose_segmentation.py:test_workflows_cellpose_segmentation.py:132 [None][patched_segment_ROI] END
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:636 ROI [0, 1, 0, 540, 640, 1280], num_labels_roi=2, num_labels_tot=4
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:672 End cellpose_segmentation task for /tmp/pytest-of-tommaso/pytest-93/test_CYX_input0/tmp_out_mip/plate_mip.zarr/B/03/0, now building pyramids.
INFO fractal_tasks_core.tasks.cellpose_segmentation:cellpose_segmentation.py:688 End building pyramids
where it's clear that the 1.0
which is the "pixel size" along the C axis is interpreted as the one along the Z axis.
As of our discussion a few minutes ago:
Great overview of conclusions from the call, this should be the scope limit for merging it.
Would it be fully CYX like the one below?
Yes, the examples I have so far always are like this and I'm aiming for supporting CYX support, not YX support. Yes, that this works is somewhat accidental, we'll need to improve with #150 eventually.
We are currently always relying that the first axis is C, independently on what comes next. Because of this, we can simply fix a current issue with the labeling tasks (they produce wrong metadata, which has scale transformations with four elements) in a simple way: always strip away the first item, since labels do not have C axis.
If we include a check for the presence of a C axis in relevant library functions, then that should be save and show us where we'd need to continue when we get back to it.
c
, in some relevant library function - which one(s)?The new test_workflows_napari_workflows.py::test_napari_workflow_CYX
(90c7528) applies two napari workflows (labeling and measurement) to a CYX OME-Zarr input. The final OME-Zarr
That's great! 👏🏻
We are clearly not fixing https://github.com/fractal-analytics-platform/fractal-tasks-core/issues/150 here, but let's aim at a version where example 01 in fractal-demos does work.
I've not run example 01 in fractal-demos (as of https://github.com/fractal-analytics-platform/fractal-demos/pull/54/commits/1152116bcd6e1c20d2960915e892b1d3cef8e096), and it went through with no noticeable issues.
That's great! Sounds like we're ready to merge this then.
Add a check that the first axis is
c
, in some relevant library function - which one(s)?
I also ran example 01 locally now and all looks good to me there. I'll continue work to update the MD converter task for server 1.3.0 & tasks 0.10.0 compatibility and will test that afterwards, but would open new issues and a new PR if problems come up there.
What about MIP? Does it also rely on having three-items scale transformations? Let's review this.
When we have a CZYX OME-Zarr and we call copy_ome_zarr.py
with project_to_2D=True
, the output is a new (metadata-only) CZYX OME-Zarr, which simply has a dummy Z axis.
Both copy_ome_zarr.py
and maximum_intensity_projection.py
then use extract_zyx_pixel_sizes
, which we patched so that it alwasy returns the last three elements of scale transformations as ZYX pixel sizes.
TL;DR Even if we don't have much flexibility, in the current (transitional..) state of fractal-tasks-core, I don't see any special issue with MIP in current workflows:
That's great! Sounds like we're ready to merge this then.
There's nothing left on my side re: #403.
We save our 2D OME-Zarrs as (z, y, x) images with (1, size_y, size_x). Some other OME-Zarrs (e.g. the ones generated by the faim-hcs OME-Zarr converter) can be (x,y) only, i.e. (size_y, size_x).
This then leads to issues in our processing, for example the following error in cellpose. The problem here is a mismatch between ROI dimensions (ROIs always being z, y, x) and image dimensions.
TODO: Figure out whether we can support 2D OME-Zarr images 1) by adapting the loading to support that? 2) by adapting our ROI tables for 2D images?
I'd prefer 1, but need to evaluate