diff --git a/src/pynxtools_mpes/nomad/examples/E2 Binning of WSe2.ipynb b/src/pynxtools_mpes/nomad/examples/E2 Binning of WSe2.ipynb new file mode 100644 index 0000000..eed9baf --- /dev/null +++ b/src/pynxtools_mpes/nomad/examples/E2 Binning of WSe2.ipynb @@ -0,0 +1,711 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Binning raw Multidimensional Photoemission Spectroscopy (MPES) data and converting it into the NeXus format" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This example shows how to generate xarray based h5 files from WSe2 trARPES measurement data as detailed in this [paper](https://www.nature.com/articles/s41597-020-00769-8) and how to generate a file in the standardised [MPES NeXus format](https://manual.nexusformat.org/classes/contributed_definitions/NXmpes.html#nxmpes) from it.\n", + "Due to the size of the example file (~6GB) you need at least 40 GB of memory on your computer you're executing this example on. If you just want to have a look on how to convert a pre-binned xarray based h5 file into the NeXus format you may have a look at the simpler [Convert to NeXus example](./E1%20Convert%20to%20NeXus.ipynb), which has lower hardware requirements." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "## Download RAW data (trARPES data of WSe2)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "Here, we just set the main file folder for holding the measurement data." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "FDIR = f'{os.getcwd()}/Scan049_1'\n", + "ECAL = f'{os.getcwd()}/energycal_2019_01_08'" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Since the provided measurement files are rather large (~6GB), they are not directly provided with the example.\n", + "You can [download](https://zenodo.org/record/6369728/files/WSe2.zip) it from zenodo. This may take some time. Place the file in the directory of this notebook afterwards. Under Linux, macOS and in a NORTH container you can directly use the cell below to download the file with curl." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "! curl -o WSe2.zip \"https://zenodo.org/records/6369728/files/WSe2.zip\"" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we extract the measurement files." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "! unzip WSe2.zip" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Binning of measurement data" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First we import the necessary packages. For a manual on how to install this dependencies refer to the provided [INSTALL.md](./INSTALL.md) file. If you're running a pre-built docker container or working with the NORTH tools, these dependencies are already available for you." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from mpes import base as base, fprocessing as fp, analysis as aly\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import os\n", + "from dask import compute\n", + "import datetime as dt\n", + "import h5py" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Initial data binning for distortion correction" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "parp = fp.parallelHDF5Processor(folder=FDIR)\n", + "parp.gather(identifier=r'/*.h5', file_sorting=True)\n", + "len(parp.files)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Bin a small range of of files to create a momentum map for distortion correction\n", + "parp.files = parp.files[0:50]\n", + "axes = ['X', 'Y', 't']\n", + "# Important to keep the whole detector area for the initial binning!\n", + "bins = [512, 512, 300]\n", + "ranges = [(0, 2048), (0, 2048), (64000, 68000)]\n", + "parp.parallelBinning(axes=axes, nbins=bins, ranges=ranges, scheduler='threads', ret=False)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Determine correction landmarks" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Select an energy slice at the valence band maximum, containing the 6 K-points and the Gamma point as distinct features\n", + "mc = aly.MomentumCorrector(parp.combinedresult['binned'])\n", + "mc.selectSlice2D(slice(165, 175), 2)\n", + "# Extract these high-symmetry points \n", + "mc.featureExtract(mc.slice, sigma=5, fwhm=10, sigma_radius=3)\n", + "mc.view(points=mc.features, annotated=True)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Calculate thin plate spline symmetry correction" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Calculate a non-linear coordinate transformation based on thin plate splines that restores 6-fold symmetry\n", + "mc.splineWarpEstimate(image=mc.slice, landmarks=mc.pouter_ord, include_center=True,\n", + " iterative=False, interp_order=2, update=True)\n", + "mc.view(image=mc.slice_transformed, annotated=True, points={'feats':mc.ptargs}, backend='bokeh', crosshair=True, radii=[75,110,150], crosshair_thickness=0.2)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Image registration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Apply a coordinate translation to move the image into the center of the detector\n", + "mc.coordinateTransform(type='translation', xtrans=70., ytrans=70., keep=True)\n", + "plt.imshow(mc.slice_transformed, origin='lower', cmap='terrain_r')\n", + "plt.axvline(x=256)\n", + "plt.axhline(y=256)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Rotate the image into a high-symmetry direction\n", + "mc.coordinateTransform( type='rotation', angle=-5, center=(256., 256.), keep=True)\n", + "plt.imshow(mc.slice_transformed, origin='lower', cmap='terrain_r')\n", + "plt.axvline(x=256)\n", + "plt.axhline(y=256)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Display the final deformation field\n", + "subs = 20\n", + "plt.scatter(mc.cdeform_field[::subs,::subs].ravel(), mc.rdeform_field[::subs,::subs].ravel(), c='b')" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Momentum calibration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Pick one high-symmetry point\n", + "point_b = [252.,255.]\n", + "# Pick the BZ center\n", + "point_a = [308.,346.]\n", + "# give the distance of the two in inverse Angstrom\n", + "distance = np.pi*4/3/3.297\n", + "# Momentum calibration assuming equal scaling along both x and y directions (equiscale=True)\n", + "# Requirements : pixel coordinates of and the momentum space distance between two symmetry points, \n", + "# plus the momentum coordinates\n", + "# of one of the two points \n", + "ext = mc.calibrate(mc.slice_transformed,\n", + " point_from=point_a,\n", + " point_to=point_b,\n", + " dist=distance,\n", + " equiscale=True,\n", + " ret=['extent'])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Display corrected image in calibrated coordinates\n", + "mc.view(image=mc.slice_transformed, imkwds=ext)\n", + "plt.xlabel('$k_x$', fontsize=15)\n", + "plt.ylabel('$k_y$', fontsize=15)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Energy calibration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Bin traces for energy calibration\n", + "axes = ['t']\n", + "bins = [1000]\n", + "ranges = [(63000, 80000)]\n", + "traces, tof = fp.extractEDC(folder=ECAL,\n", + " axes=axes, bins=bins, ranges=ranges)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Applied bias voltages (negated, in order to achieve negative binding energies, E-E_F)\n", + "voltages = np.arange(-12.2, -23.2, -1)\n", + "ec = aly.EnergyCalibrator(biases=voltages, traces=traces, tof=tof)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Normalize traces to maximum\n", + "ec.normalize(smooth=True, span=7, order=1)\n", + "ec.view(traces=ec.traces_normed, xaxis=ec.tof, backend='bokeh')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Define a TOF feature range, and translate it for each of the traces according to their shift in bias voltage\n", + "rg = [(65000, 65200)]\n", + "ec.addFeatures(traces=ec.traces_normed, refid=0, ranges=rg[0], infer_others=True, mode='append')\n", + "ec.featranges" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Extract the first peak from each feature range\n", + "ec.featureExtract(traces=ec.traces_normed, ranges=ec.featranges)\n", + "ec.view(traces=ec.traces_normed, peaks=ec.peaks, backend='bokeh')" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Calculate energy calibration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# calculate the energy calibration (3rd order polynom). Eref corresponds to the binding energy (E-E_F) of the selected feature in the refid trace.\n", + "refid=5\n", + "Eref=-1.3\n", + "axs = ec.calibrate(ret='all', Eref=Eref, t=ec.tof, refid=refid)\n", + "ec.view(traces=ec.traces_normed, xaxis=ec.calibration['axis'], backend='bokeh')" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Quality of calibration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# inspect the quality of the energy calibration\n", + "for i in range(0,len(voltages)):\n", + " plt.plot(ec.calibration['axis']-(voltages[i]-voltages[refid]), ec.traces_normed[i])\n", + "plt.xlim([-15,5])" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Inspect calibration function" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# energy calibration function vs. TOF\n", + "ec.view(traces=ec.calibration['axis'][None,:], xaxis=ec.tof, backend='matplotlib', show_legend=False)\n", + "plt.scatter(ec.peaks[:,0], ec.biases-ec.biases[refid]+Eref, s=50, c='k')\n", + "plt.xlabel('Time-of-flight', fontsize=15)\n", + "plt.ylabel('Energy (eV)', fontsize=15)\n", + "plt.ylim([-8,6])\n", + "plt.xlim([63400,69800])" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Dataframe processor" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# create the dask data frame processor\n", + "dfp = fp.dataframeProcessor(datafolder=FDIR)\n", + "dfp.read(source='folder', ftype='h5', timeStamps=True)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Apply energy calibration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# apply the energy calibration\n", + "dfp.appendEAxis(E0=ec.calibration['E0'], a=ec.calibration['coeffs'])\n", + "dfp.edf.head(8)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Apply distortion correction" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# apply the distortion correction\n", + "dfp.applyKCorrection(type='tps_matrix',\n", + " rdeform_field = mc.rdeform_field,\n", + " cdeform_field = mc.cdeform_field,\n", + " X='X', Y='Y', newX='Xm', newY='Ym')\n", + "dfp.edf.head(8)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Apply momentum calibration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# apply the momentum calibration\n", + "dfp.appendKAxis(point_b[0], point_b[1], X='Xm', Y='Ym', rstart=parp.binranges[0][0],\n", + " cstart=parp.binranges[1][0],\n", + " rstep=parp.binsteps[0],\n", + " cstep=parp.binsteps[1],\n", + " fc=mc.calibration['coeffs'][0],\n", + " fr=mc.calibration['coeffs'][1])\n", + "dfp.edf.head(8)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Apply pump-probe delay axis conversion" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# calculate the pump-probe delay from the ADC coordinates\n", + "ADCRange = (650, 6900)\n", + "timeRange = (-100, 200)\n", + "dfp.edf['delay'] = timeRange[0] + (dfp.edf['ADC']-ADCRange[0]) *\\\n", + " (timeRange[1] - timeRange[0])/(ADCRange[1]-ADCRange[0])\n", + "dfp.edf.head(8)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Bin 4D data in transformed grid" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# process the 4-dimensional binning\n", + "axes = ['kx', 'ky', 'E', 'delay']\n", + "bins = [50, 50, 100, 21]\n", + "ranges = [(-2, 2), (-2, 2), (-3, 2), (-110, 190)]\n", + "# jittering of energy and ADC should best be done on the bin size of the hardware, \n", + "# not the rebinned bin size. This requires reverse-calculating the jitter amplitudes\n", + "# from the bin sizes.\n", + "TOFrange=[64500,67000]\n", + "e_t_conversion = (base.tof2evpoly(ec.calibration['coeffs'],\n", + " ec.calibration['E0'], \n", + " TOFrange[0])\n", + " - base.tof2evpoly(ec.calibration['coeffs'],\n", + " ec.calibration['E0'], TOFrange[1])\n", + " ) / (TOFrange[1] - TOFrange[0])\n", + "d_adc_conversion = (timeRange[1] - timeRange[0]) / (ADCRange[1] - ADCRange[0])\n", + "jitter_amplitude = [0.5,\n", + " 0.5,\n", + " 1*bins[2]/abs(ranges[2][1]-ranges[2][0])*e_t_conversion,\n", + " 1*bins[3]/abs(ranges[3][1]-ranges[3][0])*d_adc_conversion]\n", + "dfp.distributedBinning(axes=axes,\n", + " nbins=bins,\n", + " ranges=ranges,\n", + " scheduler='threads',\n", + " ret=False,\n", + " jittered=True,\n", + " jitter_amplitude=jitter_amplitude)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Run the following cell to store metadata from EPICS archive only if outside the FHI network\n", + "This adds additional metadata to the xarray. This data may also be provided through additional ELN entries through a NOMAD instance or with a handwritten file directly to the mpes parser." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "metadata = {\"file\": {}}\n", + "metadata['file'][\"KTOF:Lens:Extr:I\"] = -0.12877\n", + "metadata['file'][\"KTOF:Lens:UDLD:V\"] = 399.99905\n", + "metadata['file'][\"KTOF:Lens:Sample:V\"] = 17.19976\n", + "metadata['file'][\"KTOF:Apertures:m1.RBV\"] = 3.729931\n", + "metadata['file'][\"KTOF:Apertures:m2.RBV\"] = -5.200078\n", + "metadata['file'][\"KTOF:Apertures:m3.RBV\"] = -11.000425\n", + "\n", + "# Sample motor positions\n", + "metadata['file']['trARPES:Carving:TRX.RBV'] = 7.1900000000000004\n", + "metadata['file']['trARPES:Carving:TRY.RBV'] = -6.1700200225439552\n", + "metadata['file']['trARPES:Carving:TRZ.RBV'] = 33.4501953125\n", + "metadata['file']['trARPES:Carving:THT.RBV'] = 423.30500940561586\n", + "metadata['file']['trARPES:Carving:PHI.RBV'] = 0.99931647456264949\n", + "metadata['file']['trARPES:Carving:OMG.RBV'] = 11.002500171914066" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Generate xarray\n", + "Remember to remove the optional argument, metadata_dict, from the gather_metadata() function if the previous cell was not run.\n", + "The missing archive metadata warnings are not critical for this example and can thus be ignored." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import copy\n", + "res_xarray = dfp.gather_metadata(metadata_dict=copy.deepcopy(metadata), ec=ec, mc=mc)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "## Create a NeXus file from a xarray\n", + "This conversion basically follows the same procedure as in the [convert to NeXus example](./E1%20Convert%20to%20Nexus.ipynb). Please refer to this notebook for details on the convert function. Here, we are using the objects keywords of `convert` to pass the generated xarray directly, instead of loading a h5 datafile." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from pynxtools.dataconverter.convert import convert" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "convert(input_file=[\"config_file.json\", \"WSe2_eln.yaml\"],\n", + " objects=res_xarray,\n", + " reader='mpes',\n", + " nxdl='NXmpes',\n", + " output='WSe2.mpes.nxs')" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "## View the data with H5Web\n", + "H5Web is a tool for visualizing any data in the h5 data format. Since the NeXus format builds opon h5 it can be used to view this data as well. We just import the package and call H5Web with the output filename from the convert command above. For an analysis on NeXus data files please refer to [analysis example](./E3%20pyARPES%20analysis.ipynb).\n", + "\n", + "You can also view this data with the H5Viewer or other tools from your local filesystem." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from jupyterlab_h5web import H5Web" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "H5Web('WSe2.mpes.nxs')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "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.10.4" + }, + "vscode": { + "interpreter": { + "hash": "c2ecc4d45d4efcd07af778d75fd26bf86d0642a6646ea5c57f06d5857684e419" + } + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "state": {}, + "version_major": 2, + "version_minor": 0 + } + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/src/pynxtools_mpes/nomad/examples/MoTe.archive.json b/src/pynxtools_mpes/nomad/examples/MoTe.archive.json index 7e15db0..3b2b334 100644 --- a/src/pynxtools_mpes/nomad/examples/MoTe.archive.json +++ b/src/pynxtools_mpes/nomad/examples/MoTe.archive.json @@ -1,9 +1,9 @@ { "data": { - "m_def": "nomad.datamodel.metainfo.eln.nexus_data_converter.NexusDataConverter", + "m_def": "pynxtools.nomad.dataconverter.NexusDataConverter", "input_files": [ "MoTe2.h5", - "config_file.json" + "config_file_MoTe2.json" ], "reader": "mpes", "nxdl": "NXmpes", diff --git a/src/pynxtools_mpes/nomad/examples/config_file.json b/src/pynxtools_mpes/nomad/examples/config_file.json old mode 100755 new mode 100644 diff --git a/src/pynxtools_mpes/nomad/examples/config_file_MoTe2.json b/src/pynxtools_mpes/nomad/examples/config_file_MoTe2.json new file mode 100644 index 0000000..d08c6c1 --- /dev/null +++ b/src/pynxtools_mpes/nomad/examples/config_file_MoTe2.json @@ -0,0 +1,419 @@ +{ + "/@default": "entry", + "/ENTRY/@default": "data", + "/ENTRY/title": "@attrs:metadata/entry_title", + "/ENTRY/start_time": "@attrs:metadata/timing/acquisition_start", + "/ENTRY/experiment_institution": "Fritz Haber Institute - Max Planck Society", + "/ENTRY/experiment_facility": "Time Resolved ARPES", + "/ENTRY/experiment_laboratory": "Clean Room 4", + "/ENTRY/entry_identifier": { + "identifier":"@attrs:metadata/entry_identifier" + }, + "/ENTRY/end_time": "@attrs:metadata/timing/acquisition_stop", + "/ENTRY/duration": "@attrs:metadata/timing/acquisition_duration", + "/ENTRY/duration/@units": "s", + "/ENTRY/collection_time": "@attrs:metadata/timing/collection_time", + "/ENTRY/collection_time/@units": "s", + "/ENTRY/USER[user]": { + "name": "@attrs:metadata/user0/name", + "role": "@attrs:metadata/user0/role", + "affiliation": "@attrs:metadata/user0/affiliation", + "address": "@attrs:metadata/user0/address", + "email": "@attrs:metadata/user0/email" + }, + "/ENTRY/INSTRUMENT[instrument]": { + "name": "Time-of-flight momentum microscope equipped delay line detector, at the endstation of the high rep-rate HHG source at FHI", + "name/@short_name": "TR-ARPES @ FHI", + "energy_resolution": { + "resolution": 140.0, + "resolution/@units": "meV", + "physical_quantity": "energy", + "type": "estimated" + }, + "RESOLUTION[temporal_resolution]": { + "resolution": 35.0, + "resolution/@units": "fs", + "physical_quantity": "time", + "type": "estimated" + }, + "RESOLUTION[momentum_resolution]": { + "resolution": "@attrs:metadata/instrument/analyzer/momentum_resolution", + "resolution/@units": "1/angstrom", + "physical_quantity": "momentum", + "type": "estimated" + }, + "pressure_gauge": { + "name": "sample_chamber_pressure", + "measurement": "pressure", + "value": "@attrs:metadata/file/trARPES:XGS600:PressureAC:P_RD", + "value/@units": "mbar" + }, + "ELECTRONANALYSER[electronanalyser]": { + "description": "SPECS Metis 1000 Momentum Microscope", + "device_information": { + "vendor": "SPECS GmbH", + "model": "Metis 1000 Momentum Microscope" + }, + "fast_axes": [ + "kx", + "ky", + "E" + ], + "slow_axes": "@attrs:metadata/instrument/analyzer/slow_axes", + "energy_resolution": { + "resolution": 110.0, + "resolution/@units": "meV", + "physical_quantity": "energy", + "type": "estimated" + }, + "momentum_resolution": { + "resolution": "@attrs:metadata/instrument/analyzer/momentum_resolution", + "resolution/@units": "1/angstrom", + "physical_quantity": "momentum", + "type": "estimated" + }, + "spatial_resolution": { + "resolution": "@attrs:metadata/instrument/analyzer/spatial_resolution", + "resolution/@units": "µm", + "physical_quantity": "length", + "type": "estimated" + }, + "depends_on": "/entry/instrument/electronanalyser/transformations/trans_z", + "TRANSFORMATIONS[transformations]": { + "AXISNAME[trans_z]": 4.0, + "AXISNAME[trans_z]/@depends_on": "rot_y", + "AXISNAME[trans_z]/@transformation_type": "translation", + "AXISNAME[trans_z]/@units": "mm", + "AXISNAME[trans_z]/@vector": [ + 0, + 0, + 1 + ], + "AXISNAME[rot_y]": -115.0, + "AXISNAME[rot_y]/@depends_on": ".", + "AXISNAME[rot_y]/@transformation_type": "rotation", + "AXISNAME[rot_y]/@units": "degrees", + "AXISNAME[rot_y]/@vector": [ + 0, + 1, + 0 + ] + } + } + }, + "/ENTRY/INSTRUMENT[instrument]/ELECTRONANALYSER[electronanalyser]/COLLECTIONCOLUMN[collectioncolumn]": { + "projection": "@attrs:metadata/instrument/analyzer/projection", + "scheme": "momentum dispersive", + "lens_mode": "@attrs:metadata/instrument/analyzer/lens_mode", + "extractor_voltage": "@attrs:metadata/file/KTOF:Lens:Extr:V", + "extractor_voltage/@units": "V", + "extractor_current": "@attrs:metadata/file/KTOF:Lens:Extr:I", + "extractor_current/@units": "µA", + "working_distance": 4.0, + "working_distance/@units": "mm", + "LENS_EM[lens_*{A,B,C,D,E,F,G,H,I,UCA,UFA,Foc}]": { + "name": "*", + "voltage": "@attrs:metadata/file/KTOF:Lens:*:V", + "voltage/@units": "V" + }, + "field_aperture": { + "shape": "@attrs:metadata/instrument/analyzer/fa_shape", + "size": "@attrs:metadata/instrument/analyzer/fa_size", + "size/@units": "µm", + "POSITIONER[fa_m1]": { + "value": "@attrs:metadata/file/KTOF:Apertures:m1.RBV", + "value/@units": "mm" + }, + "POSITIONER[fa_m2]": { + "value": "@attrs:metadata/file/KTOF:Apertures:m2.RBV", + "value/@units": "mm" + } + }, + "contrast_aperture": { + "shape": "@attrs:metadata/instrument/analyzer/ca_shape", + "size": "@attrs:metadata/instrument/analyzer/ca_size", + "size/@units": "µm", + "POSITIONER[ca_m3]": { + "value": "@attrs:metadata/file/KTOF:Apertures:m3.RBV", + "value/@units": "mm" + } + } + }, + "/ENTRY/INSTRUMENT[instrument]/ELECTRONANALYSER[electronanalyser]/ENERGYDISPERSION[energydispersion]": { + "pass_energy": "@attrs:metadata/file/KTOF:Lens:TOF:V", + "pass_energy/@units": "eV", + "scheme": "tof", + "tof_distance": 0.9, + "tof_distance/@units": "m" + }, + "/ENTRY/INSTRUMENT[instrument]/ELECTRONANALYSER[electronanalyser]/DETECTOR[detector]": { + "amplifier_type": "MCP", + "detector_type": "DLD", + "sensor_pixels": [ + 1800, + 1800 + ], + "sensor_pixels/@units": "", + "amplifier_bias": "@attrs:metadata/file/KTOF:Lens:MCPfront:V", + "amplifier_bias/@units": "V", + "amplifier_voltage": "@attrs:metadata/file/KTOF:Lens:MCPback:V", + "amplifier_voltage/@units": "V", + "detector_voltage": "@attrs:metadata/file/KTOF:Lens:UDLD:V", + "detector_voltage/@units": "V" + }, + "/ENTRY/INSTRUMENT[instrument]/sourceTYPE[source_probe]": { + "name": "HHG @ TR-ARPES @ FHI", + "probe": "photon", + "type": "HHG laser", + "mode": "Single Bunch", + "frequency": "@attrs:metadata/instrument/beam/probe/frequency", + "frequency/@units": "kHz", + "associated_beam": "/entry/instrument/beam_probe" + }, + "/ENTRY/INSTRUMENT[instrument]/beamTYPE[beam_probe]": { + "distance": 0.0, + "distance/@units": "mm", + "incident_energy": "@attrs:metadata/instrument/beam/probe/incident_energy", + "incident_energy/@units": "eV", + "incident_energy_spread": "@attrs:metadata/instrument/beam/probe/incident_energy_spread", + "incident_energy_spread/@units": "eV", + "pulse_duration": "@attrs:metadata/instrument/beam/probe/pulse_duration", + "pulse_duration/@units": "fs", + "incident_polarization": "@attrs:metadata/instrument/beam/probe/incident_polarization", + "incident_polarization/@units": "V^2/mm^2", + "extent": "@attrs:metadata/instrument/beam/probe/extent", + "extent/@units": "µm", + "associated_source": "/entry/instrument/source_probe" + }, + "/ENTRY/INSTRUMENT[instrument]/sourceTYPE[source_pump]": { + "name": "OPCPA @ TR-ARPES @ FHI", + "probe": "visible light", + "type": "Optical Laser", + "mode": "Single Bunch", + "frequency": "@attrs:metadata/instrument/beam/pump/frequency", + "frequency/@units": "kHz", + "associated_beam": "/entry/instrument/beam_pump" + }, + "/ENTRY/INSTRUMENT[instrument]/beamTYPE[beam_pump]": { + "distance": 0.0, + "distance/@units": "mm", + "incident_energy": "@attrs:metadata/instrument/beam/pump/incident_energy", + "incident_energy/@units": "eV", + "incident_energy_spread": "@attrs:metadata/instrument/beam/pump/incident_energy_spread", + "incident_energy_spread/@units": "eV", + "incident_wavelength": "@attrs:metadata/instrument/beam/pump/incident_wavelength", + "incident_wavelength/@units": "nm", + "pulse_duration": "@attrs:metadata/instrument/beam/pump/pulse_duration", + "pulse_duration/@units": "fs", + "incident_polarization": "@attrs:metadata/instrument/beam/pump/incident_polarization", + "incident_polarization/@units": "V^2/mm^2", + "pulse_energy": "@attrs:metadata/instrument/beam/pump/pulse_energy", + "pulse_energy/@units": "µJ", + "average_power": "@attrs:metadata/instrument/beam/pump/average_power", + "average_power/@units": "mW", + "extent": "@attrs:metadata/instrument/beam/pump/extent", + "extent/@units": "µm", + "fluence": "@attrs:metadata/instrument/beam/pump/fluence", + "fluence/@units": "mJ/cm^2", + "associated_source": "/entry/instrument/source_pump" + }, + "/ENTRY/INSTRUMENT[instrument]/MANIPULATOR[manipulator]": { + "temperature_sensor": { + "name": "sample_temperature", + "measurement": "temperature", + "value": "@attrs:metadata/file/trARPES:Carving:TEMP_RBV", + "value/@units": "K" + }, + "sample_bias_voltmeter": { + "name": "sample_bias", + "measurement": "voltage", + "value": "@attrs:metadata/file/KTOF:Lens:Sample:V", + "value/@units": "V" + }, + "depends_on": "/entry/instrument/manipulator/transformations/trans_z", + "TRANSFORMATIONS[transformations]": { + "AXISNAME[trans_z]": -0.32, + "AXISNAME[trans_z]/@depends_on": "rot_z", + "AXISNAME[trans_z]/@transformation_type": "translation", + "AXISNAME[trans_z]/@units": "m", + "AXISNAME[trans_z]/@vector": [ + 0, + 0, + 1 + ], + "AXISNAME[rot_z]/@depends_on": "rot_x", + "AXISNAME[rot_z]": -25.0, + "AXISNAME[rot_z]/@transformation_type": "rotation", + "AXISNAME[rot_z]/@units": "degrees", + "AXISNAME[rot_z]/@vector": [ + 0, + 0, + 1 + ], + "AXISNAME[rot_x]/@depends_on": ".", + "AXISNAME[rot_x]": -90.0, + "AXISNAME[rot_x]/@transformation_type": "rotation", + "AXISNAME[rot_x]/@units": "degrees", + "AXISNAME[rot_x]/@vector": [ + 1, + 0, + 0 + ] + } + }, + "/ENTRY/SAMPLE[sample]": { + "preparation_date": "@attrs:metadata/sample/preparation_date", + "history/notes/type": "text/plain", + "history/notes/description": "@attrs:metadata/sample/sample_history", + "description": "@attrs:metadata/sample/chemical_formula", + "name": "@attrs:metadata/sample/chemical_formula", + "situation": "vacuum", + "SUBSTANCE[substance]/molecular_formula_hill": "@attrs:metadata/sample/chemical_formula", + "temperature_env": { + "temperature_sensor": "@link:/entry/instrument/manipulator/temperature_sensor" + }, + "gas_pressure_env": { + "pressure_gauge": "@link:/entry/instrument/pressure_gauge" + }, + "bias_env": { + "voltmeter": "@link:/entry/instrument/manipulator/sample_bias_voltmeter" + }, + "depends_on": "/entry/sample/transformations/corrected_phi", + "TRANSFORMATIONS[transformations]": { + "AXISNAME[corrected_phi]/@depends_on": "rot_omg", + "AXISNAME[corrected_phi]": 90.0, + "AXISNAME[corrected_phi]/@units": "degrees", + "AXISNAME[corrected_phi]/@transformation_type": "rotation", + "AXISNAME[corrected_phi]/@vector": [ + 0, + 1, + 0 + ], + "AXISNAME[rot_omg]/@depends_on": "rot_phi", + "AXISNAME[rot_omg]": "@attrs:metadata/file/trARPES:Carving:OMG.RBV", + "AXISNAME[rot_omg]/@units": "degrees", + "AXISNAME[rot_omg]/@transformation_type": "rotation", + "AXISNAME[rot_omg]/@vector": [ + 1, + 0, + 0 + ], + "AXISNAME[rot_phi]/@depends_on": "rot_tht", + "AXISNAME[rot_phi]": "@attrs:metadata/file/trARPES:Carving:PHI.RBV", + "AXISNAME[rot_phi]/@units": "degrees", + "AXISNAME[rot_phi]/@transformation_type": "rotation", + "AXISNAME[rot_phi]/@vector": [ + 0, + 1, + 0 + ], + "AXISNAME[rot_tht]/@depends_on": "trans_z", + "AXISNAME[rot_tht]": "@attrs:metadata/file/trARPES:Carving:THT.RBV", + "AXISNAME[rot_tht]/@units": "degrees", + "AXISNAME[rot_tht]/@transformation_type": "rotation", + "AXISNAME[rot_tht]/@vector": [ + 0, + 0, + 1 + ], + "AXISNAME[trans_z]/@depends_on": "trans_y", + "AXISNAME[trans_z]": "@attrs:metadata/file/trARPES:Carving:TRZ.RBV", + "AXISNAME[trans_z]/@units": "mm", + "AXISNAME[trans_z]/@transformation_type": "translation", + "AXISNAME[trans_z]/@vector": [ + 0, + 0, + 1 + ], + "AXISNAME[trans_y]/@depends_on": "trans_x", + "AXISNAME[trans_y]": "@attrs:metadata/file/trARPES:Carving:TRY.RBV", + "AXISNAME[trans_y]/@units": "mm", + "AXISNAME[trans_y]/@transformation_type": "translation", + "AXISNAME[trans_y]/@vector": [ + 0, + 1, + 0 + ], + "AXISNAME[trans_x]/@depends_on": "/entry/instrument/manipulator/transformations/trans_z", + "AXISNAME[trans_x]": "@attrs:metadata/file/trARPES:Carving:TRX.RBV", + "AXISNAME[trans_x]/@units": "mm", + "AXISNAME[trans_x]/@transformation_type": "translation", + "AXISNAME[trans_x]/@vector": [ + 1, + 0, + 0 + ] + } + }, + "/ENTRY/PROCESS_MPES[process]/DISTORTION[distortion]": { + "symmetry": "@attrs:metadata/momentum_correction/rotsym", + "symmetry/@units": "", + "original_centre": "@attrs:metadata/momentum_correction/pcent", + "original_centre/@units": "", + "original_points": "@attrs:metadata/momentum_correction/pouter", + "original_points/@units": "", + "cdeform_field": "@attrs:metadata/momentum_correction/cdeform_field", + "cdeform_field/@units": "", + "rdeform_field": "@attrs:metadata/momentum_correction/rdeform_field", + "rdeform_field/@units": "" + }, + "/ENTRY/PROCESS_MPES[process]/REGISTRATION[registration]": { + "depends_on": "/entry/process/registration/transformations/rot_z", + "TRANSFORMATIONS[transformations]": { + "AXISNAME[trans_x]": "@attrs:metadata/momentum_correction/adjust_params/xtrans", + "AXISNAME[trans_x]/@transformation_type": "translation", + "AXISNAME[trans_x]/@units": "pixels", + "AXISNAME[trans_x]/@vector": "@attrs:metadata/momentum_correction/adjust_params/x_vector", + "AXISNAME[trans_x]/@depends_on": ".", + "AXISNAME[trans_y]": "@attrs:metadata/momentum_correction/adjust_params/ytrans", + "AXISNAME[trans_y]/@units": "pixels", + "AXISNAME[trans_y]/@transformation_type": "translation", + "AXISNAME[trans_y]/@vector": "@attrs:metadata/momentum_correction/adjust_params/y_vector", + "AXISNAME[trans_y]/@depends_on": "trans_x", + "AXISNAME[rot_z]": "@attrs:metadata/momentum_correction/adjust_params/angle", + "AXISNAME[rot_z]/@units": "degrees", + "AXISNAME[rot_z]/@transformation_type": "rotation", + "AXISNAME[rot_z]/@offset": "@attrs:metadata/momentum_correction/adjust_params/offset", + "AXISNAME[rot_z]/@vector": "@attrs:metadata/momentum_correction/adjust_params/rotation_vector", + "AXISNAME[rot_z]/@depends_on": "trans_y" + } + }, + "/ENTRY/PROCESS_MPES[process]/energy_calibration":{ + "coefficients": "@attrs:metadata/energy_correction/calibration/coefficients", + "coefficients/@units": "", + "fit_function": "@attrs:metadata/energy_correction/calibration/fit_function", + "original_axis": "@attrs:metadata/energy_correction/tof", + "original_axis/@units": "ns", + "calibrated_axis": "@attrs:metadata/energy_correction/calibration/axis", + "calibrated_axis/@units": "eV", + "physical_quantity": "energy" + }, + "/ENTRY/PROCESS_MPES[process]/CALIBRATION[kx_calibration]": { + "scaling": "@attrs:metadata/momentum_correction/calibration/scale_kx", + "scaling/@units": "", + "offset": "@attrs:metadata/momentum_correction/offset_kx", + "offset/@units": "", + "calibrated_axis": "@attrs:metadata/momentum_correction/calibration/axis_kx", + "calibrated_axis/@units": "1/angstrom", + "physical_quantity": "momentum" + }, + "/ENTRY/PROCESS_MPES[process]/CALIBRATION[ky_calibration]": { + "scaling": "@attrs:metadata/momentum_correction/calibration/scale_ky", + "scaling/@units": "", + "offset": "@attrs:metadata/momentum_correction/offset_ky", + "offset/@units": "", + "calibrated_axis": "@attrs:metadata/momentum_correction/calibration/axis_ky", + "calibrated_axis/@units": "1/angstrom", + "physical_quantity": "momentum" + }, + "/ENTRY/data": { + "@axes": "@data:dims", + "@*_indices": "@data:*.index", + "@signal": "data", + "data": "@data:data", + "data/@units": "counts", + "*": "@data:*.data", + "*/@units": "@data:*.unit", + "energy/@type": "binding" + } +} \ No newline at end of file