Skip to content

Commit

Permalink
Fix plotting windows with navigation dimension >=2 and simplify setti…
Browse files Browse the repository at this point in the history
…ng background and integration windows line markers
  • Loading branch information
ericpre committed Sep 18, 2024
1 parent 8edcc79 commit 7f5d456
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 18 deletions.
73 changes: 55 additions & 18 deletions exspy/signals/eds.py
Original file line number Diff line number Diff line change
Expand Up @@ -987,7 +987,7 @@ def _plot_xray_lines(
self.add_xray_lines_markers(xray_lines, render_figure=False)
if background_windows is not None:
self._add_background_windows_markers(
background_windows, render_figure=False
background_windows, linestyles="--", render_figure=False
)
if integration_windows is not None:
if integration_windows == "auto":
Expand All @@ -997,7 +997,7 @@ def _plot_xray_lines(
windows_width=integration_windows, xray_lines=xray_lines
)
self._add_vertical_lines_groups(
integration_windows, linestyle="--", render_figure=False
integration_windows, render_figure=False
)
# Render figure only at the end
if render_figure:
Expand All @@ -1012,16 +1012,22 @@ def _add_vertical_lines_groups(self, position, render_figure=True, **kwargs):
position: 2D array of float
The position on the signal axis. Each row corresponds to a
group.
kwargs
**kwargs : dict
keywords argument for :class:`hyperspy.api.plot.markers.VerticalLine`
"""
colors = itertools.cycle(
position = np.array(position)
length = position.shape[1]
colors_cycle = itertools.cycle(
np.sort(plt.rcParams["axes.prop_cycle"].by_key()["color"])
)
colors = np.array(
[[c] * length for c, w in zip(colors_cycle, position)]
).flatten()

for x, color in zip(position, colors):
line = hs.plot.markers.VerticalLines(offsets=x, color=color, **kwargs)
self.add_marker(line, render_figure=False)
line = hs.plot.markers.VerticalLines(
offsets=position.flatten(), color=colors, **kwargs
)
self.add_marker(line, render_figure=False)
if render_figure:
self._render_figure(plot=["signal_plot"])

Expand Down Expand Up @@ -1102,7 +1108,9 @@ def remove_xray_lines_markers(self, xray_lines, render_figure=True):
if render_figure:
self._render_figure(plot=["signal_plot"])

def _add_background_windows_markers(self, windows_position, render_figure=True):
def _add_background_windows_markers(
self, windows_position, render_figure=True, **kwargs
):
"""
Plot the background windows associated with each X-ray lines.
Expand All @@ -1121,21 +1129,50 @@ def _add_background_windows_markers(self, windows_position, render_figure=True):
--------
estimate_background_windows, get_lines_intensity
"""
self._add_vertical_lines_groups(windows_position)
segments = []
for bw in windows_position:
self._add_vertical_lines_groups(windows_position, **kwargs)

# Calculate the start and end of segments for each window
# nav_dim + (number of x-ray lines, vertices positions)
# vertices positions are (x0, y0), (x1, x2)
segments_ = np.zeros(
self.axes_manager.navigation_shape + (len(windows_position), 2, 2)
)

for i, bw in enumerate(windows_position):
# Check that all background windows are within the energy range
if any(v < self.axes_manager[-1].low_value for v in bw) or any(
v > self.axes_manager[-1].high_value for v in bw
):
raise ValueError("Background windows is outside of the signal range.")
y1 = self.isig[bw[0] : bw[1]].mean(-1).data
y2 = self.isig[bw[2] : bw[3]].mean(-1).data
x1 = (bw[0] + bw[1]) / 2.0
x2 = (bw[2] + bw[3]) / 2.0
segments.append([[x1, y1[0]], [x2, y2[0]]])
segments = np.array(segments)
lines = hs.plot.markers.Lines(segments=segments, color="black")

# calculate the position of the segments
y0 = self.isig[bw[0] : bw[1]].mean(-1).data
y1 = self.isig[bw[2] : bw[3]].mean(-1).data
x0 = (bw[0] + bw[1]) / 2.0
x1 = (bw[2] + bw[3]) / 2.0

segments_[..., i, 0, 0] = x0
segments_[..., i, 0, 1] = y0.T
segments_[..., i, 1, 0] = x1
segments_[..., i, 1, 1] = y1.T

# convert to ragged array to comply with requirement for
# navigation position dependent markers
# 2000 x 2000 navigation shape takes ~2s
# 1000 x 1000 navigation shape takes ~0.5s
# 500 x 500 navigation shape takes ~0.01s
segments = np.empty(self.axes_manager.navigation_shape, dtype=object)
for i in np.ndindex(self.axes_manager.navigation_shape):
segments[i] = segments_[i]

colors_cycle = itertools.cycle(
np.sort(plt.rcParams["axes.prop_cycle"].by_key()["color"])
)
colors = np.array([c for c, w in zip(colors_cycle, windows_position)]).flatten()

lines = hs.plot.markers.Lines(segments=segments, color=colors, **kwargs)
self.add_marker(lines, render_figure=False)

if render_figure:
self._render_figure(plot=["signal_plot"])

Expand Down
18 changes: 18 additions & 0 deletions exspy/tests/signals/test_eds_tem.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import numpy as np
import pytest

import hyperspy.api as hs
from hyperspy.components1d import Gaussian
from hyperspy.decorators import lazifyTestClass

Expand Down Expand Up @@ -607,6 +608,23 @@ def test_outside_range_background_windows(self):
s.isig[2.0:].plot(True, background_windows=bw)


def test_plot_windows():
s = exspy.data.EDS_TEM_FePt_nanoparticles()

rng = np.random.default_rng()

[s * v * 10 for v in rng.random((10))]

s = hs.stack([s * v * 10 for v in rng.random((10))])
s = hs.stack([s * v * 10 for v in rng.random((5))])

bw = s.estimate_background_windows(line_width=[5.0, 2.0])
iw = s.estimate_integration_windows(windows_width=3)

s.plot(True, background_windows=bw, integration_windows=iw)
s.axes_manager.indices = (1, 2)


def test_with_signals_examples():
sig = exspy.data.EDS_TEM_FePt_nanoparticles()
for s in (sig, sig.as_lazy()):
Expand Down

0 comments on commit 7f5d456

Please sign in to comment.