{ "cells": [ { "cell_type": "markdown", "id": "b570aefb-f909-4779-ad1d-f37cdc42df78", "metadata": {}, "source": [ "# Example: Inspecting a NeXus file\n", "\n", "To demonstrate that the `h5rdmtoolbox` works with [NeXus](https://manual.nexusformat.org/fileformat.html) files, we download a file and inspect it. Note that by \"works\" we don't mean that the data model of NeXus is understood by the toolbox. Rather, we want to demonstrate that we can identify specific data in the file, plot it, and apply a minimal example of convention and layout validation that we will quickly design here." ] }, { "cell_type": "code", "execution_count": 1, "id": "ce843cf0-50f9-4f7f-9160-2fcae3425503", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Failed to import module h5tbx\n" ] } ], "source": [ "import h5rdmtoolbox as h5tbx" ] }, { "cell_type": "markdown", "id": "c9f2432b-cd6a-40a2-ae7a-9eae5010de7d", "metadata": {}, "source": [ "## 1. Get the file" ] }, { "cell_type": "code", "execution_count": 2, "id": "4f6cf57c-dfcc-4ebc-9c6f-b84214c724e0", "metadata": {}, "outputs": [], "source": [ "import requests\n", "import pathlib\n", "\n", "if not pathlib.Path('file.nxs').exists():\n", " r = requests.get('https://github.com/nexusformat/exampledata/raw/master/Soleil/hdf5/file_1.nxs')\n", " with open('file.nxs', 'wb') as f:\n", " f.write(r.content)" ] }, { "cell_type": "markdown", "id": "4c3f18be-ce47-4fec-a061-b6f6ba7c27f9", "metadata": {}, "source": [ "## 2. Visit (Dump) the file" ] }, { "cell_type": "code", "execution_count": 3, "id": "8c16217f-d920-4dc4-b4c5-5b46a2aab5f9", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "C:\\Users\\Matthias\\Documents\\programming\\GitHub\\h5RDMtoolbox\\h5rdmtoolbox\\_repr.py:552: RuntimeWarning: Cannot decode attribute value for units\n", " warnings.warn(f'Cannot decode attribute value for {name}', RuntimeWarning)\n" ] }, { "data": { "text/html": [ "\n", "
\n", "\n", " \n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "h5tbx.dump('file.nxs')" ] }, { "cell_type": "markdown", "id": "029b7205-24c5-4a05-b050-28882d9adf5c", "metadata": {}, "source": [ "## 3. Find and plot data" ] }, { "cell_type": "code", "execution_count": 4, "id": "b32486e0-b3e2-4973-97fc-c3d8c55b6e55", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "obj = h5tbx.database.FileDB('file.nxs').find_one({'$name': {'$basename': 'image#5'}}, \n", " recursive=True)\n", "obj" ] }, { "cell_type": "code", "execution_count": 5, "id": "0622160c-643e-4d6d-b3c5-949300179ace", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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ePFiDBo0qMXuQ0TUmphUEbVBlZWVmD59Ojp06ICuXbtixYoVZuW/n/6TyWR47733MGHCBLRr1w79+vVDRkYGvv/+e4wePRrt27fHyJEjce7cuSbdv2fPnli9ejWmT58OlUol5aMREdkMkyqiNmjevHk4ePAgPv30U3zxxRc4cOAATp48edtrXn31VUyfPh3Z2dno27cvnnzySfz973/HokWLcOLECQiCgOjo6FZ6AiIi++Ns6wYQUeuqqKjABx98gH/9618YM2YMAGDLli3o1q3bba+bMWMG/vrXvwIAFixYAK1Wi5dffhk6nQ4AMHfuXMyYMaNlG09EZMc4UkXUxpw7dw41NTUICgoSz3l5eaFPnz63vW7gwIHiz2q1GgAwYMAAs3NVVVUwGAwSt5iIyDEwqSKiJnFxcRF/lslktzxnMplat2FERHaCSRVRG3PPPffAxcUFmZmZ4rkrV67gzJkzNmwVEZHj45oqojamQ4cOiIyMxLx589CpUyd4e3vjpZdeglzeuv+NlZ2dDeD6Gq9Lly4hOzsbCoUC/v7+rdoOIiKpMKkiaoPeeustVFRUYOLEifDw8MDzzz+P8vLyVm3DkCFDxJ+zsrKQnJyMHj164IcffmjVdhARSUUmCIJg60YQEREROTquqSIiIiKSAJMqIpLcfffdhw4dOjR6bN261dbNIyJqEZz+IyLJ/fjjj6itrW20TK1Ww8PDo5VbRETU8phUEREREUmA039EREREEmBSRURERCQBJlVEREREEmBSRURERCQBJlVEREREEmBSRURERCQBJlVEREREEmBSRURERCSB/w9XzR3OTN84VwAAAABJRU5ErkJggg==", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "obj.data[()].plot() # note, we can access children (e.g. dataset \"data\") of the (lazy) group" ] }, { "cell_type": "markdown", "id": "5d09cfc4-04db-4695-a007-228be364de6d", "metadata": {}, "source": [ "## 4. Write a standard attribute for timestamp\n", "\n", "If you carefully check the `dump` output, you will find, that all numeric (!) datasets have the attribute \"timestamp\". All of them? Well, let's write a convention, which defines that providing the attribute \"timestamp\" with every numeric dataset is *required*. The timestamp value must have a specific format.\n", "\n", "Let's create the standard name first:" ] }, { "cell_type": "markdown", "id": "3f039604-3b60-40cc-8316-34ab68a485f2", "metadata": {}, "source": [ "### 4.1 Standard Name \"timestamp\"" ] }, { "cell_type": "code", "execution_count": 6, "id": "5394bd5c-e6b0-4466-9f8b-fba8f6bd9b85", "metadata": {}, "outputs": [], "source": [ "from h5rdmtoolbox.convention import StandardAttribute\n", "\n", "from pydantic import BaseModel, ValidationError\n", "from pydantic.functional_validators import AfterValidator, Annotated\n", "from datetime import datetime\n", "from typing import Union\n", "\n", "def parse_datetime(v: Union[str, datetime]) -> str:\n", " \"\"\"validation function used by the pydantic model class\"\"\"\n", " _format = '%Y-%m-%dT%H-%M-%S.%f'\n", " if isinstance(v, datetime):\n", " return v.strftime(_format)\n", " return datetime.strptime(v, _format).strftime(_format)\n", "\n", "class NexusTimeStampObject(BaseModel):\n", " \"\"\"The standard name table of the convention.\"\"\"\n", " value: Annotated[str, AfterValidator(parse_datetime)]\n", "\n", "NexusTimeStamp = StandardAttribute('timestamp',\n", " validator=NexusTimeStampObject,\n", " target_method='create_dataset',\n", " description='Timestamp of writing the data',\n", " default_value='$EMPTY')" ] }, { "cell_type": "markdown", "id": "e645e352-c821-461d-bd67-71450e07a1ce", "metadata": {}, "source": [ "### 4.2 Build the convention" ] }, { "cell_type": "code", "execution_count": 7, "id": "7376d8e1-ffd8-4cc6-9e12-850c6bc25aa8", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "using(\"nexus\")" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from h5rdmtoolbox.convention import Convention\n", "\n", "cv = Convention(name='nexus', contact=h5tbx.__author__)\n", "\n", "cv.add_standard_attribute(NexusTimeStamp)\n", "cv.register()\n", "\n", "h5tbx.use(cv)" ] }, { "cell_type": "markdown", "id": "672faf53-c581-4b9e-b3e2-bdc227def3d6", "metadata": {}, "source": [ "First test the convention on a temporary file:" ] }, { "cell_type": "code", "execution_count": 8, "id": "fefd1e02-3348-4b21-a3a7-a87a1cad7664", "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "\n", "
    \n", "
  • \n", " \n", " \n", " \n", "\n", "
      \n", "
    \n", "\n", "
      \n", " \n", " \n", " 4 [] (int32)\n", "
      • timestamp : 2008-10-23T15-09-39.175000
      • \n", "
      \n", "
    \n", "
  • \n", "
\n", "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "with h5tbx.File() as h5:\n", " h5.create_dataset('test', data=4, timestamp='2008-10-23T15-09-39.175')\n", " h5.dump()" ] }, { "cell_type": "code", "execution_count": 9, "id": "01d00671-9399-4bb4-8db3-e4066c6d0ee3", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Convention \"nexus\" expects standard attribute \"timestamp\" to be provided as an argument during dataset creation.\n" ] } ], "source": [ "# should raise an error due to NO timestamp\n", "with h5tbx.File() as h5:\n", " try:\n", " h5.create_dataset('test', data=4)\n", " except h5tbx.errors.StandardAttributeError as e:\n", " print(e)" ] }, { "cell_type": "code", "execution_count": 10, "id": "0c7e628b-71fb-4e63-80c9-a5bd918c8736", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Validation of \"2008 10 23 15-09-39.175\" for standard attribute \"timestamp\" failed.\n", "Expected fields: {'value': FieldInfo(annotation=str, required=True, metadata=[AfterValidator(func=)])}\n", "Pydantic error: 1 validation error for NexusTimeStampObject\n", "value\n", " Value error, time data '2008 10 23 15-09-39.175' does not match format '%Y-%m-%dT%H-%M-%S.%f' [type=value_error, input_value='2008 10 23 15-09-39.175', input_type=str]\n", " For further information visit https://errors.pydantic.dev/2.7/v/value_error\n" ] } ], "source": [ "# should raise an error due to a wrong timestamp\n", "with h5tbx.File() as h5:\n", " try:\n", " h5.create_dataset('test', data=4, timestamp='2008 10 23 15-09-39.175')\n", " except h5tbx.errors.StandardAttributeError as e:\n", " print(e)" ] }, { "cell_type": "markdown", "id": "1ab57e0d-7d2b-4996-9c1f-c1e360f19cd6", "metadata": {}, "source": [ "### 4.3 Validate the NeXus file based on the convention:\n", "\n", "We find, that two datasets in fact have no timestamp!" ] }, { "cell_type": "code", "execution_count": 11, "id": "90d253d5-42aa-4b31-86c7-e66dfa0752f9", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[MissingAttribute(/NDX3_00021_ND__DLPC__00001/duration, timestamp),\n", " MissingAttribute(/NDX3_00021_ND__DLPC__00001/run_number, timestamp)]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "invalid_objs = cv.validate('file.nxs')\n", "invalid_objs" ] }, { "cell_type": "markdown", "id": "4514f306-fa02-46ac-b7d4-aee844ac2979", "metadata": {}, "source": [ "Let's convince ourselves:" ] }, { "cell_type": "code", "execution_count": 12, "id": "d980b92c-8f16-4819-be68-a3701f05c8b7", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'missing!!!'" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "obj = h5tbx.database.FileDB('file.nxs').find_one({'$name': invalid_objs[0].object_name})\n", "obj.attrs.get('timestamp', 'missing!!!')" ] }, { "cell_type": "code", "execution_count": 13, "id": "9fa5b083-d897-42eb-a706-ba4e00dba8dc", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "using(\"h5py\")" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "h5tbx.use(None)" ] }, { "cell_type": "markdown", "id": "1a4323d2-94be-467b-bdae-55a3c6c7a5da", "metadata": {}, "source": [ "## 5. Validating the file structure with a layout definition\n", "\n", "The *structure* or *layout* defines which groups, datasets and attributes need to exist and in which arrangement. This cannot be defined/checked during file creation (using standard attributes).\n", "\n", "Let's define part of a potential layout for the NeXus file in words first and then write the code:\n", "1) **Ten datasets** starting with \"image#\" and ending with a number between 0 and 9\n", "2) The group **user** must exist, which has the datasets \"name\" with the attribute \"description\"\n", "\n", "The layout is defined by specifying queries, which correspond to what we are expecting in the file. If it is not found, the layout specification failed:" ] }, { "cell_type": "code", "execution_count": 21, "id": "87f4c34c-1450-4a56-a1f2-012ef2dc54cd", "metadata": {}, "outputs": [], "source": [ "from h5rdmtoolbox import layout\n", "\n", "lay = layout.Layout()\n", "\n", "# 1.) 10 images:\n", "spec_10images = lay.add(h5tbx.database.FileDB.find,\n", " flt={'$name': {'$regex': '.*/image#[0-9]$'}},\n", " n=10)\n", "\n", "# 2.) User group. Identify by attribute \"NX_class\":\n", "spec_userGroupExists = lay.add(h5tbx.database.FileDB.find,\n", " flt={'NX_class': b'NXuser'},\n", " n=None)\n", "\n", "# within the User group, find group \"name\":\n", "spec_UserName = spec_userGroupExists.add(\n", " h5tbx.database.ObjDB.find_one,\n", " flt={'$name': {'$basename': 'name'}},\n", " n=1\n", ")\n", "\n", "# within the Name group find dataset \"name\" with a certain \"description\":\n", "spec_UserNameDescription = spec_UserName.add(\n", " h5tbx.database.ObjDB.find_one,\n", " flt={'$name': {'$basename': 'name'}, 'description': b'Name of user responsible for this entry'}, # !binary string!\n", " n=1\n", ")" ] }, { "cell_type": "markdown", "id": "94421201-9568-4e64-a232-626b2a129253", "metadata": {}, "source": [ "Validate the file:" ] }, { "cell_type": "code", "execution_count": 22, "id": "4c2ed0ad-29cc-432a-b2bb-5bc698abd10f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "res = lay.validate('file.nxs')\n", "res.is_valid()" ] }, { "cell_type": "code", "execution_count": null, "id": "a8cf5e0d-4b18-4dfb-aaf3-cab0c6a0e486", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.8.19" } }, "nbformat": 4, "nbformat_minor": 5 }