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

Improve units conversion in EMD velox files #243

Open
ThorstenBASF opened this issue Mar 25, 2024 · 7 comments
Open

Improve units conversion in EMD velox files #243

ThorstenBASF opened this issue Mar 25, 2024 · 7 comments
Labels
type: bug Something isn't working

Comments

@ThorstenBASF
Copy link
Contributor

ThorstenBASF commented Mar 25, 2024

Describe the bug

If an image has a different number of pixels in X and Y, it can happen that axes are set to different units.
In my case I had an image of 256x512 with an original pixelsize of 5.1e-09m.
This is converted to 5.1nm in X and 0.0051µm in Y.

This leads to an error while I want to save the image with a scalebar, due the sanity check of the file_writer.
(see io_plugins/image.py, line 147)

To Reproduce

(The testfile contains confidential data, so i can't share, if nessessary I could creat one with public data.)
Steps to reproduce the behavior:

import hyperspy.api as hs
myfile = "testfile.emd"
s = hs.load(myfile, select_type='images')
s[0].save(myfile[:-4])+".jpg"), scalebar=True)

Expected behavior

Not sure where to fix it. I think best would be to have same units even if X Y has a ratio of 1:2, but here I didn't checked(found) the code.
The santiy check could also be extended to compare different units, but that would be much more effort.

Python environment:

  • HyperSpy version: 1.7.5 AND 2.0.1
  • Python version: 3.11.6

Additional context

Images of original_metadata and axes.
As a workaround I just set [1]=[0] for scale and units.

original_metadata
2d_signal_hyperspy

@ThorstenBASF ThorstenBASF added the type: bug Something isn't working label Mar 25, 2024
@ThorstenBASF ThorstenBASF changed the title It can happen that axes get different units It can happen that axes get different units (EMD import) Mar 25, 2024
@CSSFrancis
Copy link
Member

@ThorstenBASF This is related to how the data is loaded downstream:

def _convert_scale_units(self, value, units, factor=1):
if units is None:
return value, units
factor /= 2
v = float(value) * _UREG(units)
converted_v = (factor * v).to_compact()
converted_value = float(converted_v.magnitude / factor)
converted_units = "{:~}".format(converted_v.units)
return converted_value, converted_units

Moving this issue to Rosettasciio.

@CSSFrancis CSSFrancis transferred this issue from hyperspy/hyperspy Mar 26, 2024
@ericpre
Copy link
Member

ericpre commented Mar 28, 2024

@ThorstenBASF for opening this issue. Indeed, even if the current behaviour is still correct, it is not convenient and it would be better to keep the same units when possible (same dimension).
The issue is that when loading emd velox file, the units are converted automatically for conveninence (for example: to get units in "nm" or "um" instead of "m", which is the units saved in the emd file for the calibration) but axes are converted independently and it is possible that in some corner cases, there end up being different.

This could be improved by checking that both units are different and pick one of the two. What criterion should we use to pick one of the two?
@ThorstenBASF, in your specific case, which one of the two ("nm" or "um") would make more sense?
I can't think of an objective criterion and I think this is arbitrary. The main impact is to have small or large number in the display of the scalebar. Also it we consider large aspect ratio which is not uncommon, then I suspect that it wouldn't be possible to find a criterion that fit all corner cases!

As a workaround, it is possible to change the units of the axes using the AxesManager conver_units or the axes convert_to_units.

@ericpre ericpre changed the title It can happen that axes get different units (EMD import) Improve units conversion in EMD velox files Mar 28, 2024
@ThorstenBASF
Copy link
Contributor Author

@ericpre Thanks for taking care and moving the issues the the right place.

This could be improved by checking that both units are different and pick one of the two. What criterion should we use to pick one of the two? @ThorstenBASF, in your specific case, which one of the two ("nm" or "um") would make more sense?

Most of time you want a scalebar for the X axes. So, I would prefer to pick units from the X axes.

As a workaround, it is possible to change the units of the axes using the AxesManager conver_units or the axes convert_to_units.

Thanks! I just used one more line and set Y=X for scale and units :)

@ThorstenBASF
Copy link
Contributor Author

ThorstenBASF commented Apr 2, 2024

@ThorstenBASF This is related to how the data is loaded downstream:

I see, I just read a bit into the code.

The units used for calculations are only from the X axis anyway.

original_units = original_metadata["BinaryResult"].get("PixelUnitX", "")

So, instead of convert scale_x and scale_y, only x would be necessary. And set Y=X.

In addition there is a bug with the offset calculation. Here also the offset units could differ from the scale unit, but scale unit is used for both. (As in my case, the X offset should be -730 nm, not -0.73). So offset needs an additional conversation to same units as the units from scale_x[1], before it is extended to 'axes'.

scale_x = self._convert_scale_units(
pix_scale["width"], original_units, data.shape[i + 1]
)
scale_y = self._convert_scale_units(
pix_scale["height"], original_units, data.shape[i]
)
offset_x = self._convert_scale_units(
offsets["x"], original_units, data.shape[i + 1]
)
offset_y = self._convert_scale_units(
offsets["y"], original_units, data.shape[i]
)
axes.extend(
[
{
"index_in_array": i,
"name": "y",
"offset": offset_y[0],
"scale": scale_y[0],
"size": data.shape[i],
"units": scale_y[1],
"navigate": False,
},
{
"index_in_array": i + 1,
"name": "x",
"offset": offset_x[0],
"scale": scale_x[0],
"size": data.shape[i + 1],
"units": scale_x[1],
"navigate": False,
},
]
)

@ericpre
Copy link
Member

ericpre commented Apr 2, 2024

@ThorstenBASF, would you be interested to make a pull request to do these changes?

If so, there are some guidance contributor guide (which mostly refer to the hyperspy contributor guide).

@ThorstenBASF
Copy link
Contributor Author

I can't promise anything. I will first have to read me into all the "convert" commands and handling. Besides, this would be more or less private "joy". :)

But, I will see what I can do.

@ThorstenBASF
Copy link
Contributor Author

@ThorstenBASF, would you be interested to make a pull request to do these changes?

#248

Hope this can be closed. :)

ericpre added a commit that referenced this issue Apr 8, 2024
fix for issue #243 (EMD axes data)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants