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

Axis conversion for TransientSpec #205

Open
wants to merge 16 commits into
base: main
Choose a base branch
from

Conversation

jlaehne
Copy link
Contributor

@jlaehne jlaehne commented Jan 1, 2024

Description of the change

Move axis conversion code to CommonLuminescence class to make it available to LuminescenceTransientSpectrum signals.

Handle inheritance for slicing of LuminescenceTransientSpectrum:

  • Create 1D version of signal_type = 'TransientSpec' (class TransientSpectrumCasting)
  • If TransientSpec is initialized in 1D with axes_manager[-1].units being a time unit, switch to LumiTransient class, otherwise switch to Luminescence class

Progress of the PR

@jlaehne jlaehne added this to the v0.2.3 milestone Jan 1, 2024
@codecov-commenter
Copy link

codecov-commenter commented Jan 1, 2024

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

Attention: Patch coverage is 97.00000% with 3 lines in your changes missing coverage. Please review.

Project coverage is 99.29%. Comparing base (9c402c0) to head (ecf514f).
Report is 22 commits behind head on main.

Files with missing lines Patch % Lines
lumispy/signals/common_luminescence.py 97.56% 2 Missing ⚠️
lumispy/signals/luminescence_transient.py 50.00% 1 Missing ⚠️

❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@             Coverage Diff             @@
##              main     #205      +/-   ##
===========================================
- Coverage   100.00%   99.29%   -0.71%     
===========================================
  Files           12       12              
  Lines          556      567      +11     
===========================================
+ Hits           556      563       +7     
- Misses           0        4       +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

>>> S1.to_invcm(laser=325)
"""

def to_invcm_relative(self, laser=None, inplace=True, jacobian=False):

Check notice

Code scanning / CodeQL

Explicit returns mixed with implicit (fall through) returns Note

Mixing implicit and explicit returns may indicate an error as implicit returns always return None.
lumispy/tests/utils/test_axis_conversion.py Dismissed Show dismissed Hide dismissed
# along with LumiSpy. If not, see <https://www.gnu.org/licenses/#GPL>.

import numpy as np
import pytest

Check notice

Code scanning / CodeQL

Unused import Note test

Import of 'pytest' is not used.
import pytest

from lumispy.signals import LumiSpectrum, LumiTransient, LumiTransientSpectrum
from hyperspy._signals.signal2d import Signal2D

Check notice

Code scanning / CodeQL

Unused import Note test

Import of 'Signal2D' is not used.

from lumispy.signals import LumiSpectrum, LumiTransient, LumiTransientSpectrum
from hyperspy._signals.signal2d import Signal2D
from numpy.testing import assert_allclose

Check notice

Code scanning / CodeQL

Unused import Note test

Import of 'assert_allclose' is not used.
@jlaehne jlaehne linked an issue Jan 29, 2024 that may be closed by this pull request
Copy link
Contributor

@ericpre ericpre left a comment

Choose a reason for hiding this comment

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

I don't like the idea of introducing the concept of "hidden signal" because by design registered signal class are not hidden.

If I understand correctly, the purpose of the TransientSpectrumCasting class is to assign to the correct class depending on the units of the last axis when converting to 1D signal. If so would it make sense to move this code to LumiTransient.__init__ and change to the Luminescence signal type when necessary? It should work if the TransientSpec signal type was added as an alias of the LumiTransient class?

lumispy/signals/luminescence_transientspec.py Outdated Show resolved Hide resolved
lumispy/hyperspy_extension.yaml Outdated Show resolved Hide resolved
lumispy/signals/luminescence_transientspec.py Outdated Show resolved Hide resolved
lumispy/signals/luminescence_transientspec.py Outdated Show resolved Hide resolved
lumispy/signals/luminescence_transientspec.py Outdated Show resolved Hide resolved
@jlaehne
Copy link
Contributor Author

jlaehne commented Oct 14, 2024

@ericpre I was also hesitating to introduce a 'hidden signal class', but it works like a charm - while I cannot make it work without.

It is more elegant than what I proposed in #204 (comment) (and did not work), so I proposed this solution in #204 (comment)

I tried again having the initialization in the __init__ of one of the two existing 1D classes, but it then does not properly convert to the other. Instead, I have improved the documentation as you proposed.

@jlaehne
Copy link
Contributor Author

jlaehne commented Oct 15, 2024

@ericpre do you have an idea why the changelog build displays a numba warning? See: https://lumispy--205.org.readthedocs.build/en/205/changelog.html
Do I have to add that dependency to the workflow now that it is optional upstream?

Also, any idea on the Azure Pipelines failures?

@ericpre
Copy link
Contributor

ericpre commented Oct 15, 2024

@ericpre do you have an idea why the changelog build displays a numba warning? See: https://lumispy--205.org.readthedocs.build/en/205/changelog.html Do I have to add that dependency to the workflow now that it is optional upstream?

This is surprising that it appears there! Yes, adding numba as dependencies or using hyperspy[speed] can be used a workaround.

Also, any idea on the Azure Pipelines failures?

mambaforge is deprecated, I will update what needs to be updated later today! 😉

@jlaehne
Copy link
Contributor Author

jlaehne commented Oct 17, 2024

@ericpre Do you want to have another look.

Copy link
Contributor

@ericpre ericpre left a comment

Choose a reason for hiding this comment

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

This looks good, I have some comments to improve the documentation.

import lumispy as lum
import numpy as np

data = np.arange(10*20).reshape(10, 20)

s = lum.signals.LumiTransientSpectrum(data)
s.axes_manager[-1].units = "ns"
s.axes_manager[-2].units = "nm"

s.sum(-1)
s.sum(-2)

conda_environment_dev.yml Outdated Show resolved Hide resolved
doc/user_guide/signal_axis.rst Outdated Show resolved Hide resolved
doc/user_guide/signal_axis.rst Outdated Show resolved Hide resolved
doc/user_guide/streak_images.rst Outdated Show resolved Hide resolved

.. image:: images/streakmap.svg
:width: 700
:alt: Plot of a streak camera image and its one-dimensional representations
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there code in lumispy that can make this figure? When I do lumispy.signals.luminescence_transientspec.LumiTransientSpectrum.plot, I get a normal plot.

It would be good to add the code to make this figure, otherwise it should be removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had previously prepared this figure for illustration purposes and thought it could be useful here to show the principle. It is indeed a useful feature to generally faciliate such kind of plots and I will open an issue to implement that in a separate PR (which could probably be taken on by one of my students). Not as the standard plotting of this class, but as a separate plot function (alternative to using sum an option to display spectra/transients for a certain range (or even an interactive span functionality can then be added later).

@@ -214,3 +224,300 @@ def normalize(self, pos=float("nan"), element_wise=False, inplace=False):
s.metadata.Signal.quantity = "Normalized intensity"
if not inplace:
return s

def _reset_variance_linear_model(self):
Copy link
Contributor

Choose a reason for hiding this comment

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

Am I understanding correctly that this is simply moved around and doesn't need reviewed of the code itself?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, all the code pertaining to signal axis conversion is moved to the CommonLuminescence class so that it is available also to LumiTransientSpectrum. That was the origin of this PR and I probably should have merged that moving part in before doing the other changes to make it clearer.

upcoming_changes/205.new.rst Outdated Show resolved Hide resolved
@jlaehne
Copy link
Contributor Author

jlaehne commented Oct 21, 2024

This looks good, I have some comments to improve the documentation.

I implemented your suggestions (and extended some to the rest of the documentation). Only the plot creation will need a separate PR.

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

Successfully merging this pull request may close these issues.

Slicing TransientSpec
3 participants