Momentum correction and alignment of already binned data#
This example shows how to use the momentum correction and alignment features of sed-processor
with data that come already in a binned format - e.g. a tiff file stored from a momentum microscope. For demonstration purposes, we will use the WSe2 data from tutorial 2, and bin these data into the raw coordinates X/Y/TOF, similar as they would come from a momentum microscope tiff file.
[1]:
%load_ext autoreload
%autoreload 2
import matplotlib.pyplot as plt
import sed
from sed.dataset import dataset
%matplotlib widget
Load Data#
[2]:
dataset.get("WSe2") # Put in Path as root_dir="" to a storage of at least 20 GByte free space, otherwise local folder will be used.
data_path = dataset.dir # This is the path to the data
scandir, caldir = dataset.subdirs # scandir contains the data, caldir contains the calibration files
INFO - Not downloading WSe2 data as it already exists at "/home/runner/work/sed/sed/docs/tutorial/datasets/WSe2".
Set 'use_existing' to False if you want to download to a new location.
INFO - Using existing data path for "WSe2": "/home/runner/work/sed/sed/docs/tutorial/datasets/WSe2"
INFO - WSe2 data is already present.
[3]:
# create sed processor using the config file:
sp = sed.SedProcessor(folder=scandir, config="../src/sed/config/mpes_example_config.yaml", user_config={}, system_config={}, verbose=True)
sp.add_jitter()
INFO - Configuration loaded from: [/home/runner/work/sed/sed/docs/src/sed/config/mpes_example_config.yaml]
INFO - Folder config loaded from: [/home/runner/work/sed/sed/docs/tutorial/sed_config.yaml]
INFO - Default config loaded from: [/opt/hostedtoolcache/Python/3.10.17/x64/lib/python3.10/site-packages/sed/config/default.yaml]
WARNING - Entry "KTOF:Lens:Sample:V" for channel "sampleBias" not found. Skipping the channel.
INFO - add_jitter: Added jitter to columns ['X', 'Y', 't', 'ADC'].
Generate binned dataset
[4]:
binned_data = sp.pre_binning()
Distortion correction and alignment for binned data#
1. step: load data into the momentum corrector class instance#
If data comes as xarray with defined axes ranges, it can just be passed directly. If the data are just a plain numpy array, also provide the detector coordinate ranges of the binned data. The interactive tool allows you to select a slice for correction.
[5]:
# sp.mc.load_data(binned_data) # as xarray DataArray
bin_ranges = ((binned_data.X[0], binned_data.X[-1]), (binned_data.Y[0], binned_data.Y[-1]), (binned_data.t[0], binned_data.t[-1]))
sp.mc.load_data(binned_data.data, bin_ranges=bin_ranges) # as np.array
sp.mc.select_slicer(plane=33, width=10, apply=True)
2. Step:#
Next, we select a number of features corresponding to the rotational symmetry of the material, plus the center. These can either be auto-detected (for well-isolated points), or provided as a list (these can be read-off the graph in the cell above). These are then symmetrized according to the rotational symmetry, and a spline-warping correction for the x/y coordinates is calculated, which corrects for any geometric distortions from the perfect n-fold rotational symmetry.
[6]:
#features = np.array([[203.2, 341.96], [299.16, 345.32], [350.25, 243.70], [304.38, 149.88], [199.52, 152.48], [154.28, 242.27], [248.29, 248.62]])
#sp.mc.define_features(features=features, rotation_symmetry=6, include_center=True, apply=True)
# Manual selection: Use a GUI tool to select peaks:
#sp.mc.feature_select(rotation_symmetry=6, include_center=True)
# Autodetect: Uses the DAOStarFinder routine to locate maxima.
# Parameters are:
# fwhm: Full-width at half maximum of peaks.
# sigma: Number of standard deviations above the mean value of the image peaks must have.
# sigma_radius: number of standard deviations around a peak that peaks are fitted
sp.define_features(rotation_symmetry=6, auto_detect=True, include_center=True, fwhm=10, sigma=12, sigma_radius=4, apply=True)
3. Step:#
Generate nonlinear correction using the splinewarp algorithm. If no landmarks have been defined in the previous step, default parameters from the config are used
[7]:
# Option whether a central point shall be fixed in the determination fo the correction
sp.mc.spline_warp_estimate(include_center=True)
INFO - Calculated thin spline correction based on the following landmarks:
pouter_ord: [[203.00479115 342.99039809]
[299.8722643 346.1988005 ]
[350.9501043 244.77840078]
[305.6490382 150.19508049]
[199.37408957 152.83715131]
[153.41465476 243.0634629 ]]
pcent: (249.22964193080713, 249.24669382719628)
[7]:
array([[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]], dtype=float32)
[8]:
sp.mc.pose_adjustment(xtrans=8, ytrans=7, angle=-4, apply=True)
INFO - Applied translation with (xtrans=8.0, ytrans=7.0).
INFO - Applied rotation with angle=-4.0.
4. Step: Apply correction to the binned dataset and visualize the results#
This function uses interpolation to apply the generated displacement field to the whole binned dataset. There might be some loss of data quality due to this process. Also, make difference data between original/binned and corrected data for direct visualisation.
[9]:
corrected_data = binned_data.copy()
corrected_data.data = sp.mc.apply_correction(binned_data.data, axis=2)
difference_data = corrected_data - binned_data
[10]:
fig,ax = plt.subplots(1,2,figsize=(6,2.5), layout='constrained')
binned_data.isel(t=40).T.plot(ax=ax[0], cmap="terrain_r")
ax[0].set_title('corrected data')
difference_data.isel(t=40).T.plot(ax=ax[1])
ax[1].set_title('difference data')
[10]:
Text(0.5, 1.0, 'difference data')
[ ]: