imagej / pyimagej

Use ImageJ from Python
https://pyimagej.readthedocs.io/
Other
475 stars 82 forks source link

Enable `dim_order` kwargs for direct image conversions #238

Closed elevans closed 1 year ago

elevans commented 2 years ago

This pull request enables dim_order kwargs for the direct image converter methods: to_dataset(), to_img(), and to_xarray(). It also adds tests for this new feature in test_image_conversion.py and some additional features. There are also a couple of bugs/enhancements I made (e.g. we now calculate the slope for linear axis using all points instead of the first two elements of the scale array).

To get a good idea on the dim_order kwarg option and how it works with the direct image converters, check out the new section I wrote in the docs (06-Working-with-Images, section 6.9). There is a nice table that outlines the image conversion behavior with or without dim_order supplied.

changes

codecov-commenter commented 1 year ago

Codecov Report

Base: 76.05% // Head: 77.40% // Increases project coverage by +1.35% :tada:

Coverage data is based on head (799113d) compared to base (bffc2d7). Patch coverage: 92.96% of modified lines in pull request are covered.

:mega: This organization is not using Codecov’s GitHub App Integration. We recommend you install it so Codecov can continue to function properly for your repositories. Learn more

Additional details and impacted files ```diff @@ Coverage Diff @@ ## main #238 +/- ## ========================================== + Coverage 76.05% 77.40% +1.35% ========================================== Files 16 16 Lines 1829 1868 +39 ========================================== + Hits 1391 1446 +55 + Misses 438 422 -16 ``` | [Impacted Files](https://codecov.io/gh/imagej/pyimagej/pull/238?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=imagej) | Coverage Δ | | |---|---|---| | [src/imagej/stack.py](https://codecov.io/gh/imagej/pyimagej/pull/238?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=imagej#diff-c3JjL2ltYWdlai9zdGFjay5weQ==) | `96.96% <ø> (ø)` | | | [tests/test\_labeling.py](https://codecov.io/gh/imagej/pyimagej/pull/238?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=imagej#diff-dGVzdHMvdGVzdF9sYWJlbGluZy5weQ==) | `100.00% <ø> (ø)` | | | [src/imagej/dims.py](https://codecov.io/gh/imagej/pyimagej/pull/238?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=imagej#diff-c3JjL2ltYWdlai9kaW1zLnB5) | `63.10% <64.28%> (+0.45%)` | :arrow_up: | | [src/imagej/\_\_init\_\_.py](https://codecov.io/gh/imagej/pyimagej/pull/238?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=imagej#diff-c3JjL2ltYWdlai9fX2luaXRfXy5weQ==) | `62.09% <80.00%> (+1.69%)` | :arrow_up: | | [tests/test\_image\_conversion.py](https://codecov.io/gh/imagej/pyimagej/pull/238?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=imagej#diff-dGVzdHMvdGVzdF9pbWFnZV9jb252ZXJzaW9uLnB5) | `98.83% <98.03%> (-1.17%)` | :arrow_down: | | [src/imagej/convert.py](https://codecov.io/gh/imagej/pyimagej/pull/238?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=imagej#diff-c3JjL2ltYWdlai9jb252ZXJ0LnB5) | `88.62% <100.00%> (+6.46%)` | :arrow_up: | Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=imagej). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=imagej)

:umbrella: View full report at Codecov.
:loudspeaker: Do you have feedback about the report comment? Let us know in this issue.

elevans commented 1 year ago

Update:

I'm working on using xarray's global attribute's to store imagej/pyimagej specific metadata like the scale and CalibratedAxis type. See the axis-scale-logic branch for more details. The way things are going it seems this will be our preferred way to assign CalibratedAxis types. Thus I think we should scrap the scale work I've done here (i.e. _compute_scale() etc...).

elevans commented 1 year ago

Me again! I have reverted the dims.py module to a near original state. The difference from main is:

I have a nice metadata solution and a rework on how we assign axes for xarrays <-> datasets. That work is still in progress (almost done) on this branch/PR: https://github.com/imagej/pyimagej/pull/247

Singleton dimensions

The reason I originally added the work with axis scales was because I discovered a bug when creating more tests for the dim_order kwargs. When converting a numpy.ndarray or an xarray.DataArray that has a singleton dimension (i.e. one or more axes is size 1) we run into an index error when trying to perform a subtraction between the first and second elements of the axis/scale array here: https://github.com/imagej/pyimagej/blob/a5544fa07a1b3652c2c0037afbbd07e0f5d32add/src/imagej/dims.py#L277-L289

From what I gather this rather serious bug has been here the entire time. Here is how you can reproduce it on main:

import numpy as np
import imagej

ij = imagej.init()
nparr = np.random.rand(1, 2, 3, 4, 5)

# index error
ds = ij.py.to_dataset(nparr)

I think no one has ran into this yet (or very few people have) because when you slice an array to a singleton dimension its usually squashed. But anyone who is making an array with a singleton dimension will hit this bug when converting to a Dataset.