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

Axes sizes should always match signal shape #2692

Open
thomasaarholt opened this issue Mar 31, 2021 · 4 comments
Open

Axes sizes should always match signal shape #2692

thomasaarholt opened this issue Mar 31, 2021 · 4 comments

Comments

@thomasaarholt
Copy link
Contributor

We should ensure that the axes size and the number of axes provided to a signal, actually matches the data shape.

Note that there are a lot of new features coming in #2399.
While one could theoretically provide flexible-size (following signal shape) to UniformDataAxis and FunctionalDataAxis, DataAxis requires a fixed-length array. I think it is better that we for now expect the size attribute to match the signal shape when an axis is passed to a signal, and then we can consider a more flexible approach in the future.

As an example of where this can go wrong, currently the following does not raise any errors:

import hyperspy.api as hs
import numpy as np

data = np.zeros((5, 10))
ax1 = {'size' : 20}
ax2 = {'size' : 30}
ax3 = {'size' : 40}
axes = [ax1, ax2, ax3]
s = hs.signals.Signal1D(data, axes=axes)
print(s)
# <Signal1D, title: , dimensions: (30, 1|40)>
print(s.data.shape) 
# (5, 10) # very different from the hyperspy shape

Should be as simple as looping through the axes, and comparing its size with s.data.shape[ax.index_in_array], as well as checking the number of axes vs len(data.shape).

I will make a PR to #2399.

@thomasaarholt
Copy link
Contributor Author

thomasaarholt commented Mar 31, 2021

Another example from March 26, 2021 3:40 PM, note the size of the navigation dimensions.

import hyperspy.api as hs
import numpy as np

data = np.zeros((63, 51, 400, 975))

ax1 = {'size' : 63}
ax2 = {'size' : 51}
ax3 = {'size' : 400}
ax4 = {'size' : 975}

s = hs.signals.Signal2D(data, axes=[ax2, ax1, ax3, ax4])
s
# <Signal2D, title: , dimensions: (63, 51|975, 400)>
s.isig[1:2, 3:4]
# <Signal2D, title: , dimensions: (51, 63|1, 1)>

@F00lWise
Copy link

F00lWise commented Apr 6, 2021

Hello Thomas,
thank you for following up on this. Yes, the simple looping through the axes and comparing the length to the specified size would prevent confusions like mine (specifying the axes in an incorrect order or slightly differing size).
Another cool future feature could be to define the axes by providing a vector of edges or mids instead the dictionary attributes directly. Here, somebody could get the idea of providing axes with non-uniform stepsize, which would then also need to be checked for (either making it work or throwing an error).
Either way, thanks!

@jlaehne
Copy link
Contributor

jlaehne commented Apr 11, 2021

Another cool future feature could be to define the axes by providing a vector of edges or mids instead the dictionary attributes directly. Here, somebody could get the idea of providing axes with non-uniform stepsize, which would then also need to be checked for (either making it work or throwing an error).

Well that is what #2399 is about initially. Allowing to define axes through a vector or using an expression and thereby facilitating non-uniform stepsizes to be handled correctly.

@ericpre
Copy link
Member

ericpre commented Jul 6, 2021

Should be as simple as looping through the axes, and comparing its size with s.data.shape[ax.index_in_array], as well as checking the number of axes vs len(data.shape).

I will make a PR to #2399.

Are you still planning to make a PR?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants