Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix remaining assumptions on 5D dimensions #148

Merged
merged 15 commits into from
Jan 19, 2022
Merged

Conversation

sbesson
Copy link
Member

@sbesson sbesson commented Dec 10, 2021

Fixes #145

A few specifications especially in the HCS domain still rely on the expectation that the underlying image will be 5D. As this constraint has been lifted with v0.3, these changes update various places in the code to dynamically identify the x, y and c axis before performing array manipulation.

Without this PR, both ome_zarr info and napari should fail to read https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.3/idr0094A/7751.zarr is a suitable example for testing this change (plate with XY dimensions). With this PR included, both commands should work successfully.

The last commits also disable PlateLabels to fix the HCS display in napari. #177 as well as #65 (comment) might be fixed by this PR

sbesson and others added 2 commits December 10, 2021 11:07
A few specifications especially in the HCS domain still rely on the expectation
that the underlying image will be 5D. As this constraint has been lifted with
v0.3, these changes update various places in the code to dynamically identify
the x, y and c axis before performing array manipulation.
@codecov
Copy link

codecov bot commented Dec 10, 2021

Codecov Report

Merging #148 (962031f) into master (13b8428) will increase coverage by 0.28%.
The diff coverage is 81.25%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #148      +/-   ##
==========================================
+ Coverage   82.11%   82.40%   +0.28%     
==========================================
  Files          12       12              
  Lines        1269     1250      -19     
==========================================
- Hits         1042     1030      -12     
+ Misses        227      220       -7     
Impacted Files Coverage Δ
ome_zarr/reader.py 85.20% <81.25%> (+1.01%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 13b8428...962031f. Read the comment docs.

@will-moore
Copy link
Member

napari https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.3/idr0095B/11511420.zarr/ gave me a single image, not a plate.

Trying with:

$ napari https://uk1s3.embassy.ebi.ac.uk/0.3_samples/7751.zarr
11:37:57 ERROR Failed to load D/2/0/4
11:37:58 ERROR Failed to load G/11/0/4
...
Traceback (most recent call last):
  File "/opt/anaconda3/envs/napari/lib/python3.9/site-packages/napari/components/viewer_model.py", line 1061, in _add_layer_from_data
    layer = add_method(data, **(meta or {}))
TypeError: add_image() got an unexpected keyword argument 'properties'

I'm not sure why I'm getting that last error.

napari==0.4.12
napari-ome-zarr==0.3.1

@sbesson
Copy link
Member Author

sbesson commented Dec 10, 2021

napari https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.3/idr0095B/11511420.zarr/ gave me a single image, not a plate.

Apologies, that's indeed a single image. https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.3/idr0094A/7751.zarr is the one I had in mind (description updated)

@will-moore
Copy link
Member

I'm afraid I get the same error:

error
$ napari  https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.3/idr0094A/7751.zarr
12:10:02 ERROR Failed to load A/3/0/4
12:10:02 ERROR Failed to load E/7/0/4
12:10:02 ERROR Failed to load D/2/0/4
12:10:02 ERROR Failed to load H/3/0/4
12:10:02 ERROR Failed to load G/5/0/4
12:10:02 ERROR Failed to load A/2/0/4
12:10:02 ERROR Failed to load E/2/0/4
12:10:02 ERROR Failed to load H/7/0/4
12:10:02 ERROR Failed to load F/7/0/4
12:10:02 ERROR Failed to load C/12/0/4
12:10:02 ERROR Failed to load C/7/0/4
12:10:03 ERROR Failed to load C/9/0/4
12:10:03 ERROR Failed to load A/12/0/4
12:10:03 ERROR Failed to load C/2/0/4
12:10:03 ERROR Failed to load H/12/0/4
12:10:03 ERROR Failed to load G/7/0/4
12:10:03 ERROR Failed to load C/3/0/4
12:10:03 ERROR Failed to load E/12/0/4
12:10:03 ERROR Failed to load A/1/0/4
12:10:03 ERROR Failed to load B/12/0/4
12:10:03 ERROR Failed to load D/12/0/4
12:10:03 ERROR Failed to load F/10/0/4
12:10:03 ERROR Failed to load G/4/0/4
12:10:03 ERROR Failed to load C/10/0/4
12:10:03 ERROR Failed to load E/5/0/4
12:10:03 ERROR Failed to load E/11/0/4
12:10:04 ERROR Failed to load G/12/0/4
12:10:04 ERROR Failed to load D/3/0/4
12:10:04 ERROR Failed to load B/1/0/4
12:10:04 ERROR Failed to load E/10/0/4
12:10:04 ERROR Failed to load B/7/0/4
12:10:04 ERROR Failed to load G/6/0/4
12:10:04 ERROR Failed to load G/2/0/4
12:10:04 ERROR Failed to load F/8/0/4
12:10:04 ERROR Failed to load A/5/0/4
12:10:04 ERROR Failed to load D/10/0/4
12:10:04 ERROR Failed to load G/11/0/4
12:10:04 ERROR Failed to load C/8/0/4
12:10:04 ERROR Failed to load A/11/0/4
12:10:04 ERROR Failed to load G/10/0/4
12:10:04 ERROR Failed to load E/6/0/4
12:10:05 ERROR Failed to load D/6/0/4
12:10:05 ERROR Failed to load E/1/0/4
12:10:05 ERROR Failed to load F/12/0/4
12:10:05 ERROR Failed to load E/9/0/4
12:10:05 ERROR Failed to load A/7/0/4
12:10:05 ERROR Failed to load H/8/0/4
12:10:05 ERROR Failed to load E/4/0/4
12:10:05 ERROR Failed to load A/8/0/4
12:10:05 ERROR Failed to load A/10/0/4
12:10:05 ERROR Failed to load H/6/0/4
12:10:05 ERROR Failed to load B/5/0/4
12:10:05 ERROR Failed to load H/4/0/4
12:10:05 ERROR Failed to load B/9/0/4
12:10:05 ERROR Failed to load F/6/0/4
12:10:05 ERROR Failed to load F/9/0/4
12:10:06 ERROR Failed to load B/11/0/4
12:10:06 ERROR Failed to load D/11/0/4
12:10:06 ERROR Failed to load C/4/0/4
12:10:06 ERROR Failed to load G/9/0/4
12:10:06 ERROR Failed to load C/6/0/4
12:10:06 ERROR Failed to load B/3/0/4
12:10:06 ERROR Failed to load D/7/0/4
12:10:06 ERROR Failed to load C/11/0/4
12:10:06 ERROR Failed to load H/11/0/4
12:10:06 ERROR Failed to load F/1/0/4
12:10:06 ERROR Failed to load C/1/0/4
12:10:06 ERROR Failed to load H/9/0/4
12:10:06 ERROR Failed to load B/6/0/4
12:10:07 ERROR Failed to load D/5/0/4
12:10:07 ERROR Failed to load G/1/0/4
12:10:07 ERROR Failed to load A/4/0/4
12:10:07 ERROR Failed to load G/8/0/4
12:10:07 ERROR Failed to load B/4/0/4
12:10:07 ERROR Failed to load H/10/0/4
12:10:07 ERROR Failed to load H/2/0/4
12:10:07 ERROR Failed to load D/1/0/4
12:10:07 ERROR Failed to load B/10/0/4
12:10:07 ERROR Failed to load C/5/0/4
12:10:07 ERROR Failed to load A/9/0/4
12:10:07 ERROR Failed to load F/5/0/4
12:10:07 ERROR Failed to load E/8/0/4
12:10:07 ERROR Failed to load B/8/0/4
12:10:07 ERROR Failed to load H/5/0/4
12:10:07 ERROR Failed to load E/3/0/4
12:10:08 ERROR Failed to load F/2/0/4
12:10:08 ERROR Failed to load D/4/0/4
12:10:08 ERROR Failed to load F/11/0/4
12:10:08 ERROR Failed to load D/8/0/4
12:10:08 ERROR Failed to load D/9/0/4
12:10:08 ERROR Failed to load B/2/0/4
12:10:08 ERROR Failed to load F/4/0/4
12:10:08 ERROR Failed to load G/3/0/4
12:10:08 ERROR Failed to load A/6/0/4
12:10:08 ERROR Failed to load F/3/0/4
12:10:08 ERROR Failed to load H/1/0/4
Traceback (most recent call last):
  File "/opt/anaconda3/envs/napari/lib/python3.9/site-packages/napari/components/viewer_model.py", line 1032, in _add_layer_from_data
    layer = add_method(data, **(meta or {}))
TypeError: add_image() got an unexpected keyword argument 'properties'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/opt/anaconda3/envs/napari/bin/napari", line 8, in <module>
    sys.exit(main())
  File "/opt/anaconda3/envs/napari/lib/python3.9/site-packages/napari/__main__.py", line 431, in main
    _run()
  File "/opt/anaconda3/envs/napari/lib/python3.9/site-packages/napari/__main__.py", line 308, in _run
    viewer = view_path(  # noqa: F841
  File "/opt/anaconda3/envs/napari/lib/python3.9/site-packages/napari/view_layers.py", line 167, in view_path
    return _make_viewer_then('open', args, kwargs)
  File "/opt/anaconda3/envs/napari/lib/python3.9/site-packages/napari/view_layers.py", line 117, in _make_viewer_then
    method(*args, **kwargs)
  File "/opt/anaconda3/envs/napari/lib/python3.9/site-packages/napari/components/viewer_model.py", line 885, in open
    self._add_layers_with_plugins(
  File "/opt/anaconda3/envs/napari/lib/python3.9/site-packages/napari/components/viewer_model.py", line 958, in _add_layers_with_plugins
    added.extend(self._add_layer_from_data(*_data))
  File "/opt/anaconda3/envs/napari/lib/python3.9/site-packages/napari/components/viewer_model.py", line 1037, in _add_layer_from_data
    raise TypeError(
TypeError: _add_layer_from_data received an unexpected keyword argument ('properties') for layer type image

@sbesson
Copy link
Member Author

sbesson commented Dec 10, 2021

Interesting thanks. I hadn't tested with napari but I can reproduce.
Opening individual well samples e.g. via napari -v https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.3/idr0094A/7751.zarr/A/2/0/ works for me so I assume the issue is in the HCS loading logic.

@sbesson
Copy link
Member Author

sbesson commented Dec 10, 2021

d61e4d5 allowed me to identify the source of one of the issues

(napari) sbesson@ls30630:ome-zarr-py ((d61e4d5...)) $ napari -vv https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.3/idr0094A/7751.zarr
...
21:06:18 DEBUG LOADING tile... E/12/0/4
loading E/12/0/4
21:06:18 DEBUG https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.3/idr0094A/7751.zarr/e/12/0/4/.zarray
...

i.e. the normalization corrupts the path. c3927c0 disables the keys normalization and the command now fails with

(napari) sbesson@ls30630:ome-zarr-py ((d61e4d5...)) $ napari -vv https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.3/idr0094A/7751.zarr
...
21:10:14 DEBUG https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.3/idr0094A/7751.zarr/G/4/0/4/0/0
Traceback (most recent call last):
  File "/Users/sbesson/anaconda3/envs/napari/lib/python3.9/site-packages/napari/components/viewer_model.py", line 1032, in _add_layer_from_data
    layer = add_method(data, **(meta or {}))
TypeError: add_image() got an unexpected keyword argument 'properties'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/sbesson/anaconda3/envs/napari/bin/napari", line 10, in <module>
    sys.exit(main())
  File "/Users/sbesson/anaconda3/envs/napari/lib/python3.9/site-packages/napari/__main__.py", line 431, in main
    _run()
  File "/Users/sbesson/anaconda3/envs/napari/lib/python3.9/site-packages/napari/__main__.py", line 308, in _run
    viewer = view_path(  # noqa: F841
  File "/Users/sbesson/anaconda3/envs/napari/lib/python3.9/site-packages/napari/view_layers.py", line 167, in view_path
    return _make_viewer_then('open', args, kwargs)
  File "/Users/sbesson/anaconda3/envs/napari/lib/python3.9/site-packages/napari/view_layers.py", line 117, in _make_viewer_then
    method(*args, **kwargs)
  File "/Users/sbesson/anaconda3/envs/napari/lib/python3.9/site-packages/napari/components/viewer_model.py", line 885, in open
    self._add_layers_with_plugins(
  File "/Users/sbesson/anaconda3/envs/napari/lib/python3.9/site-packages/napari/components/viewer_model.py", line 958, in _add_layers_with_plugins
    added.extend(self._add_layer_from_data(*_data))
  File "/Users/sbesson/anaconda3/envs/napari/lib/python3.9/site-packages/napari/components/viewer_model.py", line 1037, in _add_layer_from_data
    raise TypeError(
TypeError: _add_layer_from_data received an unexpected keyword argument ('properties') for layer type image

with might be an issue at the napari-ome-zarr layer. To be confirmed with @will-moore.

@will-moore
Copy link
Member

I'm afraid I'm now getting seg-faults every time I run napari, so I'm not currently in a position to look into this any further.

I think the unexpected keyword argument ('properties')... is because ome-zarry-py is passing properties dict in the node.metadata to napari-ome-zarr which is then passing it on to napari. It it used for labels layers, but is not expected for image layers I think.
However, when I commented-out this in napari-ome-zarr, I got a different error: something like "data must be at least 2D" but don't remember exactly what that was - and it did look like the data was 2D.

@joshmoore
Copy link
Member

Sounds like another vote for integration tests in napari-ome-zarr.

@sbesson
Copy link
Member Author

sbesson commented Dec 14, 2021

Sounds like another vote for integration tests in napari-ome-zarr.

Seconding this statement, I also feel we need additional test coverage in this repository - which I suspect is also what https://github.com/ome/ome-zarr-py/pull/148/checks?check_run_id=4486647472 is reporting.

I had an initial look at extending test_reader, test_node to cover the use case described in this PR but these are fairly minimal tests and it looks like we need some infrastructure. I can imagine a few options:

Is there a consensus on the best approach?

@sbesson
Copy link
Member Author

sbesson commented Jan 12, 2022

Last commits allow to fix all HCS integration tests introduced in #153 including the reading of plates with 2D-4D images via ome_zarr info.

I am still failing to get these reading in napari with the same errors as mentioned in #148 (comment). Any hint on where to get started? Or is the issue at the napari-ome-zarr level?

Copy link
Member

@joshmoore joshmoore left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Big 👍 for the fixes. Have a vague concern about updating the [magic numbers](https://en.wikipedia.org/wiki/Magic_number_(programming) since conceivably we'll need to re-adjust at some point in the future.

size_y = well_spec.img_shape[3]
size_x = well_spec.img_shape[4]
self.axes = well_spec.img_metadata["axes"]
size_y = well_spec.img_shape[len(self.axes) - 2]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How close do you think we are getting to wanting accessors for these?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely feels like something the Axes object proposed in #124 could handle i.e. self.axes.get_y_index() or similar?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking more about it, in https://github.com/ome/ome-zarr-py/pull/148/files#diff-b50d9715cc6e4017cfc055fd0ed73ecb5d9158e17f4d58ca5b3ba08b89c46657R581, I used c_index = self.axes.index("c") to avoid relying on magic numbers.

With the current spec, this is also a strategy that could be used here i.e. self.axes.index("y"). However this will also be affected by #124 since the axes representation will become a list of dictionaries rather than a list of strings. @will-moore It looks like we need to decide on a resolution order as this PRs are becoming effectively coupled.

@sbesson
Copy link
Member Author

sbesson commented Jan 18, 2022

The remaining failure is due to the fact that 41c0d8f disables the entire PlateLabels spec which is not used anywhere and this reduces the test coverage. Any feeling on how we should deal with this scenario?

@joshmoore
Copy link
Member

I imagine ignoring or explicitly excluding some lines from codecov for the moment would be fine. Do we assume that a PlateLabel can't currently exist in the wild?

@jburel
Copy link
Member

jburel commented Jan 19, 2022

with this PR

ome_zarr info  https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.3/idr0094A/7751.zarr 
WARNING:ome_zarr.io:version mismatch: detected:FormatV03, requested:FormatV04
WARNING:ome_zarr.io:version mismatch: detected:FormatV04, requested:FormatV03
https://uk1s3.embassy.ebi.ac.uk/idr/zarr/v0.3/idr0094A/7751.zarr/ [zgroup]
 - metadata
   - Plate
 - data
   - (536, 804)

without

  File "<__array_function__ internals>", line 5, in concatenate
numpy.AxisError: axis 4 is out of bounds for array of dimension 2

@@ -57,7 +57,7 @@ def __init__(
self.specs.append(PlateLabels(self))
elif Plate.matches(zarr):
self.specs.append(Plate(self))
self.add(zarr, plate_labels=True)
# self.add(zarr, plate_labels=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe a comment indicating why it is commented out?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. @joshmoore @will-moore should #65 act as the reference issue for re-enabling/rewriting PlateLabels? In which case the code could directly link to it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think so - Don't fully know the reason for each failure, but they seem closely related

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll leave you to open a follow-up PR. Merging for a pre-release

@jburel
Copy link
Member

jburel commented Jan 19, 2022

Screenshot 2022-01-19 at 11 39 58

11:38:12 WARNING version mismatch: detected:FormatV03, requested:FormatV04
11:38:14 WARNING version mismatch: detected:FormatV04, requested:FormatV03

@sbesson sbesson merged commit 0a3e927 into ome:master Jan 19, 2022
@sbesson sbesson deleted the hcs_axes_fix branch January 19, 2022 15:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

HCS stitching of Wells to Plate broken for data less than 5D
4 participants