Skip to content

add tutorial for momentum correction of already binned datasets #570

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

Merged
merged 3 commits into from
Apr 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/workflows/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ myst:
../tutorial/4_hextof_workflow
../tutorial/5_sxp_workflow
../tutorial/9_hextof_workflow_trXPD
../tutorial/12_momentum_correction_of_binned_data
```
234 changes: 234 additions & 0 deletions tutorial/12_momentum_correction_of_binned_data.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"id": "8ad4167a-e4e7-498d-909a-c04da9f177ed",
"metadata": {
"tags": []
},
"source": [
"# Momentum correction and alignment of already binned data\n",
"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](2_conversion_pipeline_for_example_time-resolved_ARPES_data.ipynb), and bin these data into the raw coordinates X/Y/TOF, similar as they would come from a momentum microscope tiff file."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fb045e17-fa89-4c11-9d51-7f06e80d96d5",
"metadata": {},
"outputs": [],
"source": [
"%load_ext autoreload\n",
"%autoreload 2\n",
"\n",
"import matplotlib.pyplot as plt\n",
"import sed\n",
"from sed.dataset import dataset\n",
"\n",
"%matplotlib widget"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "42a6afaa-17dd-4637-ba75-a28c4ead1adf",
"metadata": {},
"source": [
"## Load Data"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "34f46d54",
"metadata": {},
"outputs": [],
"source": [
"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.\n",
"data_path = dataset.dir # This is the path to the data\n",
"scandir, caldir = dataset.subdirs # scandir contains the data, caldir contains the calibration files"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f1f82054",
"metadata": {},
"outputs": [],
"source": [
"# create sed processor using the config file:\n",
"sp = sed.SedProcessor(folder=scandir, config=\"../src/sed/config/mpes_example_config.yaml\", user_config={}, system_config={}, verbose=True)\n",
"sp.add_jitter()"
]
},
{
"cell_type": "markdown",
"id": "2af4e36d",
"metadata": {},
"source": [
"Generate binned dataset"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5b6564f7",
"metadata": {},
"outputs": [],
"source": [
"binned_data = sp.pre_binning()"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "70aa4343",
"metadata": {},
"source": [
"## Distortion correction and alignment for binned data\n",
"### 1. step: load data into the momentum corrector class instance\n",
"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."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "345ab949",
"metadata": {},
"outputs": [],
"source": [
"# sp.mc.load_data(binned_data) # as xarray DataArray\n",
"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]))\n",
"sp.mc.load_data(binned_data.data, bin_ranges=bin_ranges) # as np.array\n",
"sp.mc.select_slicer(plane=33, width=10, apply=True)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "fee3ca76",
"metadata": {},
"source": [
"### 2. Step:\n",
"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).\n",
"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."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fd9666c5",
"metadata": {},
"outputs": [],
"source": [
"#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]])\n",
"#sp.mc.define_features(features=features, rotation_symmetry=6, include_center=True, apply=True)\n",
"# Manual selection: Use a GUI tool to select peaks:\n",
"#sp.mc.feature_select(rotation_symmetry=6, include_center=True)\n",
"# Autodetect: Uses the DAOStarFinder routine to locate maxima.\n",
"# Parameters are:\n",
"# fwhm: Full-width at half maximum of peaks.\n",
"# sigma: Number of standard deviations above the mean value of the image peaks must have.\n",
"# sigma_radius: number of standard deviations around a peak that peaks are fitted\n",
"sp.define_features(rotation_symmetry=6, auto_detect=True, include_center=True, fwhm=10, sigma=12, sigma_radius=4, apply=True)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"id": "f7519ff8",
"metadata": {},
"source": [
"### 3. Step: \n",
"Generate nonlinear correction using the splinewarp algorithm. If no landmarks have been defined in the previous step, default parameters from the config are used"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d27cd7a4",
"metadata": {},
"outputs": [],
"source": [
"# Option whether a central point shall be fixed in the determination fo the correction\n",
"sp.mc.spline_warp_estimate(include_center=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7f32988f",
"metadata": {},
"outputs": [],
"source": [
"sp.mc.pose_adjustment(xtrans=8, ytrans=7, angle=-4, apply=True)"
]
},
{
"cell_type": "markdown",
"id": "a85b6bcc",
"metadata": {},
"source": [
"### 4. Step: Apply correction to the binned dataset and visualize the results\n",
"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.\n",
"Also, make difference data between original/binned and corrected data for direct visualisation."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "37233997",
"metadata": {},
"outputs": [],
"source": [
"corrected_data = binned_data.copy()\n",
"corrected_data.data = sp.mc.apply_correction(binned_data.data, axis=2)\n",
"difference_data = corrected_data - binned_data"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "467d6b34-3c68-4e64-8cde-b1ad58f60206",
"metadata": {},
"outputs": [],
"source": [
"fig,ax = plt.subplots(1,2,figsize=(8,3), layout='constrained')\n",
"binned_data.isel(t=40).T.plot(ax=ax[0], cmap=\"terrain_r\")\n",
"ax[0].set_title('corrected data')\n",
"difference_data.isel(t=40).T.plot(ax=ax[1])\n",
"ax[1].set_title('difference data')"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3f4068f2-f015-497e-9b63-550b53e96ce6",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "sed_kernel_v1",
"language": "python",
"name": "sed_kernel_v1"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.16"
}
},
"nbformat": 4,
"nbformat_minor": 5
}