{ "cells": [ { "metadata": {}, "cell_type": "markdown", "source": [ "# Tutorial 6: Experimental and Sample Metadata\n", "\n", "`pygid` supports metadata handling through the `ExpMetadata` and `SampleMetadata` classes.\n", "\n", "## Experimental Metadata\n", "\n", "`ExpMetadata` stores additional information about the experiment that is **not** used for coordinate calculations, such as experiment dates and source details.\n", "The structure is dictionary-like.\n", "\n", "This metadata is saved in the **`entry/instrument`** group of the NeXus file.\n", "\n", "If multiple `pygid.Conversion` results are saved into the **same NeXus entry**, the experimental metadata will be **overwritten**, except for fields listed in `extend_fields`.\n", "\n", "\n" ], "id": "d7abde7538c74fa5" }, { "metadata": { "ExecuteTime": { "end_time": "2026-02-09T17:21:26.863679Z", "start_time": "2026-02-09T17:21:24.598150Z" } }, "cell_type": "code", "source": "import pygid", "id": "a90e1b2fb2b7e088", "outputs": [], "execution_count": 1 }, { "metadata": { "ExecuteTime": { "end_time": "2026-02-09T17:21:27.635239Z", "start_time": "2026-02-09T17:21:27.631971Z" } }, "cell_type": "code", "source": [ "exp_metadata = pygid.ExpMetadata(\n", " start_time=\"2024-03-29T15:51:41.343788\",\n", " end_time=\"2024-07-12T08:26:22Z\",\n", " source_type=\"synchrotron\",\n", " source_name=\"ESRF ID10\",\n", " instrument_name=\"ID10-surf\",\n", " detector=\"eiger4m\",\n", " monitor=1.1e5, # optional\n", " extend_fields=[\"monitor\"] # fields appended instead of overwritten\n", ")" ], "id": "4451c0c3b7257e00", "outputs": [], "execution_count": 2 }, { "metadata": {}, "cell_type": "markdown", "source": [ "## Sample Metadata\n", "\n", "Sample-related information is handled by the **SampleMetadata** class.\n", "The input format is a nested dictionary, and the same structure is written to the entry/sample group in the NeXus file.\n", "\n", "We strongly recommend that the metadata include the sample name, structure, preparation description and\n", "experimental conditions via the **SampleMetadata** class. Users may further extend the sample group with custom fields, for example chemical formula, temperature, pressure, mass etc., as proposed by the\n", "[DAPHNE4NFDI](https://www.daphne4nfdi.de/english/) initiative in accordance with the [FAIR](https://www.nature.com/articles/sdata201618). Both metadata classes support formats such as strings, lists, integer or float\n", "values, and **NumPy** arrays\n" ], "id": "9e7e04eeaa07a515" }, { "metadata": { "ExecuteTime": { "end_time": "2026-02-09T17:21:29.443934Z", "start_time": "2026-02-09T17:21:29.439583Z" } }, "cell_type": "code", "source": [ "data = {\n", " \"name\": \"240306_DIP\",\n", " \"structure\": {\n", " \"stack\": \"air | DIP 0-25 | SiOx 1 | Si\",\n", " \"materials\": {\n", " \"DIP\": {\n", " \"name\": \"Diindenoperylene DIP\",\n", " \"thickness\": 25e-9, # optional\n", " \"cif\": \"DIP.cif\", # optional\n", " \"type\": \"gradient film\"\n", " },\n", " \"SiOx\": {\n", " \"name\": \"native SiOx\",\n", " \"thickness\": 1\n", " },\n", " \"Si\": {\n", " \"name\": \"Si wafer\"\n", " }\n", " }\n", " },\n", " \"preparation\": \"gradient thin film prepared by thermal evaporation\",\n", " \"experimental_conditions\": \"standard conditions, on air\"\n", "}\n", "\n", "smpl_metadata = pygid.SampleMetadata(data=data)\n" ], "id": "3875ec7f04d7be5e", "outputs": [], "execution_count": 3 }, { "metadata": {}, "cell_type": "markdown", "source": [ "## Saving and Loading Sample Metadata\n", "\n", "Sample metadata can be stored as a YAML file and reused for other conversions." ], "id": "c85a9b9b16d41b1d" }, { "metadata": {}, "cell_type": "markdown", "source": "Saving:", "id": "973460dd6b844d93" }, { "metadata": { "ExecuteTime": { "end_time": "2026-02-09T17:22:00.517907Z", "start_time": "2026-02-09T17:22:00.510409Z" } }, "cell_type": "code", "source": [ "smpl_metadata = pygid.SampleMetadata(\n", " path_to_save=\"sample.yaml\",\n", " data=data\n", ")" ], "id": "e9d4ad3db3307b14", "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO - Saved sample metadata to D:\\PhD\\mlgid\\pygid\\docs\\tutorials\\sample.yaml\n" ] } ], "execution_count": 6 }, { "metadata": {}, "cell_type": "markdown", "source": "Loading:", "id": "4e3841a34808974f" }, { "metadata": { "ExecuteTime": { "end_time": "2026-02-09T17:22:18.042671Z", "start_time": "2026-02-09T17:22:18.037008Z" } }, "cell_type": "code", "source": [ "smpl_metadata = pygid.SampleMetadata(\n", " path_to_load=\"sample.yaml\"\n", ")" ], "id": "60150b1b9c815e26", "outputs": [], "execution_count": 7 }, { "metadata": {}, "cell_type": "markdown", "source": "## Saving the Metadata in a NeXus file", "id": "50da3bd601d7bbab" }, { "metadata": {}, "cell_type": "markdown", "source": "Define the paths:", "id": "e0aed7cefc7e33bb" }, { "metadata": { "ExecuteTime": { "end_time": "2026-02-09T17:24:11.676535Z", "start_time": "2026-02-09T17:24:08.606555Z" } }, "cell_type": "code", "source": [ "from pygid.datasets import get_dataset\n", "\n", "# Download example dataset from Zenodo\n", "try:\n", " files = get_dataset(\"tutorial_06\")\n", " poni_path = files[\"poni\"]\n", " mask_path = files[\"mask\"]\n", " # several files for batch processing\n", " data_path = files[\"data\"]\n", "except:\n", " print(\"Dataset download skipped on Read the Docs.\")" ], "id": "4e3212668f26530", "outputs": [], "execution_count": 8 }, { "metadata": {}, "cell_type": "markdown", "source": "Make the conversion as described in Tutorials 1-5:", "id": "bf5287b1f6076cff" }, { "metadata": { "ExecuteTime": { "end_time": "2026-02-09T17:25:39.958572Z", "start_time": "2026-02-09T17:25:38.524938Z" } }, "cell_type": "code", "source": [ "import pygid\n", "\n", "params = pygid.ExpParams(\n", " poni_path=poni_path, # path to the PONI file\n", " mask_path=mask_path,\n", " ai=0.01, # angle of incidence (degrees)\n", " fliplr=True,\n", " flipud=True\n", ")\n", "\n", "matrix = pygid.CoordMaps(\n", " params, # pygid.ExpParams\n", " vert_positive=True,\n", " hor_positive=True,\n", ")\n", "\n", "analysis = pygid.Conversion(\n", " matrix=matrix, # pygid.CoordMaps\n", " path=data_path, # path to the raw data file\n", " dataset='/entry_0000/ESRF-ID10/eiger4m/data', # dataset path\n", " frame_num = 0,\n", ")\n", "\n", "analysis.det2q_gid(\n", " plot_result=False,\n", " save_result=True,\n", " path_to_save=\"result.h5\",\n", " smpl_metadata=smpl_metadata,\n", " exp_metadata=exp_metadata,\n", ")" ], "id": "c00644c7393ad8b9", "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO - Saved in D:\\PhD\\mlgid\\pygid\\docs\\tutorials\\result.h5 in group entry_0000\n" ] } ], "execution_count": 9 }, { "metadata": {}, "cell_type": "markdown", "source": "or after conversion using DataSaver:", "id": "8a7d43cb79d2e810" }, { "metadata": { "ExecuteTime": { "end_time": "2026-02-09T17:28:35.488241Z", "start_time": "2026-02-09T17:28:35.279014Z" } }, "cell_type": "code", "source": [ "# Run conversion without saving\n", "analysis.det2q_gid(save_result=False)\n", "\n", "# Save results to HDF5\n", "pygid.DataSaver(\n", " analysis, # pygid.Conversion instance\n", " path_to_save='result.h5', # path to save\n", " overwrite_file=True, # Whether to overwrite an existing HDF5 file\n", " overwrite_group=True, # Whether to overwrite an existing HDF5 entry\n", " smpl_metadata=smpl_metadata, # pygid.SampleMetadata\n", " exp_metadata=exp_metadata, # pygid.ExpMetadata\n", ")" ], "id": "11e9763dd6decc34", "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO - Saved in D:\\PhD\\mlgid\\pygid\\docs\\tutorials\\result.h5 in group entry_0000\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "execution_count": 11 } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.6" } }, "nbformat": 4, "nbformat_minor": 5 }