././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.8934543 nexusformat-2.0.0/0000755000077000000000000000000015060352601012433 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649549.0 nexusformat-2.0.0/.gitattributes0000644000077000000000000000124014777236515015346 0ustar00rosborn# Auto detect text files and perform LF normalization * text=auto # Source files # ============ *.pxd text *.py text *.py3 text *.pyw text *.pyx text *.xml text *.md text *.rst text *.bat text *.sh text *.yaml text *.cfg text *.ipynb text # Binary files # ============ *.nxs binary *.h5 binary *.db binary *.p binary *.pkl binary *.pyc binary *.pyd binary *.pyo binary *.png binary *.jpg binary *.jpeg binary *.gif binary *.tif binary *.tiff binary *.svg binary *.eps binary *.ico binary ././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.7589145 nexusformat-2.0.0/.github/0000755000077000000000000000000015060352601013773 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/.github/dependabot.yaml0000644000077000000000000000032314777236751017007 0ustar00rosborn--- version: 2 updates: - package-ecosystem: "pip" directory: "/" schedule: interval: "weekly" - package-ecosystem: "github-actions" directory: "/" schedule: interval: "weekly" ././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.7592764 nexusformat-2.0.0/.github/workflows/0000755000077000000000000000000015060352601016030 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1757344203.0 nexusformat-2.0.0/.github/workflows/ci.yml0000644000077000000000000000116215057570713017162 0ustar00rosbornname: CI on: [push, pull_request] jobs: build: runs-on: ${{ matrix.os }} strategy: matrix: python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] os: [ubuntu-latest, macOS-latest, windows-latest] steps: - uses: actions/checkout@v5 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | python -m pip install . python -m pip install pytest - name: Test with pytest run: | pytest ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649549.0 nexusformat-2.0.0/.gitignore0000644000077000000000000000112414777236515014444 0ustar00rosborn*.py[cod] # C extensions *.so # Packages *.egg *.egg-info dist build eggs parts bin var sdist develop-eggs .installed.cfg lib lib64 MANIFEST # Installer logs pip-log.txt # Unit test / coverage reports .coverage .tox nosetests.xml # Patch files *.patch # Translations *.mo # Mr Developer .mr.developer.cfg # OSX files .DS_Store .DS_Store? ._* .Spotlight-V100 .Trashes Icon? # PyCharm Files .idea # eclipse .settings .project .pydevproject # Emacs backup files *~ # Virtual Studio Code .vscode # setuptools_scm src/nexusformat/_version.py # miscellaneous system files .directoryhash ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/COPYING0000644000077000000000000000450614777236751013520 0ustar00rosbornLicensing Terms for NeXpy ------------------------- NeXpy is licensed under the terms of the Modified BSD License (also known as New or Revised BSD), as follows: Copyright (c) 2014-2025, NeXpy Development Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the NeXpy Development Team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. About the NeXpy Development Team ---------------------------------- The NeXpy Development Team is the set of all contributors to the NeXpy project on the Github at https://github.com/nexpy. The project is currently led by Ray Osborn. Copyright --------- The following banner should be used in any source code file to indicate the copyright and license terms: # ----------------------------------------------------------------------------- # Copyright (c) 2014-2025, NeXpy Development Team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING, distributed with this software. # ----------------------------------------------------------------------------- ././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.8930836 nexusformat-2.0.0/PKG-INFO0000644000077000000000000001373115060352601013535 0ustar00rosbornMetadata-Version: 2.4 Name: nexusformat Version: 2.0.0 Summary: Python API to access NeXus data Author-email: Raymond Osborn License: Licensing Terms for NeXpy ------------------------- NeXpy is licensed under the terms of the Modified BSD License (also known as New or Revised BSD), as follows: Copyright (c) 2014-2025, NeXpy Development Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the NeXpy Development Team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. About the NeXpy Development Team ---------------------------------- The NeXpy Development Team is the set of all contributors to the NeXpy project on the Github at https://github.com/nexpy. The project is currently led by Ray Osborn. Copyright --------- The following banner should be used in any source code file to indicate the copyright and license terms: # ----------------------------------------------------------------------------- # Copyright (c) 2014-2025, NeXpy Development Team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING, distributed with this software. # ----------------------------------------------------------------------------- Project-URL: Homepage, https://nexpy.github.io/nexpy Project-URL: Repository, https://github.com/nexpy/nexusformat.git Project-URL: Issues, https://github.com/nexpy/nexusformat/issues Project-URL: Documentation, https://nexpy.github.io/nexpy/pythonshell.html Project-URL: Changelog, https://github.com/nexpy/nexusformat/releases Keywords: data format,HDF5,neutron scattering,x-ray scattering Classifier: Development Status :: 5 - Production/Stable Classifier: License :: OSI Approved :: BSD License Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Science/Research Classifier: Topic :: Scientific/Engineering Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 Classifier: Topic :: Scientific/Engineering Classifier: Topic :: Scientific/Engineering :: Visualization Requires-Python: >=3.9 Description-Content-Type: text/markdown License-File: COPYING Requires-Dist: colored Requires-Dist: h5py Requires-Dist: hdf5plugin Requires-Dist: numpy Requires-Dist: packaging Requires-Dist: pygments Requires-Dist: python-dateutil Requires-Dist: scipy Requires-Dist: importlib_resources; python_version <= "3.9" Provides-Extra: testing Requires-Dist: pytest; extra == "testing" Dynamic: license-file Introduction ============ This package provides a Python API to open, create, and manipulate [NeXus data](http://www.nexusformat.org/) written in the HDF5 format. The 'nexusformat' package provides the underlying API for [NeXpy](http://nexpy.github.io/nexpy), which provides a GUI interface for visualizing and analyzing NeXus data. The latest development version is always available from [NeXpy's GitHub repository](https://github.com/nexpy/nexusformat). Installing and Running ====================== Released versions of `nexusformat` can be installed using either ``` $ pip install nexusformat ``` or, if you are in a conda environment:: ``` $ conda install -c conda-forge nexusformat ``` The source code can be downloaded from the NeXpy Git repository: ``` $ git clone http://github.com/nexpy/nexusformat.git ``` Prerequisites ============= The following libraries are used by the full installation of NeXpy. There is more details of the nature of these dependencies in the [NeXpy documentation](http://nexpy.github.io/nexpy). * h5py http://www.h5py.org * numpy http://numpy.org * scipy http://scipy.org User Support ============ Consult the [NeXpy documentation](http://nexpy.github.io/nexpy) for details of both the Python command-line API and how to use the NeXpy GUI. If you have any general questions concerning the use of NeXpy, please address them to the [NeXus Mailing List](http://download.nexusformat.org/doc/html/mailinglist.html). If you discover any bugs, please submit a [Github issue](https://github.com/nexpy/nexusformat/issues), preferably with relevant tracebacks. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649549.0 nexusformat-2.0.0/README.md0000644000077000000000000000320314777236515013733 0ustar00rosbornIntroduction ============ This package provides a Python API to open, create, and manipulate [NeXus data](http://www.nexusformat.org/) written in the HDF5 format. The 'nexusformat' package provides the underlying API for [NeXpy](http://nexpy.github.io/nexpy), which provides a GUI interface for visualizing and analyzing NeXus data. The latest development version is always available from [NeXpy's GitHub repository](https://github.com/nexpy/nexusformat). Installing and Running ====================== Released versions of `nexusformat` can be installed using either ``` $ pip install nexusformat ``` or, if you are in a conda environment:: ``` $ conda install -c conda-forge nexusformat ``` The source code can be downloaded from the NeXpy Git repository: ``` $ git clone http://github.com/nexpy/nexusformat.git ``` Prerequisites ============= The following libraries are used by the full installation of NeXpy. There is more details of the nature of these dependencies in the [NeXpy documentation](http://nexpy.github.io/nexpy). * h5py http://www.h5py.org * numpy http://numpy.org * scipy http://scipy.org User Support ============ Consult the [NeXpy documentation](http://nexpy.github.io/nexpy) for details of both the Python command-line API and how to use the NeXpy GUI. If you have any general questions concerning the use of NeXpy, please address them to the [NeXus Mailing List](http://download.nexusformat.org/doc/html/mailinglist.html). If you discover any bugs, please submit a [Github issue](https://github.com/nexpy/nexusformat/issues), preferably with relevant tracebacks. ././@PaxHeader0000000000000000000000000000005400000000000010214 xustar0017 gid=660979062 27 mtime=1757533568.760453 nexusformat-2.0.0/conda-recipe/0000755000077000000000000000000015060352601014764 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1516999012.0 nexusformat-2.0.0/conda-recipe/bld.bat0000644000077000000000000000006313232710544016217 0ustar00rosborn"%PYTHON%" setup.py install if errorlevel 1 exit 1 ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1516999012.0 nexusformat-2.0.0/conda-recipe/build.sh0000644000077000000000000000014713232710544016424 0ustar00rosborn#!/bin/bash $PYTHON setup.py install --single-version-externally-managed --record installed_files.txt ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1745963862.0 nexusformat-2.0.0/conda-recipe/meta.yaml0000644000077000000000000000167015004245526016607 0ustar00rosbornpackage: name: nexusformat version: "2.0.0" source: git_url: https://github.com/nexpy/nexusformat.git git_tag: v2.0.0 build: entry_points: - nexusformat = nexusformat.scripts.nexusformat:main - nxcheck = nexusformat.scripts.nxcheck:main - nxconsolidate = nexusformat.scripts.nxconsolidate:main - nxdir = nexusformat.scripts.nxdir:main - nxduplicate = nexusformat.scripts.nxduplicate:main - nxinspect = nexusformat.scripts.nxinspect:main - nxstack = nexusformat.scripts.nxstack:main number: 0 requirements: build: - python >=3.9 - setuptools - setuptools_scm run: - python >=3.9 - colored - h5py - hdf5plugin - numpy - packaging - pygments - python-dateutil - scipy test: commands: - nexusformat --version - pytest about: home: http://nexpy.github.io/nexusformat/ license: BSD License summary: 'nexusformat: Python API to access NeXus data' ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1757533274.0 nexusformat-2.0.0/pyproject.toml0000644000077000000000000000434715060352132015356 0ustar00rosborn[build-system] requires = ["setuptools >= 64", "setuptools_scm >= 8"] build-backend = "setuptools.build_meta" [project] name = "nexusformat" dynamic = ["version"] description = "Python API to access NeXus data" readme = "README.md" license = {file = "COPYING"} authors = [{name = "Raymond Osborn", email = "rayosborn@mac.com"}] classifiers = [ "Development Status :: 5 - Production/Stable", "License :: OSI Approved :: BSD License", "Intended Audience :: Developers", "Intended Audience :: Science/Research", "Topic :: Scientific/Engineering", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Topic :: Scientific/Engineering", "Topic :: Scientific/Engineering :: Visualization", ] keywords = ["data format", "HDF5", "neutron scattering", "x-ray scattering"] requires-python = ">=3.9" dependencies = [ "colored", "h5py", "hdf5plugin", "numpy", "packaging", "pygments", "python-dateutil", "scipy", "importlib_resources; python_version <= '3.9'", ] [project.optional-dependencies] testing = ["pytest"] [project.urls] Homepage = "https://nexpy.github.io/nexpy" Repository = "https://github.com/nexpy/nexusformat.git" Issues = "https://github.com/nexpy/nexusformat/issues" Documentation = "https://nexpy.github.io/nexpy/pythonshell.html" Changelog = "https://github.com/nexpy/nexusformat/releases" [project.scripts] nexusformat = "nexusformat.scripts.nexusformat:main" nxcheck = "nexusformat.scripts.nxcheck:main" nxconsolidate = "nexusformat.scripts.nxconsolidate:main" nxdir = "nexusformat.scripts.nxdir:main" nxduplicate = "nexusformat.scripts.nxduplicate:main" nxinspect = "nexusformat.scripts.nxinspect:main" nxstack = "nexusformat.scripts.nxstack:main" [tool.setuptools_scm] version_file = "src/nexusformat/_version.py" [tool.setuptools.package-data] "nexusformat.definitions.applications" = ["*.nxdl.xml"] "nexusformat.definitions.base_classes" = ["*.nxdl.xml"] "nexusformat.definitions.contributed_definitions" = ["*.nxdl.xml"] "nexusformat.examples" = ["*.nxs", "*.h5"] "nexusformat.notebooks" = ["*.pnyb"] ././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.8935204 nexusformat-2.0.0/setup.cfg0000644000077000000000000000004615060352601014254 0ustar00rosborn[egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.7539754 nexusformat-2.0.0/src/0000755000077000000000000000000015060352601013222 5ustar00rosborn././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.7614493 nexusformat-2.0.0/src/nexusformat/0000755000077000000000000000000015060352601015575 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649549.0 nexusformat-2.0.0/src/nexusformat/__init__.py0000644000077000000000000000061314777236515017731 0ustar00rosborn# ----------------------------------------------------------------------------- # Copyright (c) 2013-2021, NeXpy Development Team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING, distributed with this software. # ----------------------------------------------------------------------------- from ._version import version as __version__ ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1757533568.0 nexusformat-2.0.0/src/nexusformat/_version.py0000644000077000000000000000131015060352600017765 0ustar00rosborn# file generated by setuptools-scm # don't change, don't track in version control __all__ = [ "__version__", "__version_tuple__", "version", "version_tuple", "__commit_id__", "commit_id", ] TYPE_CHECKING = False if TYPE_CHECKING: from typing import Tuple from typing import Union VERSION_TUPLE = Tuple[Union[int, str], ...] COMMIT_ID = Union[str, None] else: VERSION_TUPLE = object COMMIT_ID = object version: str __version__: str __version_tuple__: VERSION_TUPLE version_tuple: VERSION_TUPLE commit_id: COMMIT_ID __commit_id__: COMMIT_ID __version__ = version = '2.0.0' __version_tuple__ = version_tuple = (2, 0, 0) __commit_id__ = commit_id = 'g8bee8633d' ././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.7645905 nexusformat-2.0.0/src/nexusformat/definitions/0000755000077000000000000000000015060352601020110 5ustar00rosborn././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.7836728 nexusformat-2.0.0/src/nexusformat/definitions/applications/0000755000077000000000000000000015060352601022576 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXapm.nxdl.xml0000644000077000000000000030222615046415443025324 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Number of hit qualities, the so-called hit types, distinguished. Number of delay-line-detector (DLD) wires of the detector. Number of bins used in the mass-to-charge-state-ratio spectrum. Number of pulses collected in between start_time and end_time resolved by an instance of :ref:`NXevent_data_apm`. If this is not defined, p is the number of ions included in the reconstructed volume if the application definition is used to store results of an already reconstructed dataset. Number of pulses returned by the hit_finding algorithm. Neither necessarily equal to p nor to n. Number of ions spatially filtered from results of the hit_finding algorithm from which an instance of a reconstructed volume has been generated. These ions get new identifier assigned in the process, the so-called evaporation_id. This identifier must not be confused with the pulse_id. This value is typically smaller than both p and p_out. Number of mass resolution values. Application definition for real or simulated atom probe and field-ion microscopy experiments. Atom probe tomography and field-ion microscopy are methods for characterizing materials through induced controlled extraction of individual atoms as ions and molecular ions from a sharp needle-shaped specimen. Offering isotopic and nanometer-scale resolution, atom probe data enable quantification of local chemical composition and computing of volumetric reconstructions which are models for the atomic architecture of the small specimen volume analyzed. These reconstructions provide input for characterization of atomic segregation at crystal defects. The term microstructural features is considered as a narrow synonym for crystal defects. The aim of the NXapm application definition is to provide a general yet specific enough solution to serialize artifacts for virtually all atom probe and field-ion microcopy experiments. Before summarizing the design of the base classes and the parts of the NXapm application definition, it is worthwhile to recall and distinguish concepts that are related to atom extraction events and the molecular ions that are frequently generated by the sequence of events: * An atom probe instrument uses laser or voltage pulsing events to trigger ion extraction events. * These ions are accelerated in an electric field towards a position-sensitive detector system. Physical events and corresponding signal on this detector is triggered by an ion hitting the detector. Some of these events are not necessarily caused by or directly correlated with an identifiable pulsing event. * Note that only a part the specimen volume can be measured and finite detection efficiency means that not all atoms in the measured volume will be detected. Neutral atoms can escape detection. Some ions escape detection because they hit into walls of the analysis_chamber. Raw data are typically processed as follows: * Detector pulses and their timing are processed and discriminated into signal events of different quality levels. High quality events might be considered in further processing to identify the corresponding molecular ion and its original position in the reconstructed volume. * Signal calibration and filtering steps are applied to convert raw time-of-flight data to calibrated mass-to-charge state ratio values and obtain calibrated impact positions on the detector. * Ranging and identifying an ion that corresponds to each detector event. Isotopic abundance and theoretical models inform these ranging algorithms. * Finally, such selected ion impact positions and iontypes are used to compute a reconstructed volume of the specimen using backprojection algorithms. In effect, an atom probe measurement is a combination of a data acquisition and a data analysis workflow. Not only in AMETEK/Cameca's APSuite/IVAS software, which the majority of atom probers use, these concepts are well distinguished. However, the algorithms used to transform correlations between pulses and physical events into actual events, the so-called detector hits of ions, is a proprietary one. This algorithm is also referred to as the hit finding algorithm. Due to this practical inaccessibility of details, virtually all atom probe studies currently use a reporting schema where the course of the specimen evaporation is documented such that quantities are a function of evaporation_id i.e. actual event/ion, i.e. after having the hit finding algorithm and correlations applied. That is the evaporation_id values take the role of an implicit time and course of the experiment given that ion extraction physically is a sequential process. This application definition includes fields that the atom probe community has decided to represent best practices for reporting atom probe measurements. Exemplar mapping tables are provided for documents that reported these best practices to translate technical term into concepts of the NXapm application definition. *The NeXus application definition NXapm defines a hierarchical data model with ten building blocks:* The data model represents a tree of concepts. The tree is constructed from groups of concepts representing the branches, together with fields and attributes representing leaves. NXapm is defined by composing and specializing base classes into the following ten categories: - The field ``definition`` specifies that the data schema is NXapm. In combination with administrative metadata such as the attribute ``NeXus_version`` provided by :ref:`NXroot` this specifies which version of NXapm the instance data in a NeXus/HDF5 file are compliant with. - The fields ``run_number``, ``experiment_alias``, ``experiment_description`` and the group ``userID`` provide concepts for storing organizational metadata that contextualize the work within the research workflow and humans involved in this. - The fields ``start_time``, ``end_time`` provide concepts for framing a temporal context for the research. - The groups ``citeID``, ``noteID`` provide concepts for adding contextual details such as citations or notes that are associated with the data, i.e. other artifacts that are deemed relevant when reporting about a measurement or simulation. These groups are useful when NXapm is used as a serialization format for technology-partner-agnostic archival of data and metadata that have been collected during a session with an atom probe instrument. The terms run and session are understood as exact synonyms that refer to an uninterrupted period of measurement. Resuming measurement on a specimen after an interruption is viewed as a new run and the new data should not be appended to the previous run, but written to either a new NXentry, or a new file. Removing the specimen from the instrument is an interruption. Changing evaporation conditions while the specimen is remains in the analysis_chamber and resuming thereafter the measurement is not considered as an interruption. It is a common strategy to probe the evaporation process for different instrument parameters. Each individual collection should then though be stored in an own NXevent_data_apm group. Parking the specimen to the buffer_chamber and resuming the measurement at a later stage is an interruption. During a run, the microscope is used for a certain amount of time to characterize a single specimen. - The groups ``sample`` and ``specimen`` provide concepts for storing metadata about the sample and the specimen, i.e. the smaller part that was removed from the sample to be measured in the atom probe session. The term "tip" in the context of atom probe research is considered jargon. Specimen is an exact synonym for tip. - The field ``operation_mode`` and group ``measurement`` provides concepts that are useful for describing a measurement during a session with an atom probe or field-ion microscope. This includes the chain of events of data and metadata that were collected during such a session. - The group ``simulation`` provides concepts that are useful for describing a simulation of an atom extraction, ionization, and ion trajectory simulation. Combined with ``measurement`` this provides a data schema for defining a digital twin of the instrument and its setup. - The groups ``consistent_rotations``, and ``NAMED_reference_frame`` provide concepts for reporting coordinate systems (frames of reference) and rotation conventions that clarify how data should be interpreted specifying the rotation of orientable objects in the microscope, its components, or of crystals and crystal defects in the material analyzed. - The group ``atom_probeID`` provides concepts for the computational workflows that were used to convert raw detector data into reconstructed ion positions and documentation of ranging definitions made. - The group ``profiling`` provides concepts for reporting computational details such as programs and libraries used, for documenting the libraries of virtual environments such as those used by conda or python virtual environment, including details about the computing hardware used, and documenting capabilities for performance analyses and benchmarking of the software or its parts. *Design choices:* Given that most atom probe instruments across the globe were built by AMETEK/Cameca and are delivered with the AP Suite/IVAS software there is some homogeneity in how a measurement is performed and which data artifacts and algorithms used for data processing. Complementary use of open-source software specifically for the reconstruction, ranging, and later data processing stages contributes to a landscape of multiple tools in use. Therefore, communication of atom probe research differs between user groups. This holds even more so true for the sub community in atom probe which study physical mechanisms involved during ionization to the point that here that almost each research work defines different simulation tools with different types of data artifacts. NXapm defines constraints on the existence and cardinality of concepts and its concept branches but seeks to offer a compromise. The key design pattern followed is that most branches are made optional or at most recommended but their child concepts are conditionally required. Thereby, NXapm can cover a variety of simple but also complex use cases. An example of this parent-optional-but-childs-stronger-restricted design is the combination of the optional group ``measurement`` with its required child ``measurement/instrument``: Users which report simulations are not forced to document the instrument but users which have characterized a specimen are motivated to report about the instrument. They are though not necessarily required to report all the details of the instruments' components because the design pattern is applied recursively. *NXapm distinguishes and stores instance data based on how long they remain unchanged:* ``measurement`` provides two groups ``measurement/instrument`` and ``measurement/eventID``. The first group is designed for storing metadata about the instrument that do not change over the course of the session. Examples are the name of the technology partner who built the microscope or whether a laser or voltage pulser and reflectron exists or not. The second group is designed for metadata and data that are collected during the session with the instrument. These, are stored as instances of ``measurement/eventID``, events that can be time-stamped individually. Each instance of a group ``measurement/eventID`` contains ``measurement/instrument`` whose purpose is to store those specific state and settings of the instrument that was present during the collection of the event. Thereby, changing conditions such as compaigns with different target detection rate can be stored. Noteworthy, such an approach of the atom probe detecting groups of events and storing these as groups has also been in use in the proprietary software via CamecaRoot, a set of customized data structures and file formats that use the CernRoot library. By virtue of design this reduces unnecessary repetition of metadata stored in the first group. ``atom_probeID`` offer classes for the each task relevant task in the data processing pipeline that converts raw detector event data to calibrated mass-to-charge-state-ratio values and hit_position on the detector. These include ``initial_specimen``, and ``final_specimen`` locations for storing images of the specimen prior/after the measurement as considered best practice by AMETEK/Cameca, ``raw_data`` for delay-line timing data, ``hit_finding`` for details of the hit finding algorithm, ``hit_spatial_filtering`` a process that filters hits of too low quality and those laying outside the about to be computed reconstruction volume. Furthermore, group ``voltage_and_bowl`` offers a place for documenting calibrations and processing non-linearities. Group ``mass_to_charge_conversion`` is used to document the mass calibration and the conversion from time-of-flight to mass-to-charge-state-ratio values. Finally, the groups ``reconstruction`` and ``ranging`` were designed to match and document the classical approaches how from all the previous sources of input one can compute a reconstructed volume, and apply peak fitting routines on the mass-to-charge-state-ratio histogram to label ions, i.e. range them for their isotopic identity. Group ``atom_probeID/reconstruction/naive_discretization`` offers a standardized way to report simple three-dimensional histograms. Group ``atom_probeID/ranging/peak_identification/ionID`` and its complementing group ``atom_probeID/ranging/peak_identification/ionID/charge_state_analysis`` solves the issue that the ranging definitions in classical file formats are not reported for always for their isotopic identity and charge state. The field ``atom_probeID/ranging/peak_identification/iontypes`` provides a place for storing a compact representation of the results of each ranging definition made at the level of each ion. *The compatibility of NXapm and NXem:** The design of NXapm mirrors that of :ref:`NXem`. This was an intentional choice to support the increasingly stronger connection between these two materials characterization methods, especially in light of recent advances in the direct coupling of atom probe and transmission electron microscopes and scanning transmission electron microscopes. The configuration of the software that was used to generate this NeXus file. A collection of all programs and libraries which are considered relevant to understand with which software tools this NeXus file instance was generated. Ideally, to enable a binary recreation from the input data. Examples include the name and version of the libraries used to write the instance. Ideally, the software which writes these NXprogram instances also includes the version of the set of NeXus classes i.e. the specific set of base classes, application definitions, and contributed definitions with which the here described concepts can be resolved. For the `pynxtools library <https://github.com/FAIRmat-NFDI/pynxtools>`_ which is used by the `NOMAD <https://nomad-lab.eu/nomad-lab>`_ research data management system, it makes sense to store e.g. the GitHub repository commit and respective submodule references used. Programs and libraries representing the computational environment The identifier whereby the experiment is referred to in the control software. It is common practice in atom probe research to refer to a measurement on a single specimen as a run. When working with AMETEK/Cameca instruments it is a common practice also to store all data associated with such a run in files whose name is composed from a prefix that details the type of instrument (e.g. R5076) followed by the run_number. These filenames are often used as the specimen_name or experiment_identifier. The terms run and session are understood as exact synonyms. For other instruments, such as the one from Stuttgart or Oxcart from Erlangen, or the instruments at GPM in Rouen, use the identifier which matches best conceptually to the LEAP run number. The field does not have to be required, if the information is recoverable in the dataset which for LEAP instruments is the case; provided these RHIT or HITS files respectively are stored alongside a data artifact. With NXapm the RHIT or HITS can be stored via NXnote in the hit_finding algorithm section. As a destructive microscopy technique, a run can be performed only once. It is possible, however, to interrupt a run and restart data acquisition while still using the same specimen. In this case, each evaporation run needs to be distinguished with different run numbers. We follow this habit of most atom probe groups. Such interrupted runs should be stored as individual :ref:`NXentry` instances in one NeXus file. Alias or short name which scientists can use to refer to this experiment. Free-text description about the experiment. Users are strongly advised to parameterize the description of their experiment by using respective groups and fields and base classes instead of writing prose into the field. ISO 8601 time code with local time zone offset to UTC information included when the atom probe session started. If the exact duration of the measurement is not relevant, start_time only should be used. The start_time is required in order to ensure that at least one point in time is provided for full temporal context to a measurement and simulation when writing instance data using NXapm. Otherwise, the instance data can not be sorted in order or even placed in a logical sequence to other steps of the research workflow, which would disallow using functionalities in research data management systems that rely on temporal context. Specifying start_time and end_time is useful for capturing more detailed bookkeeping of the experiment. The user should be aware that even with having both dates specified, it may not be possible to infer how long the experiment took or for how long data were collected. More detailed timing data over the course of the experiment have to be collected to compute this event chain during the experiment. For this purpose the :ref:`NXevent_data_apm` instance should be used. ISO 8601 time code with local time zone offset to UTC included when the atom probe session ended. Writing the end_time can be a tricky in practice. If written at the start of the experiment, it can only be an estimate. If written at the end, there is the risk for having the computer crash or lose power. The absence of end_time should not be interpreted as that the experiment was aborted. Only, the field ``status`` should be used for communicating such abortion. How long did the measurement take e.g. use CRunHeader.CAnalysis.fElapsedTime What type of atom probe experiment is performed to inform research data management systems and allow filtering: * apt are experiments where the analysis_chamber has no imaging gas. Experiments with LEAP instruments are typically with this operation_mode. * fim are experiments where the analysis_chamber has an imaging gas, which should be specified with the atmosphere in the analysis_chamber group. * apt_fim should be used for combinations of the two imaging modes. Few experiments of this type have been performed, as it can be detrimental to LEAP systems (see `S. Katnagallu et al. <https://doi.org/10.1017/S1431927621012381>`_). Description of the sample from which the specimen was prepared or site-specifically cut out using e.g. a focused-ion beam instrument. In NXapm, a measurement is performed on a specimen. Since APM specimens are very small, they are typically cut from a larger object with some scientific significance, which NXapm refers to as a sample. False, if the sample is a real one. True, if the sample is a virtual one. Given name/alias for the sample. Qualitative information about the grain size, here specifically described as the equivalent spherical diameter of an assumed average grain size for the crystal ensemble. If the specimen does not contain many crystals average values might be an unreliable descriptor. Reporting a grain size may be useful though as it allows judging if specific features are expected to be found in the detector hit map. Magnitude of the standard deviation of the grain_diameter. An array of elapsed time, the independent axis, of a time-temperature curve. This field can be used in combination with heat_treatment_temperature and heat_treatment_temperature_errors as well as heat_treatment_quenching_rate and heat_treatment_quenching_rate_errors respectively. In this case, these fields should also be stored as an array with the same dimensions as heat_treatment_time to store the dependant axes of a time-temperature curve as well as its first derivative. If heat_treatment_time is absent, the temperature of the last heat treatment step before quenching. Knowledge about this value can give an idea how the sample was heat treated. However, if a documentation of the annealing treatment as a function of time is available one should better rely on this information and have it stored alongside the NeXus file. If heat_treatment_time is provided, the temperature. Consult the docstring of heat_treatment_time. Magnitude of the standard deviation of the heat_treatment_temperature. If heat_treatment_time is provided, the magnitude of the standard derivation of the temperature. Consult the docstring of heat_treatment_time. If heat_treatment_time is absent, the rate of the last quenching step. Knowledge about this value can give an idea how the sample was heat treated. However, there are many situations where one can imagine that the scalar value for just the quenching rate is insufficient. If heat_treatment_time is provided, the first derivative of the time-temperature curve. Consult the docstring of heat_treatment_time for further details. Magnitude of the standard deviation of the heat_treatment_quenching_rate. If heat_treatment_time is provided, the magnitude of the standard deviation of the first derivative of the time-temperature curve. Consult the docstring of heat_treatment_time for further details. The chemical composition of the sample. Typically, it is assumed that this more macroscopic composition is representative for the material so that the composition of the typically substantially less voluminous specimen probes from the more voluminous sample. Description of the specimen that was cut off from the sample. In atom probe jargon this is typically referred to as the tip. False, if the specimen is a real one. True, if the specimen is a virtual one. Given name or an alias. Better use identifierNAME and identifier_parent instead. A single NXentry should be used only for the characterization of a single specimen. Identifier of the sample from which the specimen was cut or the string "n/a". The purpose of this field is to support functionalities for tracking sample provenance via a research data management system. ISO 8601 time code with local time zone offset to UTC information when the specimen was prepared. Ideally, report the end of the preparation, i.e. the last known time the measured specimen surface was actively prepared. Ideally, this matches the last timestamp that is mentioned in the digital resource pointed to by identifier_parent. Knowing when the specimen was exposed to e.g. specific atmosphere is especially required for environmentally sensitive material such as hydrogen charged specimens or experiments including tracers with a short half time. List of comma-separated elements from the IUPAC periodic table that are contained in the specimen. If the specimen substance has multiple components, all elements from each component must be included in `atom_types`. The purpose of the field is to offer research data management systems an opportunity to parse the relevant elements without having to interpret these from the resources pointed to by identifier_parent or walk through eventually deeply nested groups in data instances. Discouraged free-text field. True, if the specimen contains a grain or phase boundary. False, if the specimen is a single crystal. True, if the specimen is amorphous. False, if the specimen is not. Ideally measured otherwise best elaborated guess of the initial radius of the specimen. Ideally measured, otherwise best estimate, of the initial shank angle. This is a measure of the specimen taper. Define it in such a way that the base of the specimen is modelled as a conical frustrum so that the shank angle is the smallest angle between the specimen space z-axis and a vector on the lateral surface of the cone. The conventions used when reporting crystal orientations. We follow the best practices of the Material Science community that are defined in reference `<https://doi.org/10.1088/0965-0393/23/8/083501>`_. Convention how a positive rotation angle is defined when viewing from the end of the rotation unit vector towards its origin. This is in accordance with convention 2 of reference `<https://doi.org/10.1088/0965-0393/23/8/083501>`_. Counter_clockwise is equivalent to a right-handed choice. Clockwise is equivalent to a left-handed choice. How are rotations interpreted into an orientation according to convention 3 of reference `<https://doi.org/10.1088/0965-0393/23/8/083501>`_. How are Euler angles interpreted given that there are several choices e.g. zxz, xyz according to convention 4 of reference `<https://doi.org/10.1088/0965-0393/23/8/083501>`_. The most frequently used convention in Materials Science is zxz, which is based on the work of H.-J. Bunge but using other conventions is possible. Proper Euler angles are distinguished from Tait-Bryan angles. To which angular range is the rotation angle argument of an axis-angle pair parameterization constrained according to convention 5 of reference `<https://doi.org/10.1088/0965-0393/23/8/083501>`_. Which sign convention is followed when converting orientations between different parametrizations/representations according to convention 6 of reference `<https://doi.org/10.1088/0965-0393/23/8/083501>`_. A coordinate system. Multiple instances require unique names. Several Euclidean coordinate systems (CS) are used in the field of atom probe: * World space; a CS specifying a local coordinate system of the planet earth which identifies into which direction gravity is pointing such that the laboratory space CS can be rotated into this world CS. * The laboratory space; a CS specifying the room where the instrument is located in or a physical landmark on the instrument, e.g. the direction of the transfer rod where positive is the direction how the rod has to be pushed during loading a specimen into the instrument. In summary, this CS is defined by the chassis of the instrument. Suggested name of the group ``laboratory_reference_frame``. * The specimen space; a CS affixed to either the base or the initial apex of the specimen, whose z axis points towards the detector. Suggested name of the group ``specimen_reference_frame``. * The detector space; a CS affixed to the detector plane whose xy plane is usually in the detector and whose z axis points towards the specimen. This is a distorted space with respect to the reconstructed ion positions. Suggested name of the group ``detector_reference_frame``. * The reconstruction space; a CS in which the reconstructed ion positions are defined. The orientation depends on the analysis software used. * Eventually further coordinate systems attached to the flight path of individual ions might be defined. Suggested name of the group ``reconstruction_reference_frame``. To achieve unique names, the prefix "NAMED" should be replaced to with something derived from an alias for the coordinate system, or the value of the "alias" field. Use the suffix _reference_frame when creating specific instances of NXcoordinate_system e.g. laboratory_reference_frame, reconstruction_reference_frame and so on and so forth. In atom probe microscopy a frequently used choice for the detector space (CS) is discussed with the so-called detector space image stack. This is a stack of two-dimensional histograms of detected ions within a predefined evaporation identifier interval. Typically, the set of ion evaporation sequence identifiers is grouped into chunks. For each chunk a histogram of the ion hit positions on the detector is computed. This leaves the possibility for inconsistency between the so-called detector space and the e.g. specimen space. To avoid these ambiguities, instances of :ref:`NXtransformations` should be used. A region-of-interest analyzed either during or after the session for which specific processed data of the measured or simulated data are available. If a single instance is required the group should be named atom_probe. If multiple groups are required these should be named atom_probe1, atom_probe2, and so on and so forth. SEM or TEM image of the initial specimen taken before the measurement. SEM or TEM image of the final specimen taken after completion of the measurement. Document the control software that was used on the instrument with which raw data were collected. For almost all atom probe instruments, the recorded raw data and metadata follow proprietary semantics. Therefore, this group can currently often not be filled with more than the control software and some pointing to digital artifacts (e.g. proprietary files) that have been collected during the measurement in an effort to document as best as possible all steps of an analysis workflow. The physical quantities measured in an atom probe experiment are time-of-flight and tuples of arrival_time_pairs as a function of the event chain on the pulser. From these tuples, hits are computed in a process called hit_finding. The control software that was used for running the measurement. At least the main software should be reported. If this is the only program to report name the group "program" and use its below fields program and version to detail the version used. E.g. program AP Suite, version 6.3 It is recommended to report multiple programs though, i.e. also the libraries and dependencies of the software. In the case of AP Suite/IVAS this can be used to document the AP Suite GUI, LAS, CamecaRoot, and CernRoot versions. In this case always name the program groups program1, program2, ... with program one being AP Suite/IVAS. In the case of an open-source instrument, like P. Felfer's Oxcart or G. Schmitz's M-TAP instruments, also use program1, program2, ... with program1 representing the control software e.g. `M. Monajem and P. Felfer pyCCAPT <https://pyccapt.readthedocs.io/en/latest/>`_. Further instances (program2, ...) can be used to list the dependencies, the python virtual environment. Possibility to point to files that contain raw data. Exemplar files that could be pointed to here when working with AMETEK/Cameca instruments are the proprietary STR, RRAW, or HITS files that AP Suite/IVAS generates. The number of delay-line-detector (DLD) wires present. Alias tuple, typical for the begin and the end of each DLD wire of the detector. Order follows arrival_time_pairs. The order of the first dimension should match that of the second dimension of the arrival_time_pairs field. Raw readings from the analog-to-digital-converter timing circuits of the detector wires. The configuration of a hit finding algorithm and its output. Hit finding is the process of deciding which detector signals are significant and assigning specific ions colliding with the detector to each observed event. Evaluated ion impact coordinates on the detector. Use the depends_on field to specify which reference frame the positions are defined in. Contains the path to an instance of NX_coordinate_system in which the positions are defined. Number of events of type "golden" when APSuite/IVAS was used as the software with which the measurement was performed. The value can be extracted from the CRunHeader.fTotalEventGolden field of a CamecaRoot RHIT/HITS file. Number of events of type "incomplete" when APSuite/IVAS was used as the software with which the measurement was performed. The value can be extracted from the CRunHeader.fTotalEventIncomplete field of a CamecaRoot RHIT/HITS file. Number of events of type "multiple" when APSuite/IVAS was used as the software with which the measurement was performed. The value can be extracted from the CRunHeader.fTotalEventMultiple field of a CamecaRoot RHIT/HITS file. Number of events of type "partials" when APSuite/IVAS was used as the software with which the measurement was performed. The value can be extracted from the CRunHeader.fTotalEventPartials field of a CamecaRoot RHIT/HITS file. Number of events when APSuite/IVAS was used as the software with which the measurement was performed. The value can be extracted from the CRunHeader.fTotalEventRecords field of a CamecaRoot RHIT/HITS file. Hit quality is an integer that specifies which category/type a hit was assigned to. This field lists the human-readable, possibly though proprietary types distinguished. The indices of this array are used in hit_quality to encode hit_quality for each pulse in a more efficient way than by repeating the string that is used for each type as it is provided in this field. As an example, assume two types, "golden" and "partial", are distinguished. If hit_quality_type stores the array "golden", "partial", the index 0 in hit_quality identifies all those pulses of category "golden", while the index 1 in hit_quality identifies all of category "partial". Hit quality identifier for each pulse. Identifier has to be within hit_quality_type. The number of ions determined to have been collected on the same pulse. These ions may hit different pixels, or even the same detector pixel. The hit_multiplicity is not related to the makeup of the ions and should not be confused with the number of atoms or elements that constitute a molecular ion. Integer which defines the first evaporation_id. Typically, this is either zero or one. There are two possibilities to report evaporation_id values: If evaporation_id_offset is provided, the evaporation_id values are defined by the sequence :math:`[evaporation\_id\_offset, evaporation\_id\_offset + n]` with :math:`n` the number of ions in the reconstructed volume. Alternatively, evaporation_id_offset is not provided but instead a a sequence of :math:`n` values is defined, these integer values do not need to be sorted. Configuration of and results obtained from a voltage-and-bowl time-of-flight correction algorithm. The voltage-and-bowl correction is a data post-processing step to correct ion impact positions for flight path differences, detector bias, and nonlinearities. Reference mass-to-charge state ratio value For example 16 Da as mentioned by `T. Blum et al. <https://doi.org/10.1002/9781119227250.ch18>`_ (page 371). Raw time-of-flight data without corrections. The parameter :math:`t_0`, CAnalysis.CCalibMass.fT0Estimate Calibrated time-of-flight. Mass calibration with unit peaks/interp. as mentioned by `T. Blum et al. <https://doi.org/10.1002/9781119227250.ch18>`_ (page 371). Inverse of the mass resolution :math:`\frac{M}{\Delta M}` as mentioned by `T. Blum et al. <https://doi.org/10.1002/9781119227250.ch18>`_ (page 371). Multiple values can be reported but reporting each is only useful when stating also: * The full width at which :math:`{\Delta M}_{fw}` fraction of maximum this value was defined. Examples are at tenth :math:`{\Delta M}_{10}` or at half maximum (FWHM). Consequently, mass_resolution_fw should needs to be a vector of the same length and using the same order like used for mass_resolution, i.e. the first mass resolution was defined at the maximum as defined by the first value from mass_resolution_fw. * The reference molecular ion e.g. :math:`^{16}{O_{2}}^{+}` As many instances of mass_resolutionION should be used with instances numbered starting from 1 up to the length of the mass_resolution vector. The full width at which :math:`{\Delta M}_{fw}` fraction of maximum this value was defined. Examples are at tenth :math:`{\Delta M}_{10}` or at half maximum (FWHM). Consequently, mass_resolution_fw should needs to be a vector of the same length and using the same order like used for mass_resolution, i.e. the first mass resolution was defined at the maximum as defined by the first value from mass_resolution_fw. The reference molecular ion e.g. :math:`^{16}{O_{2}}^{+}` As many instances of mass_resolutionION should be used with instances numbered starting from 1 up to the length of the mass_resolution vector. For LEAP and APSuite/IVAS-based analyses the root file which stores the settings whereby an RHIT/HITS file can be used to regenerate the reconstructed volume that is here referred to. The respective RHIT/HITS file should ideally be specified in the serialized group of the hit_finding section of this application definition. For LEAP and APSuite/IVAS-based analyses the resulting typically file with the reconstructed positions and calibrated mass-to-charge- state ratio values. For other data collection/analysis software the data artifact which comes closest conceptually to AMETEK/Cameca's typical file formats. These are typically exported as a POS, ePOS, APT, ATO, ENV, or HDF5 file, which should be stored alongside this record in the research data management system. The respective ranging definitions file RNG/RRNG/ENV/HDF5. (Out-of-sync, time-independent) background levels in ppm/ns reported by e.g. APSuite/IVAS for LEAP systems. The mass-resolving power (MRP) value `D. Larson et al. <https://doi.org/10.1007/978-1-4614-8721-0>`_ report Eq. D.8 in page 282: :math:`MRP = \frac{1}{2\delta t} \cdot \sqrt{\frac{m}{n}\frac{1}{2eV}L}`, with :math:`\delta t` representing the timing imprecision, :math:`\frac{m}{n}` the mass-to-charge state ratio, :math:`e` the elementary charge, :math:`V` the potential difference, and :math:`L` the flight path length. Timing imprecision is caused by variations of flight path length and voltage, the fact that the precision of electronics is finite and a spread of the time-of-departure of individual ions is observed. Mass-to-charge state ratio :math:`\frac{m}{n}` at which mrp_value was specified. Potential difference :math:`V` at which mrp_value was specified. Flight path length :math:`L` at which mrp_value was specified. Category for the peak offering a qualitative statement of the location of the peak in light of limited mass-resolving power that is relevant for composition quantification. See `D. Larson et al. (p172) <https://doi.org/10.1007/978-1-4614-8721-0>`_ for examples of each category: * 0, well-separated, :math:`^{10}B^{+}`, :math:`^{28}Si^{2+}` * 1, close, but can be sufficiently separated for quantification in a LEAP system, :math:`^{94}Mo^{3+}`, :math:`^{63}Cu^{2+}` * 2, closely overlapping, demands better than LEAP4000X MRP can provide :math:`^{14}N^{+}`, :math:`^{28}Si^{2+}` at different charge states * 3, overlapped exactly due to multi-charge molecular species, :math:`^{16}{O_{2}}^{2+}`, :math:`^{16}O^{+}` * 4, overlapped, same charge state, cannot as of 2013 be discriminated with a LEAP4000X, :math:`^{14}{N_{2}}^{+}`, :math:`^{28}Si^{+}` * 5, overlapped, same charge state, any expectation of resolvability, :math:`^{54}Cr^{2+}`, :math:`^{54}Fe^{2+}` Ions that were ranged. The value zero is reserved for documenting that an ion was unranged. Identifier for ranged ions need to start at 1 up to number_of_ion_types. The iontype identifier for each ion that was best matching; stored in the order of the evaporation_id. The value zero is reserved for documenting that an ion was unranged. Identifier for ranged ions need to start at 1 up to number_of_ion_types. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXarchive.nxdl.xml0000644000077000000000000001476314777236751026213 0ustar00rosborn This is a definition for data to be archived by ICAT (http://www.icatproject.org/). .. text from the icatproject.org site the database (with supporting software) that provides an interface to all ISIS experimental data and will provide a mechanism to link all aspects of ISIS research from proposal through to publication. unique identifier for the experiment Brief description of the experiment and its objectives ID of user or DAQ define group of data files Brief summary of the collection, including grouping criteria unique identifier for this measurement as provided by the facility TODO: needs documentation TODO: needs documentation TODO: needs documentation revision ID of this file, may be after recalibration, reprocessing etc. Official NeXus NXDL schema to which this file conforms The program and version used for generating this file when this file is to be released into PD role of the user ID of the user in the facility burocracy database Brief description of the instrument Descriptive name of sample Unique database id of the sample Chemical formula formatted according to CIF conventions Description of the environment the sample is in: air, vacuum, oxidizing atmosphere, dehydrated, etc. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXarpes.nxdl.xml0000644000077000000000000001213715046415443025660 0ustar00rosborn This is an application definition for angular resolved photo electron spectroscopy. It has been drawn up with hemispherical electron analysers in mind. This definition is a legacy support for older NXarpes experiments. There is, however, a newer definition to collect data & metadata for general photoemission experiments, called :ref:`NXmpes`, as well as a specialization for ARPES experiments, called :ref:`NXmpes_arpes`." Official NeXus NXDL schema to which this file conforms. setting for the electron analyser lens dial setting of the entrance slit size of the entrance slit energy of the electrons on the mean path of the analyser todo: define more clearly Angular axis of the analyser data which dimension the axis applies to is defined using the normal NXdata methods. Energy axis of the analyser data which dimension the axis applies to is defined using the normal NXdata methods. number of raw active elements in each dimension origin of rectangular region selected for readout size of rectangular region selected for readout Descriptive name of sample ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXcanSAS.nxdl.xml0000644000077000000000000014333414777236751025677 0ustar00rosborn Implementation of the canSAS standard to store reduced small-angle scattering data of any dimension. .. index:: canSAS For more details, see: * http://www.cansas.org/ * http://www.cansas.org/formats/canSAS1d/1.1/doc/ * http://cansas-org.github.io/canSAS2012/ * https://github.com/canSAS-org/NXcanSAS_examples The minimum requirements for *reduced* small-angle scattering data as described by canSAS are summarized in the following figure: .. _canSAS_2012_minimum: .. figure:: canSAS/2012-minimum.png :width: 60% The minimum requirements for *reduced* small-angle scattering data. (:download:`full image <canSAS/2012-minimum.png>`) See :ref:`below <NXcanSAS_minimum>` for the minimum required information for a NeXus data file written to the NXcanSAS specification. .. rubric:: Implementation of canSAS standard in NeXus This application definition is an implementation of the canSAS standard for storing both one-dimensional and multi-dimensional *reduced* small-angle scattering data. * NXcanSAS is for reduced SAS data and metadata to be stored together in one file. * *Reduced* SAS data consists of :math:`I(\vec{Q})` or :math:`I(|\vec{Q}|)` * External file links are not to be used for the reduced data. * A good practice/practise is, at least, to include a reference to how the data was acquired and processed. Yet this is not a requirement. * There is no need for NXcanSAS to refer to any raw data. The canSAS data format has a structure similar to NeXus, not identical. To allow canSAS data to be expressed in NeXus, yet identifiable by the canSAS standard, an additional group attribute ``canSAS_class`` was introduced. Here is the mapping of some common groups. =============== ============ ========================== group (*) NX_class canSAS_class =============== ============ ========================== sasentry NXentry SASentry sasdata NXdata SASdata sasdetector NXdetector SASdetector sasinstrument NXinstrument SASinstrument sasnote NXnote SASnote sasprocess NXprocess SASprocess sasprocessnote NXcollection SASprocessnote sastransmission NXdata SAStransmission_spectrum sassample NXsample SASsample sassource NXsource SASsource =============== ============ ========================== (*) The name of each group is a suggestion, not a fixed requirement and is chosen as fits each data file. See the section on defining :ref:`NXDL group and field names <RegExpName>`. Refer to the NeXus Coordinate System drawing (:ref:`Design-CoordinateSystem`) for choice and direction of :math:`x`, :math:`y`, and :math:`z` axes. .. _NXcanSAS_minimum: .. rubric:: The minimum required information for a NeXus data file written to the NXcanSAS specification. .. literalinclude:: canSAS/minimum-required.txt :tab-width: 4 :linenos: :language: text .. index:: plotting Declares which :ref:`NXdata` group contains the data to be shown by default. It is needed to resolve ambiguity when more than one :ref:`NXdata` group exists. The value is the name of the default :ref:`NXdata` group. Usually, this will be the name of the first *SASdata* group. .. index:: NXcanSAS (applications); SASentry Place the canSAS ``SASentry`` group as a child of a NeXus ``NXentry`` group (when data from multiple techniques are being stored) or as a replacement for the ``NXentry`` group. Note: It is required for all numerical objects to provide a *units* attribute that describes the engineering units. Use the Unidata UDunits [#]_ specification as this is compatible with various community standards. .. [#] The UDunits specification also includes instructions for derived units. Official canSAS group: **SASentry** Describes the version of the canSAS standard used to write this data. This must be a text (not numerical) representation. Such as:: @version="1.1" Official NeXus NXDL schema to which this subentry conforms. A *SASData* group contains a single reduced small-angle scattering data set that can be represented as :math:`I(\vec{Q})` or :math:`I(|\vec{Q}|)`. *Q* can be either a vector (:math:`\vec{Q}`) or a vector magnitude (:math:`|\vec{Q}|`) The name of each *SASdata* group must be unique within a SASentry group. Suggest using names such as ``sasdata01``. NOTE: For the first *SASdata* group, be sure to write the chosen name into the `SASentry/@default` attribute, as in:: SASentry/@default="sasdata01" A *SASdata* group has several attributes: * I_axes * Q_indices * Mask_indices To indicate the dependency relationships of other varied parameters, use attributes similar to ``@Mask_indices`` (such as ``@Temperature_indices`` or ``@Pressure_indices``). Official canSAS group: :index:`NXcanSAS (applications); SASdata` Name of the default data field. For canSAS **SASdata**, this is always "I". String array that defines the independent data fields used in the default plot for all of the dimensions of the *signal* field (the *signal* field is the field in this group that is named by the ``signal`` attribute of this group). One entry is provided for every dimension of the ``I`` data object. Such as:: @I_axes="Temperature", "Time", "Pressure", "Q", "Q" Since there are five items in the list, the intensity field of this example ``I`` must be a five-dimensional array (rank=5). Integer or integer array that describes which indices (of the :math:`I` data object) are used to reference the ``Q`` data object. The items in this array use zero-based indexing. Such as:: @Q_indices=1,3,4 which indicates that ``Q`` requires three indices from the :math:`I` data object: one for time and two for Q position. Thus, in this example, the ``Q`` data is time-dependent: :math:`\vec{Q}(t)`. Name of the data mask field. .. see: https://github.com/nexusformat/definitions/issues/533 The data *mask* must have the same shape as the *data* field. Positions in the mask correspond to positions in the *data* field. The value of the mask field may be either a boolean array where ``false`` means *no mask* and ``true`` means *mask* or a more descriptive array as as defined in :ref:`NXdetector`. Integer or integer array that describes which indices (of the :math:`I` data object) are used to reference the ``Mask`` data object. The items in this array use zero-based indexing. Such as:: @Mask_indices=3,4 which indicates that Q requires two indices from the :math:`I` data object for Q position. ISO-8601 time [#iso8601]_ .. index:: NXcanSAS (applications); Q Array of :math:`Q` data to accompany :math:`I`. .. figure:: canSAS/Q-geometry.jpg :width: 60% The :math:`\vec{Q}` geometry. (:download:`full image <canSAS/Q-geometry.jpg>`) :math:`Q` may be represented as either the three-dimensional scattering vector :math:`\vec{Q}` or the magnitude of the scattering vector, :math:`|\vec{Q}|`. .. math:: |\vec{Q}| = (4\pi/\lambda) sin(\theta) When we write :math:`Q`, we may refer to either or both of :math:`|\vec{Q}|` or :math:`\vec{Q}`, depending on the context. Engineering units to use when expressing :math:`Q` and related terms. Data expressed in other units will generate a warning from validation software and may not be processed by some analysis software packages. preferred (optional: for numerical arrays) Names the dataset (in this SASdata group) that provides the uncertainty to be used for data analysis. The name of the dataset containing the :math:`Q` uncertainty is flexible. The name must be unique in the *SASdata* group. .. comment see: https://github.com/canSAS-org/canSAS2012/issues/7 Such as:: @uncertainties="Q_uncertainties" The *uncertainties* field will have the same *shape* (dimensions) as the Q field. These values are the estimates of uncertainty of each Q. By default, this will be interpreted to be the estimated standard deviation. In special cases, when a standard deviation cannot possibly be used, its value can specify another measure of distribution width. There may also be a subdirectory (optional) with constituent components. .. note:: To report distribution in reported :math:`Q` values, use the ``@resolutions`` attribute. It is possible for both ``@resolutions`` and ``uncertainties`` to be reported. .. index:: NXcanSAS (applications); resolutions (optional: for numerical arrays) Names the dataset (in this SASdata group) containing the :math:`Q` resolution. The name of the dataset containing the :math:`Q` resolution is flexible. The name must be unique in the *SASdata* group. .. comment see: https://github.com/canSAS-org/canSAS2012/issues/7 The *resolutions* field will have the same *shape* (dimensions) as the Q field. Generally, this is the principal resolution of each :math:`Q`. Names the data object (in this SASdata group) that provides the :math:`Q` resolution to be used for data analysis. Such as:: @resolutions="Qdev" To specify two-dimensional resolution for slit-smearing geometry, such as (*dQw*, *dQl*), use a string array, such as:: @resolutions="dQw", "dQl" There may also be a subdirectory (optional) with constituent components. This pattern will demonstrate how to introduce further as-yet unanticipated terms related to the data. .. comment see: https://github.com/nexusformat/definitions/issues/492#issuecomment-262813907 By default, the values of the resolutions data object are assumed to be one standard deviation of any function used to approximate the resolution function. This equates to the width of the gaussian distribution if a Gaussian is chosen. See the ``@resolutions_description`` attribute. .. note:: To report uncertainty in reported :math:`Q` values, use the ``@uncertainties`` attribute. It is possible for both ``@resolutions`` and ``uncertainties`` to be reported. (optional) Generally, this describes the :math:`Q` ``@resolutions`` data object. By default, the value is assumed to be "Gaussian". These are suggestions: * Gaussian * Lorentzian * Square : note that the full width of the square would be ~2.9 times the standard deviation specified in the vector * Triangular * Sawtooth-outward : vertical edge pointing to larger Q * Sawtooth-inward vertical edge pointing to smaller Q * Bin : range of values contributing (for example, when 2-D detector data have been reduced to a 1-D :math:`I(|Q|)` dataset) For other meanings, it may be necessary to provide further details such as the function used to assess the resolution. In such cases, use additional datasets or a :ref:`NXnote` subgroup to include that detail. .. index:: NXcanSAS (applications); I Array of intensity (:math:`I`) data. The intensity may be represented in one of these forms: **absolute units**: :math:`d\Sigma/d\Omega(Q)` differential cross-section per unit volume per unit solid angle (such as: 1/cm/sr or 1/m/sr) **absolute units**: :math:`d\sigma/d\Omega(Q)` differential cross-section per unit atom per unit solid angle (such as: cm^2 or m^2) **arbitrary units**: :math:`I(Q)` usually a ratio of two detectors but units are meaningless (such as: a.u. or counts) This presents a few problems for analysis software to sort out when reading the data. Fortunately, it is possible to analyze the *units* to determine which type of intensity is being reported and make choices at the time the file is read. But this is an area for consideration and possible improvement. One problem arises with software that automatically converts data into some canonical units used by that software. The software should not convert units between these different types of intensity indiscriminately. A second problem is that when arbitrary units are used, then the set of possible analytical results is restricted. With such units, no meaningful volume fraction or number density can be determined directly from :math:`I(Q)`. In some cases, it is possible to apply a factor to convert the arbitrary units to an absolute scale. This should be considered as a possibility of the analysis process. Where this documentation says *typical units*, it is possible that small-angle data may be presented in other units and still be consistent with NeXus. See the :ref:`design-units` section. Engineering units to use when expressing :math:`I` and intensity-related terms. Data expressed in other units (or missing a ``@units`` attribute) will be treated as ``arbitrary`` by some software packages. For software using the UDUNITS-2 library, ``arbitrary`` will be changed to ``unknown`` for handling with that library. includes m2/m3 and 1/m/sr includes cm2/cm3 and 1/cm/sr (optional: for numerical arrays) Names the dataset (in this SASdata group) that provides the uncertainty of :math:`I` to be used for data analysis. The name of the dataset containing the :math:`I` uncertainty is flexible. The name must be unique in the *SASdata* group. .. comment see: https://github.com/canSAS-org/canSAS2012/issues/7 Generally, this is the estimate of the uncertainty of each :math:`I`. Typically the estimated standard deviation. *Idev* is the canonical name from the 1D standard. The NXcanSAS standard allows for the name to be described using this attribute. Such as:: @uncertainties="Idev" (optional) Names the field (a.k.a. dataset) that contains a factor to multiply ``I``. By default, this value is unity. Should an uncertainty be associated with the scaling factor field, the field containing that uncertainty would be designated via the ``uncertainties`` attribute. Such as:: I : NX_NUMBER @uncertainties="Idev" : NX_CHAR @scaling_factor="I_scaling" : NX_CHAR Idev : NX_NUMBER I_scaling : NX_NUMBER @uncertainties="I_scaling_dev" : NX_CHAR I_scaling_dev : NX_NUMBER The exact names for ``I_scaling`` and ``I_scaling_dev`` are not defined by NXcanSAS. The user has the flexibility to use names different than those shown in this example. .. index:: NXcanSAS (applications); Idev Estimated **uncertainty** (usually standard deviation) in :math:`I`. Must have the same units as :math:`I`. When present, the name of this field is also recorded in the *uncertainties* attribute of *I*, as in:: I/@uncertainties="Idev" Engineering units to use when expressing :math:`I` and intensity-related terms. Data expressed in other units (or missing a ``@units`` attribute) will generate a warning from any validation process and will be treated as ``arbitrary`` by some analysis software packages. For software using the UDUNITS-2 library, ``arbitrary`` will be changed to ``unknown`` for handling with that library. includes m2/m3 and 1/m/sr includes cm2/cm3 and 1/cm/sr .. index:: NXcanSAS (applications); Qdev Estimated :math:`Q` **resolution** (usually standard deviation). Must have the same units as :math:`Q`. When present, the name of this field is also recorded in the *resolutions* attribute of *Q*, as in:: Q/@resolutions="Qdev" or:: Q/@resolutions="dQw", "dQl" Engineering units to use when expressing :math:`Q` and related terms. Data expressed in other units may not be processed by some software packages. preferred .. index:: NXcanSAS (applications); dQw :math:`Q` **resolution** along the axis of scanning (the high-resolution *slit width* direction). Useful for defining resolution data from slit-smearing instruments such as Bonse-Hart geometry. Must have the same units as :math:`Q`. When present, the name of this field is also recorded in the *resolutions* attribute of *Q*, as in:: Q/@resolutions="dQw", "dQl" Engineering units to use when expressing :math:`Q` and related terms. Data expressed in other units may not be processed by some software packages. preferred .. index:: NXcanSAS (applications); dQl :math:`Q` **resolution** perpendicular to the axis of scanning (the low-resolution *slit length* direction). Useful for defining resolution data from slit-smearing instruments such as Bonse-Hart geometry. Must have the same units as :math:`Q`. When present, the name of this field is also recorded in the *resolutions* attribute of *Q*, as in:: Q/@resolutions="dQw", "dQl" Engineering units to use when expressing :math:`Q` and related terms. Data expressed in other units may not be processed by some software packages. preferred Mean value of :math:`Q` for this data point. Useful when describing data that has been binned from higher-resolution data. It is expected that ``Q`` is provided and that both ``Q`` and ``Qmean`` will have the same units. Engineering units to use when expressing :math:`Q` and related terms. Data expressed in other units may not be processed by some software packages. preferred A numerical factor applied to pixels affected by the beam stop penumbra. Used in data files from NIST/NCNR instruments. See: J.G. Barker and J.S. Pedersen (1995) *J. Appl. Cryst.* **28**, 105-114. Title of this *SASentry*. Make it so that you can recognize the data by its title. Could be the name of the sample, the name for the measured data, or something else representative. Run identification for this *SASentry*. For many facilities, this is an integer, such as en experiment number. Use multiple instances of ``run`` as needed, keeping in mind that HDF5 requires unique names for all entities in a group. Optional string attribute to identify this particular *run*. Could use this to associate (correlate) multiple *SASdata* elements with *run* elements. Official canSAS group: :index:`NXcanSAS (applications); SASinstrument` Description of the small-angle scattering instrument. Consider, carefully, the relevance to the SAS data analysis process when adding subgroups in this **NXinstrument** group. Additional information can be added but will likely be ignored by standardized data anlysis processes. The NeXus :ref:`NXbeam` base class may be added as a subgroup of this **NXinstrument** group *or* as a subgroup of the **NXsample** group to describe properties of the beam at any point downstream from the source. :ref:`NXaperture` is generic and limits the variation in data files. Possible NeXus base class alternatives are: :ref:`NXpinhole` or :ref:`NXslit`. Official canSAS group: :index:`NXcanSAS (applications); SASaperture` describe the type of aperture (pinhole, 4-blade slit, Soller slit, ...) opening along the :math:`x` axis opening along the :math:`y` axis Official canSAS group: :index:`NXcanSAS (applications); SAScollimation` Description of a collimating element (defines the divergence of the beam) in the instrument. To document a slit, pinhole, or the beam, refer to the documentation of the ``NXinstrument`` group above. Amount/length of collimation inserted (as on a SANS instrument) Distance from this collimation element to the sample Official canSAS group: :index:`NXcanSAS (applications); SASdetector` Description of a detector in the instrument. Identifies the name of this detector Distance between sample and detector. Note: In NXdetector, the ``distance`` field records the distance to the previous component ... most often the sample. This use is the same as ``SDD`` for most SAS instruments but not all. For example, Bonse-Hart cameras have one or more crystals between the sample and detector. We define here the field ``SDD`` to document without ambiguity the distance between sample and detector. Slit length of the instrument for this detector, expressed in the same units as :math:`Q`. Location of the detector in :math:`x` Location of the detector in :math:`y` Rotation of the detector about the :math:`z` axis (roll) Rotation of the detector about the :math:`x` axis (roll) Rotation of the detector about the :math:`y` axis (yaw) Position of the beam center on the detector. This is the x position where the direct beam would hit the detector plane. This is a length and can be outside of the actual detector. The length can be in physical units or pixels as documented by the units attribute. The value can be any real number (positive, zero, or negative). Position of the beam center on the detector. This is the y position where the direct beam would hit the detector plane. This is a length and can be outside of the actual detector. The length can be in physical units or pixels as documented by the units attribute. The value can be any real number (positive, zero, or negative). Size of each detector pixel. If it is scalar all pixels are the same size Size of each detector pixel. If it is scalar all pixels are the same size Official canSAS group: :index:`NXcanSAS (applications); SASsource` Description of the radiation source. Name of the radiation used. Note that this is **not** the name of the facility! This field contains a value from either the ``probe`` or ``type`` fields in :ref:`NXsource`. Thus, it is redundant with existing NeXus structure. Text description of the shape of the beam (incident on the sample). wavelength (:math:`\lambda`) of radiation incident on the sample Some facilities specify wavelength using a range. This is the lowest wavelength in such a range. Some facilities specify wavelength using a range. This is the highest wavelength in such a range. Some facilities specify wavelength using a range. This is the width (FWHM) of such a range. Size of the incident beam along the x axis. Size of the incident beam along the y axis. Official canSAS group: :index:`NXcanSAS (applications); SASsample` Description of the sample. **ID**: Text string that identifies this sample. Thickness of this sample Transmission (:math:`I/I_0`) of this sample. There is no *units* attribute as this number is dimensionless. Note: the ability to store a transmission *spectrum*, instead of a single value, is provided elsewhere in the structure, in the *SAStransmission_spectrum* element. Temperature of this sample. Any additional sample details. Location of the sample in :math:`x` Location of the sample in :math:`y` Rotation of the sample about the :math:`z` axis (roll) Rotation of the sample about the :math:`x` axis (roll) Rotation of the sample about the :math:`y` axis (yaw) Official canSAS group: :index:`NXcanSAS (applications); SASprocess` Description of a processing or analysis step. Add additional fields as needed to describe value(s) of any variable, parameter, or term related to the *SASprocess* step. Be sure to include *units* attributes for all numerical fields. Optional name for this data processing or analysis step Optional date for this data processing or analysis step. [#iso8601]_ .. [#iso8601] ISO-8601 standard time representation. NeXus dates and times are reported in ISO-8601 (e.g., ``yyyy-mm-ddThh:mm:ss``) or modified ISO-8601 (e.g., ``yyyy-mm-dd hh:mm:ss``). See: http://www.w3.org/TR/NOTE-datetime or http://en.wikipedia.org/wiki/ISO_8601 for more details. Optional description for this data processing or analysis step Specifies the value of a single variable, parameter, or term (while defined here as a string, it could be a number) related to the *SASprocess* step. Note: The name *term* is not required, it could take any name, as long as the name is unique within this group. Any additional notes or subprocessing steps will be documented here. An **NXnote** group can be added to any NeXus group at or below the **NXentry** group. It is shown here as a suggestion of a good place to *consider* its use. Describes anything about *SASprocess* that is not already described. Any content not defined in the canSAS standard can be placed at this point. Note: The name of this group is flexible, it could take any name, as long as it is unique within the **NXprocess** group. Official canSAS group: :index:`NXcanSAS (applications); SASprocessnote` Official canSAS group: :index:`NXcanSAS (applications); SASnote` Free form description of anything not covered by other elements. The *SAStransmission_spectrum* element This describes certain data obtained from a variable-wavelength source such as pulsed-neutron source. The name of each *SAStransmission_spectrum* group must be unique within a SASentry group. Suggest using names such as ``sastransmission_spectrum01``. Official canSAS group: :index:`NXcanSAS (applications); SAStransmission_spectrum` Name of the default data field. For **SAStransmission_spectrum**, this is always "T". the wavelengths field (as axis coordinates) corresponding to this transmission Identify what type of spectrum is being described. It is expected that this value will take either of these two values: ====== ============================================== value meaning ====== ============================================== sample measurement with the sample and container can measurement with just the container ====== ============================================== ISO-8601 time [#iso8601]_ Wavelength of the radiation. This array is of the same shape as ``T`` and ``Tdev``. Transmission values (:math:`I/I_0`) as a function of wavelength. This array is of the same shape as ``lambda`` and ``Tdev``. Names the dataset (in this SASdata group) that provides the uncertainty of each transmission :math:`T` to be used for data analysis. The name of the dataset containing the :math:`T` uncertainty is expected to be ``Tdev``. .. comment see: https://github.com/canSAS-org/canSAS2012/issues/7 Typically: @uncertainties="Tdev" .. index:: NXcanSAS (applications); Tdev Estimated uncertainty (usually standard deviation) in :math:`T`. Must have the same units as :math:`T`. This is the field is named in the *uncertainties* attribute of *T*, as in:: T/@uncertainties="Tdev" This array is of the same shape as ``lambda`` and ``T``. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXdirecttof.nxdl.xml0000644000077000000000000000513614777236751026547 0ustar00rosborn This is a application definition for raw data from a direct geometry TOF spectrometer Official NeXus NXDL schema to which this file conforms chopper rotation speed energy selected chopper rotation speed energy selected We definitly want the rotation_speed and energy of the chopper. Thus either a fermi_chopper or a disk_chopper group is required. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXellipsometry.nxdl.xml0000644000077000000000000004513015046415443027275 0ustar00rosborn Variables used throughout the document, e.g. dimensions or parameters. Length of the spectrum array (e.g. wavelength or energy) of the measured data. Number of measurements (1st dimension of measured_data array). This is equal to the number of parameters scanned. For example, if the experiment was performed at three different temperatures and two different pressures N_measurements = 2*3 = 6. Number of detection angles of the beam reflected or scattered off the sample. Number of angles of incidence of the incident beam. This is the application definition describing ellipsometry experiments. Such experiments may be as simple as identifying how a reflected beam of light with a single wavelength changes its polarization state, to a variable angle spectroscopic ellipsometry experiment. The application definition specializes :ref:`NXoptical_spectroscopy` by extending the terms and setting specific requirements. Information on ellipsometry is provided, e.g. in: * H. Fujiwara, Spectroscopic ellipsometry: principles and applications, John Wiley & Sons, 2007. * R. M. A. Azzam and N. M. Bashara, Ellipsometry and Polarized Light, North-Holland Publishing Company, 1977. * H. G. Tompkins and E. A. Irene, Handbook of Ellipsometry, William Andrew, 2005. Open access sources: * https://www.angstromadvanced.com/resource.asp * https://pypolar.readthedocs.io/en/latest/ Review articles: * T. E. Jenkins, "Multiple-angle-of-incidence ellipsometry", J. Phys. D: Appl. Phys. 32, R45 (1999), https://doi.org/10.1088/0022-3727/32/9/201 * D. E. Aspnes, "Spectroscopic ellipsometry - Past, present, and future", Thin Solid Films 571, 334-344 (2014), https://doi.org/10.1016/j.tsf.2014.03.056 * R. M. A. Azzam, "Mueller-matrix ellipsometry: a review", Proc. SPIE 3121, Polarization: Measurement, Analysis, and Remote Sensing, (3 October 1997), https://doi.org/10.1117/12.283870 * E. A. Irene, "Applications of spectroscopic ellipsometry to microelectronics", Thin Solid Films 233, 96-111 (1993), https://doi.org/10.1016/0040-6090(93)90069-2 * S. Zollner et al., "Spectroscopic ellipsometry from 10 to 700 K", Adv. Opt. Techn., (2022), https://doi.org/10.1515/aot-2022-0016 An application definition for ellipsometry. Version number to identify which definition of this application definition was used for this entry/data. URL where to find further material (documentation, examples) relevant to the application definition. Specify the type of the optical experiment. You may specify fundamental characteristics or properties in the experimental sub-type. Specify the type of ellipsometry. Properties of the ellipsometry equipment. What type of ellipsometry was used? See Fujiwara Table 4.2. If focusing probes (lenses) were used, please state if the data were corrected for the window effects. Were the recorded data corrected by the window effects of the focusing probes (lenses)? Specify the angular spread caused by the focusing probes. Properties of the rotating element defined in 'instrument/rotating_element_type'. Define which element rotates, e.g. polarizer or analyzer. Define how many revolutions of the rotating element were averaged for each measurement. If the number of revolutions was fixed to a certain value use the field 'fixed_revolutions' instead. Define how many revolutions of the rotating element were taken into account for each measurement (if number of revolutions was fixed to a certain value, i.e. not averaged). Specify the maximum value of revolutions of the rotating element for each measurement. Was the backside of the sample roughened? Relevant for infrared ellipsometry. Measured data, data errors, and varied parameters. This may be used to describe indirectly derived data or data transformed between different descriptions, such as: Raw Data --> Psi Delta Psi, Delta --> N,C,S Mueller matrix --> N,C,S Mueller matrix --> Psi, Delta etc. Other types of data, such as temperature or sample location, may be saved in a generic (NXdata) concept from :ref:`NXoptical_spectroscopy`, or better directly in the location of the sample positioner or temperature sensor. An identifier to correlate data to the experimental conditions, if several were used in this measurement; typically an index of 0-N. Select which type of data was recorded, for example intensity, reflectivity, transmittance, Psi and Delta etc. It is possible to have multiple selections. The enumeration list depends on the type of experiment and may differ for different application definitions. Spectral values (e.g. wavelength or energy) used for the measurement. An array of 1 or more elements. Length defines N_spectrum. Replace 'SPECTRUM' by the physical quantity that is used, e.g. wavelength. If applicable, change 'unit: NX_ANY' to the appropriate NXDL unit. If the unit of the measured data is not covered by NXDL units state here which unit was used. Resulting data from the measurement, described by 'data_type'. The first dimension is defined by the number of measurements taken, (N_measurements). The instructions on how to order the values contained in the parameter vectors given in the doc string of INSTRUMENT/sample_stage/environment_conditions/PARAMETER/values, define the N_measurements parameter sets. For example, if the experiment was performed at three different temperatures (T1, T2, T3), two different pressures (p1, p2) and two different angles of incidence (a1, a2), the first measurement was taken at the parameters {a1,p1,T1}, the second measurement at {a1,p1,T2} etc. If applicable, change 'unit: NX_ANY' to the appropriate NXDL unit. If the unit of the measured data is not covered by NXDL units state here which unit was used. Specified uncertainties (errors) of the data described by 'data_type' and provided in 'measured_data'. If applicable, change 'unit: NX_ANY' to the appropriate NXDL unit. If the unit of the measured data is not covered by NXDL units state here which unit was used. List of links to the values of the sensors. Add a link for each varied parameter (i.e. for each sensor). :ref:`External link <Design-Links>` to the data field in the NeXus file which describes the reference data if a reference measurement was performed. Ideally, the reference measurement was performed using the same conditions as the actual measurement and should be as close in time to the actual measurement as possible. Ideally, the link uses the relative path with respect to the actual NeXus file. Commercial or otherwise defined given name of the program that was used to generate the result file(s) with measured data and/or metadata (in most cases, this is the same as INSTRUMENT/software). If home written, one can provide the actual steps in the NOTE subfield here. Either version with build number, commit hash, or description of a (online) repository where the source code of the program and build instructions can be found so that the program can be configured in such a way that result files can be created ideally in a deterministic manner. Website of the software. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXfluo.nxdl.xml0000644000077000000000000000731614777236751025533 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. Number of energies This is an application definition for raw data from an X-ray fluorescence experiment Official NeXus NXDL schema to which this file conforms. Descriptive name of sample Count to a preset value based on either clock time (timer) or received monitor counts (monitor). preset value for time or monitor ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXindirecttof.nxdl.xml0000644000077000000000000000531414777236751027074 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. Number of detectors This is a application definition for raw data from an indirect geometry TOF spectrometer Official NeXus NXDL schema to which this file conforms analyzed energy polar angle towards sample distance from sample ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXiqproc.nxdl.xml0000644000077000000000000001153714777236751026063 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. The number of values taken by the varied variable Number of values for the first dimension of Q Number of values for the second dimension of Q Application definition for any :math:`I(Q)` data. Official NeXus NXDL schema to which this file conforms Name of the instrument from which this data was reduced. Descriptive name of sample Raw data files used to generate this I(Q) Input parameters for the reduction program used Eventual output parameters from the data reduction program used This is I(Q). The client has to analyse the dimensions of I(Q). Often, multiple I(Q) for various environment conditions are measured; that would be the first dimension. Q can be multidimensional, this accounts for the further dimensions in the data The real name of the varied variable in the first dim of data, temperature, P, MF etc... Values for the first dimension of Q Values for the second dimension of Q ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXlauetof.nxdl.xml0000644000077000000000000001265014777236751026222 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. Number of X pixels Number of Y pixels Time of flight This is the application definition for a TOF laue diffractometer Official NeXus NXDL schema to which this file conforms This assumes a planar 2D detector. All angles and distances refer to the center of the detector. The polar_angle (two theta) where the detector is placed. The azimuthal angle where the detector is placed. Descriptive name of sample The orientation matrix according to Busing and Levy conventions. This is not strictly necessary as the UB can always be derived from the data. But let us bow to common usage which includes thie UB nearly always. The unit cell, a, b, c, alpha, beta, gamma. Again, not strictly necessary, but normally written. Count to a preset value based on either clock time (timer) or received monitor counts (monitor). preset value for time or monitor use these attributes ``primary=1 signal=1`` ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXmonopd.nxdl.xml0000644000077000000000000001255714777236751026065 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. i is the number of wavelengths Number of detectors Monochromatic Neutron and X-Ray Powder diffractometer Instrument definition for a powder diffractometer at a monochromatic neutron or X-ray beam. This is both suited for a powder diffractometer with a single detector or a powder diffractometer with a position sensitive detector. Official NeXus NXDL schema to which this file conforms Optimum diffracted wavelength detector signal (usually counts) are already corrected for detector efficiency Descriptive name of sample Optional rotation angle for the case when the powder diagram has been obtained through an omega-2theta scan like from a traditional single detector powder diffractometer Count to a preset value based on either clock time (timer) or received monitor counts (monitor). preset value for time or monitor Total integral monitor counts Link to polar angle in /NXentry/NXinstrument/NXdetector Link to data in /NXentry/NXinstrument/NXdetector ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXmpes.nxdl.xml0000644000077000000000000023432615046415443025520 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays Number of data points in the transmission function. This is the most general application definition for photoemission experiments. Groups and fields are named according to the `ISO 18115-1:2023`_ specification as well as the `IUPAC Recommendations 2020`_. .. _ISO 18115-1:2023: https://www.iso.org/standard/74811.html .. _IUPAC Recommendations 2020: https://doi.org/10.1515/pac-2019-0404 Datetime of the start of the measurement. Should be an ISO8601 date/time stamp. It is recommended to add an explicit time zone, otherwise the local time zone is assumed per ISO8601. Datetime of the end of the measurement. Should be a ISO8601 date/time stamp. It is recommended to add an explicit time zone, otherwise the local time zone is assumed per ISO8601. Name of the experimental method. If applicable, this name should match the terms given by `Clause 11`_ of the `ISO 18115-1:2023`_ specification. Examples include: * X-ray photoelectron spectroscopy (XPS) * angle-resolved X-ray photoelectron spectroscopy (ARXPS) * ultraviolet photoelectron spectroscopy (UPS) * angle-resolved photoelectron spectroscopy (ARPES) * hard X-ray photoemission spectroscopy (HAXPES) * near ambient pressure X-ray photoelectron spectroscopy (NAPXPS) * photoelectron emission microscopy (PEEM) * electron spectroscopy for chemical analysis (ESCA) * time-resolved angle-resolved X-ray photoelectron spectroscopy (trARPES) * spin-resolved angle-resolved X-ray photoelectron spectroscopy (spin-ARPES) * momentum microscopy .. _ISO 18115-1:2023: https://www.iso.org/standard/74811.html .. _Clause 11: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:sec:11 Array of strings representing the electronic core levels and Auger transitions probed in this MPES experiment. In order for experiments to be comparable, the notation must follow a strict convention. **For core levels:** - The element symbol (chemical symbol) is written first. - It is followed by a whitespace and then the electronic level (e.g., "1s", "2p", "3d", etc.) - Fine-structure splitting levels must include the total angular momentum quantum number **J**, written as a fraction after the orbital label (e.g., "3d5/2", "4f7/2"). - When relevant, fine-structure levels should be specified. If multiple fine-structure levels are probed, they should either be given explicitly or the generic level (e.g., "3d", "4f") can be used. Examples of correct core level notation: - "C 1s" - "O 1s" - "Fe 2p" - "Fe 2p3/2" - "Fe 2p1/2" - "Au 4f" - "Au 4f5/2" - "Au 4f7/2" **For Auger transitions:** - The element symbol (chemical symbol) is written first. - It is followed by a whitespace and the Auger transitions, which can include: - Explicit transitions (e.g., "KLL", "LMM") without fine-structure splitting - Explicit transitions (e.g., "KL1L2", "LM1M2") with fine-structure splitting - Simplified valence notation (e.g., "KVV", "KLV"). - Combinations of the above (e.g. "KL1V"). Examples of correct Auger transition notation: - "C KLL" - "O KLL" - "O KVV" - "O KL1L2" **Additional Allowed Entries:** Besides specific core levels and Auger transitions, the following broader spectral regions can also be listed: - "Fermi Edge" - "Valence Band" - "Survey" **Incorrect Notation Examples (Do Not Use):** - "C1s" (missing space) - "O-1s" (incorrect separator) - "Fe2p" (missing space) - "Au4f7/2" (missing space) - "O-KVV" (incorrect separator) - "Fe 2p_3/2" (incorrect underscore) - "Fe 2p 3/2" (extra space between "p" and "3/2") Description of one coordinate systems that are specific to the setup and the measurement geometry. Multiple coordinate systems can be used if necessary. Contact information of at least the user of the instrument or the investigator who performed this experiment. Adding multiple users if relevant is recommended. Name of the user. Name of the affiliation of the user at the time when the experiment was performed. Description of the photoemission spectrometer and its individual parts. This concept is related to term `12.58`_ of the ISO 18115-1:2023 standard. .. _12.58: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:12.58 Overall energy resolution of the photoemission instrument. Minimum distinguishable energy separation in the energy spectra. This concept is related to term `10.24`_ of the ISO 18115-1:2023 standard. .. _10.24: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:10.24 Ratio of the energy resolution of the photoemission spectrometer at a specified energy value to that energy value. This concept is related to term `10.7 ff.`_ of the ISO 18115-1:2023 standard. .. _10.7 ff.: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:10.7 Any further resolution information about the instrument. For example, the angular resolution of the instrument if the spectrometer is angle-resolving. The source used to generate the :ref:`beam_probe </NXmpes/ENTRY/INSTRUMENT/beam_probe-group>`. Properties refer strictly to parameters of the source, not of the output beam. For example, the energy of the source is not the optical power of the beam, but the energy of the electron beam in a synchrotron or similar. A reference to a beam emitted by this source. Should be named with the same suffix, e.g., for ``source_probe`` it should refer to ``beam_probe``. Example: * /entry/instrument/source_probe/associated_beam = /entry/instrument/beam_probe The source used to generate the :ref:`beam_pump </NXmpes/ENTRY/INSTRUMENT/beam_pump-group>` in pump-probe experiments. Properties refer strictly to parameters of the source, not of the output beam. A reference to a beam emitted by this source. Should be named with the same suffix, e.g., for ``source_pump`` it should refer to ``beam_pump``. Example: * /entry/instrument/source_pump/associated_beam = /entry/instrument/beam_pump Any other source used to generate a beam. This group is to be used for any additional beams that are not described by :ref:`source_probe </NXmpes/ENTRY/INSTRUMENT/source_probe-group>` or :ref:`source_pump </NXmpes/ENTRY/INSTRUMENT/source_pump-group>`. Examples could be a low energy electron source for charge neutralization (see also :ref:`flood_gun </NXmpes/ENTRY/INSTRUMENT/flood_gun-group>`) or an additional laser source. Properties refer strictly to parameters of the source, not of the output beam. Note that the uppercase notation in ``source_TYPE`` means that multiple sources can be provided. The uppercase part can be substituted with any string that consists of alphanumeric characters, including both uppercase and lowercase letters from A to Z and numerical digits from 0 to 9. For example, in pump-probe experiments, it is possible to have both a ``source_laser`` and a ``source_electron``. A reference to a beam emitted by this source. Should be named with the same suffix, e.g., for ``source_laser`` it should refer to ``beam_laser``. Example: * /entry/instrument/source_laser/associated_beam = /entry/instrument/beam_laser Properties of the probe beam at a given location. This is the beam that is used to facilitate the photoemission during MPES experiments. Distance between the point where the current NXbeam instance is evaluating the beam properties and the point where the beam interacts with the sample. For photoemission, the latter is the point where the the centre of the beam touches the sample surface. The source that emitted this beam. Should be named with the same suffix, e.g., for ``beam_probe`` it should refer to ``source_probe``. This should be specified if an associated source exists. Example: * /entry/instrument/beam_probe/associated_source = /entry/instrument/source_probe Properties of the pump beam at a given location. In pump-probe experiments, this is the beam that excites the system, initiating a change in its state. It sets the timing for the experiment by defining time zero in a pump-probe setup. Distance between the point where the current NXbeam instance is evaluating the beam properties and the point where the beam interacts with the sample. For photoemission, the latter is the point where the the centre of the beam touches the sample surface. The source that emitted this beam. Should be named with the same suffix, e.g., for ``beam_pump`` it should refer to ``source_pump``. This should be specified if an associated source exists. Example: * /entry/instrument/beam_pump/associated_source = /entry/instrument/source_pump Properties of any other beam at a given location. This group is to be used for any additional beams that are not described by :ref:`beam_probe </NXmpes/ENTRY/INSTRUMENT/beam_probe-group>` or :ref:`beam_pump </NXmpes/ENTRY/INSTRUMENT/beam_pump-group>`. Should be named with the same suffix as ``source_TYPE``, e.g., for ``source_laser`` it should refer to ``beam_laser``. Distance between the point where the current NXbeam instance is evaluating the beam properties and the point where the beam interacts with the sample. For photoemission, the latter is the point where the the centre of the beam touches the sample surface. The source that emitted this beam. Should be named with the same suffix, e.g., for ``beam_laser`` it should refer to ``source_laser``. This should be specified if an associated source exists. Example: * /entry/instrument/beam_laser/associated_source = /entry/instrument/source_laser Scheme of the electron collection column. The size and position of the field aperture inserted in the column. To add additional or other apertures use the APERTURE group of NXcollectioncolumn. The size and position of the contrast aperture inserted in the column. To add additional or other apertures use the APERTURE group of NXcollectioncolumn. Size, position and shape of the iris inserted in the column. The iris is an aperture in the lens with a variable diameter which can reduce the number of electrons entering the analyzer. To add additional or other slits use the APERTURE group of NXcollectioncolumn. Only one of ``pass_energy`` or ``drift_energy`` should be supplied. ``pass_energy`` should be used when working with hemispherical analyzers. Only one of ``pass_energy`` or ``drift_energy`` should be supplied. ``drift_energy`` should be used if a TOF is used in the energy dispersive part of the electron analyzer. Size, position and shape of the entrance slit in dispersive analyzers. To add additional or other slits use the APERTURE group of NXenergydispersion. Size, position and shape of the exit slit in dispersive analyzers. To add additional or other slits use the APERTURE group of NXenergydispersion. Type of electron amplifier in the first amplification step. Description of the detector type. Contains the raw data collected by the detector before calibration. The data which is considered raw might change from experiment to experiment due to hardware pre-processing of the data. This group ideally collects the data with the lowest level of processing possible. Axes should be named according to the conventions defined below. Note that this list is a glossary with explicitly named axis names, which is only intended to cover the most common measurement axes and is therefore not complete. It is possible to add axes with other names at any time. Raw data before calibration. Detector pixel number in x direction. Detector pixel number in y direction. (Un)calibrated energy axis. The energy can be either stored as kinetic or as binding energy. (Un)calibrated kinetic energy axis. This concept is related to term `3.35`_ of the ISO 18115-1:2023 standard. .. _3.35: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:3.35 (Un)calibrated binding energy axis. This concept is related to term `12.16`_ of the ISO 18115-1:2023 standard. .. _12.16: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:12.16 (Un)calibrated photon energy of the incoming probe beam. Could be a link to /entry/instrument/beam_probe/incident_energy. (Un)calibrated k-space coordinate in x direction. It is envisioned that the axes in momentum space are named ``kx``, ``ky``, and ``kz``. Typically, the vectors in momentum space are defined such that ``kx`` and ``ky`` comprise the parallel component, while ``kz`` is the perpendicular component. It is also possible to define ``k_parallel`` and ``k_perpendicular`` for the parallel and perpendicular momenta, respectively. Units are typically 1/angstrom. (Un)calibrated k-space coordinate in y direction. For more information, see the definition of the :ref:`kx </NXmpes/ENTRY/INSTRUMENT/ELECTRONANALYZER/ELECTRON_DETECTOR/raw_data/kx-field>` axis. (Un)calibrated k-space coordinate in z direction. For more information, see the definition of the :ref:`kx </NXmpes/ENTRY/INSTRUMENT/ELECTRONANALYZER/ELECTRON_DETECTOR/raw_data/kx-field>` axis. (Un)calibrated parallel component in k-space. ``k_parallel`` and :ref:`k_perpendicular </NXmpes/ENTRY/INSTRUMENT/ELECTRONANALYZER/ELECTRON_DETECTOR/raw_data/k_perpendicular-field>` describe how the electron's wave vector ``k`` is split into components relative to the surface. ``k_parallel`` is the component of the electron's wave vector that is parallel to the surface. It is conserved during the photoemission process. This means that the electron's momentum along the surface inside the material is directly related to its measured momentum outside the material. Units are typically 1/angstrom. (Un)calibrated perpendicular component in k-space. ``k_perpendicular`` is the component that is normal (perpendicular) to the surface. It is not conserved during photoemission because the electron experiences a potential change when it exits the material into vacuum. To determine ``k_perpendicular`` inside the material, one typically needs to estimate the inner potential :math:`\phi_0`, which accounts for the energy shift due to the material's work function and electronic structure. Units are typically 1/angstrom. First (un)calibrated angular coordinate. It is envisioned that the axes in angular space are named ``angular0`` and ``angular1``. The angular axes should be named in order of decreasing speed, i.e., ``angular0`` should be the fastest scan axis and ``angular1`` should be the slow-axis angular coordinate. However, ``angular0`` may also be second slowest axis if the measurement is angularly integrated and ``angular1`` could also be the second fastest axis in the case of simultaneous dispersion in two angular dimensions. Second (un)calibrated angular coordinate. For more information, see the definition of the :ref:`angular0 </NXmpes/ENTRY/INSTRUMENT/ELECTRONANALYZER/ELECTRON_DETECTOR/raw_data/angular0-field>` axis. This is typically the slower scan axis compared to ``angular0``. First (un)calibrated spatial coordinate. It is envisioned that the axes in regular space are named ``spatial0`` and ``spatial1``. The spatial axes should be named in order of decreasing speed, i.e., ``spatial0`` should be the fastest scan axis and `spatial1`` should be the slow-axis spatial coordinate. However, ``spatial`` may also be second slow axis if the measurement is spatially integrated and ``spatial1`` could also be the second fast axis in the case of simultaneous dispersion in two spatial dimensions. Second (un)calibrated spatial coordinate. For more information, see the definition of the :ref:`spatial0 </NXmpes/ENTRY/INSTRUMENT/ELECTRONANALYZER/ELECTRON_DETECTOR/raw_data/spatial0-field>` axis. This is typically the slower scan axis compared to ``spatial0``. (Un)calibrated delay time. This is to be used for time-resolved pump-probe experiments and describes the delay between :ref:`beam_pump </NXmpes/ENTRY/INSTRUMENT/beam_pump-group>` and :ref:`beam_probe </NXmpes/ENTRY/INSTRUMENT/beam_probe-group>`. (Un)calibrated temperature axis in case of experiments where the temperature was scanned. This is typically the sample temperature and could be linked from /entry/sample/temperature_env/temperature_sensor/value. Manipulator for positioning of the sample. Device to measure the gas pressure in the instrument. In case of a single or averaged gas pressure measurement, this is the scalar gas pressure. It can also be an 1D array of measured pressures (without time stamps). In the case of an experiment in which the gas pressure changes and is recorded, this is an array of length m of gas pressures. Device to bring low-energy electrons to the sample for charge neutralization In case of a fixed or averaged electron current, this is the scalar current. It can also be an 1D array of output current (without time stamps). In the case of an experiment in which the electron current is changed and recorded with time stamps, this is an array of length m of current setpoints. If any of the beams is monochromatized, an ``NXmonochromator`` can be used to describe the properties of the monochromator. A reference to a beam emitted by this source. Should be named with the same suffix, e.g., for ``monochromator_probe`` it should refer to ``beam_probe``. Example: * /entry/instrument/monochromator_probe/associated_beam = /entry/instrument/beam_probe Insertion device if synchrotron radiation is used for the MPES experiment. A set of activities that occurred to the instrument prior to/during the photoemission experiment, including any activities performed on the individual instrument parts. This group can be used to describe the preparation of the instrument prior to the experiment, e.g. the cleaning procedure for a spin filter crystal. Calibration event on the energy axis. For XPS, the calibration should ideally be performed according to `ISO 15472:2010`_ specification. .. _ISO 15472:2010: https://www.iso.org/standard/74811.html This is the calibrated energy axis to be used for data plotting. Calibration event for one of the axes in the :ref:`NXdata </NXmpes/ENTRY/data-group>`. The naming of these calibrations should follow those in the :ref:`NXdata </NXmpes/ENTRY/data-group>`. For example, for the momentum axis ``kx``, the corresponding calibration should be called ``kx_axis_calibration``. For energy referencing, the measured energies are corrected for the charging potential (i.e., the electrical potential of the surface region of an insulating sample, caused by irradiation) such that those energies correspond to a sample with no surface charge. Usually, the energy axis is adjusted by shifting all energies uniformly until one well-defined emission line peak (or the Fermi edge) is located at a known _correct_ energy. This concept is related to term `12.74 ff.`_ of the ISO 18115-1:2023 standard. .. _12.74 ff.: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:12.74 Electronic core or valence level that was used for the calibration. This should be single string defining the core or valence level that was used for energy referencing. The notation should be the same as the one described in the :ref:`NXmpes/ENTRY/transitions </NXmpes/ENTRY/transitions-field>` field. Reference peak that was used for the calibration. For example: adventitious carbon | C-C | metallic Au | elemental Si | Fermi edge | vacuum level The binding energy (in units of eV) that the specified emission line appeared at, after adjusting the binding energy scale. This concept is related to term `12.16`_ of the ISO 18115-1:2023 standard. .. _12.16: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:12.16 Offset between measured binding energy and calibrated binding energy of the emission line. This is the calibrated energy axis to be used for data plotting. This could be a link to /entry/data/energy. In the transmission correction, each intensity measurement for electrons of a given kinetic energy is multiplied by the corresponding value in the relative_intensity field of the transmission_function. This calibration procedure is used to account for energy-dependent transmission efficiencies in certain lens modes. Transmission function of the electron analyzer. The transmission function (TF) specifies the detection efficiency for electrons of different kinetic energy passing through the electron analyzer. This can be a link to /entry/instrument/electronanalyzer/transmission_function. Kinetic energy values Relative transmission efficiency for the given kinetic energies Describes the operations of image registration (i.e. affine transformations like rotations or translations). Describes the operations of image distortion correction. Any further calibration procedures. For example, a calibration event for the photoemission counts (e.g., by dividing by some base line intensity :math:`I_0`.). Any fit procedures. Array of comma-separated elements from the periodic table that are contained in the sample. If the sample substance has multiple components, all elements from each component must be included in `atom_types`. A set of activities that occurred to the sample prior to/during photoemission experiment. Details about the sample preparation for the photoemission experiment (e.g. UHV cleaving, in-situ growth, sputtering/annealing, etc.). Details about the method of sample preparation before the photoemission experiment. Sample temperature (either controlled or just measured) and actuators/sensors controlling/measuring it. Temperature sensor measuring the sample temperature. In most cases, this can be a link to /entry/instrument/manipulator/temperature_sensor if a manipulator is present in the instrument. Device to heat the sample. In most cases, this can be a link to /entry/instrument/manipulator/sample_heater if a manipulator is present in the instrument. Cryostat for cooling the sample. In most cases, this can be a link to /entry/instrument/manipulator/cryostat if a manipulator is present in the instrument. This is to be used if there is no actuator/sensor that controls/measures the temperature. An example would be a room temperature experiment where the temperature is not actively measured, but rather estimated. Note that this method for recording the temperature is not advised, but using NXsensor and NXactuator is strongly recommended instead. Gas pressure surrounding the sample and actuators/sensors controlling/measuring it. Gauge measuring the gas pressure. In most cases, this can be a link to /entry/instrument/pressure_gauge or to another NXsensor measuring gas pressure (typically, the gauge in closest proximity to the sample) if such a pressure gauge is present in the instrument. This is to be used if there is no actuator/sensor that controls/measures the gas pressure around the sample. An example would be a UHV experiment where the gas pressure is not monitored. Note that this method for recording the gas pressure is not advised, but using NXsensor and NXactuator is strongly recommended instead. Bias of the sample with respect to analyzer ground and actuators/sensors controlling/measuring it. This concept is related to term `8.41`_ of the ISO 18115-1:2023 standard. .. _8.41: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:8.41 Sensor measuring the applied voltage. In most cases, this can be a link to /entry/instrument/manipulator/sample_bias_voltmeter if a manipulator is present in the instrument. Actuator applying a voltage to sample and sample holder. In most cases, this can be a link to /entry/instrument/manipulator/sample_bias_potentiostat if a manipulator is present in the instrument. This is to be used if there is no actuator/sensor that controls/measures the bias. Note that this method for recording the bias is not advised, but using NXsensor and NXactuator is strongly recommended instead. Drain current of the sample and sample holder. Ammeter measuring the drain current of the sample and sample holder. In most cases, this can be a link to /entry/instrument/manipulator/drain_current_ammeter if a manipulator is present in the instrument. This is to be used if there is no actuator/sensor that controls/measures the drain current. Note that this method for recording the drain current is not advised, but using NXsensor and NXactuator is strongly recommended instead. Current of low-energy electrons to the sample (for charge neutralization) and actuators/sensors controlling/measuring it. Flood gun creating a current of low-energy electrons. In most cases this can be a link to /entry/instrument/flood_gun if a flood_gun is present in the instrument. This is to be used if there is no actuator/sensor that controls/measures the flood_gun_current. Note that this method for recording the flood gun current is not advised, but using NXsensor and NXactuator is strongly recommended instead. The NXdata group containing a view on the measured data. This NXdata group contains a collection of the main relevant fields (axes). Axes should be named according to the conventions defined below. Note that this list is a glossary with explicitly named axis names, which is only intended to cover the most common measurement axes and is therefore not complete. It is possible to add axes with other names at any time. In NXmpes, it is recommended to provide an energy axis. Represents a measure of one- or more-dimensional photoemission counts, where the varied axis may be for example energy, momentum, spatial coordinate, pump-probe delay, spin index, temperature, etc. The axes traces should be linked to the actual encoder position in NXinstrument or calibrated axes in NXprocess (or classes inheriting from NXprocess). Calibrated axis for the energy of the measured electrons. The energy can be either stored as kinetic or as binding energy. Calibrated kinetic energy axis. In case the kinetic energy axis is referenced to the Fermi level :math:`E_F` (e.g., in entry/process/energy_referencing), kinetic energies :math:`E` are provided as :math:`E-E_F`. This concept is related to term `3.35`_ of the ISO 18115-1:2023 standard. .. _3.35: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:3.35 Calibrated binding energy axis. This concept is related to term `12.16`_ of the ISO 18115-1:2023 standard. .. _12.16: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:12.16 Calibrated photon energy of the incoming probe beam. Could be a link to /entry/instrument/beam_probe/incident_energy. Calibrated k-space coordinate in x direction. It is envisioned that the axes in momentum space are named ``kx``, ``ky``, and ``kz``. Typically, the vectors in momentum space are defined such that ``kx`` and ``ky`` comprise the parallel component, while ``kz`` is the perpendicular component. It is also possible to define ``k_parallel`` and ``k_perp`` for the parallel and perpendicular momenta, respectively. Units are typically 1/angstrom. Calibrated k-space coordinate in y direction. For more information, see the definition of the :ref:`kx </NXmpes/ENTRY/DATA/kx-field>` axis. Calibrated k-space coordinate in z direction. For more information, see the definition of the :ref:`kx </NXmpes/ENTRY/DATA/kx-field>` axis. Calibrated parallel component in k-space. ``k_parallel`` and :ref:`k_perpendicular </NXmpes/ENTRY/DATA/k_perpendicular-field>` describe how the electron's wave vector ``k`` is split into components relative to the surface. ``k_parallel`` is the component of the electron's wave vector that is parallel to the surface. It is conserved during the photoemission process. This means that the electron's momentum along the surface inside the material is directly related to its measured momentum outside the material. Units are typically 1/angstrom. Calibrated perpendicular component in k-space. ``k_perpendicular`` is the component that is normal (perpendicular) to the surface. It is not conserved during photoemission because the electron experiences a potential change when it exits the material into vacuum. To determine ``k_perpendicular`` inside the material, one typically needs to estimate the inner potential :math:`V_0`, which accounts for the energy shift due to the material's work function and electronic structure. Units are typically 1/angstrom. First calibrated angular coordinate. It is envisioned that the axes in angular space are named ``angular0`` and ``angular1``. The angular axes should be named in order of decreasing speed, i.e., ``angular0`` should be the fastest scan axis and ``angular1`` should be the slow-axis angular coordinate. However, ``angular0`` may also be second slow axis if the measurement is angularly integrated and ``angular1`` could also be the second fast axis in the case of simultaneous dispersion in two angular dimensions. Second calibrated angular coordinate. For more information, see the definition of the :ref:`angular0 </NXmpes/ENTRY/DATA/angular0-field>` axis. This is typically the slower scan axis compared to ``angular0``. First calibrated spatial coordinate. It is envisioned that the axes in angular space are named ``spatial0`` and ``spatial1``. The spatial axes should be named in order of decreasing speed, i.e., ``spatial0`` should be the fastest scan axis and `spatial1`` should be the slow-axis spatial coordinate. However, ``spatial`` may also be second slow axis if the measurement is spatially integrated and ``spatial1`` could also be the second fast axis in the case of simultaneous dispersion in two spatial dimensions. Second calibrated spatial coordinate. For more information, see the definition of the :ref:`spatial0 </NXmpes/ENTRY/DATA/spatial0-field>` axis. This is typically the slower scan axis compared to ``spatial0``. Calibrated pump-probe delay time. Could be a link to /entry/instrument/beam_pump/pulse_delay. Calibrated temperature axis in case of experiments where the temperature was scanned. This is typically the sample temperature and could be linked from /entry/sample/temperature_env/temperature_sensor/value. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXmpes_arpes.nxdl.xml0000644000077000000000000004463115046415443026710 0ustar00rosborn This is a general application definition for angle-resolved (multidimensional) photoelectron spectroscopy (ARPES). Name of the experimental method. If applicable, this name should match the terms given by `Clause 11`_ of the `ISO 18115-1:2023`_ specification. Examples include: * angle-resolved photoelectron spectroscopy (ARPES) * time-resolved angle-resolved X-ray photoelectron spectroscopy (trARPES) * spin-resolved angle-resolved X-ray photoelectron spectroscopy (spin-ARPES) .. _ISO 18115-1:2023: https://www.iso.org/standard/74811.html .. _Clause 11: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:sec:11 Link to transformations defining an ARPES base coordinate system, which is defined such that the positive z-axis points towards the analyzer entry, and the x-axis lies within the beam/analyzer plane. Set of transformations, describing the orientation of the ARPES coordinate system with respect to the beam coordinate system (.). Overall angular resolution along the Nth angular axis. Create one such entry per relevant angular axis, corresponding to the angular axes in NXdata. For hemispherical analyzers, angular0_resolution corresponds to the direction along the analyzer slit, and angular1_resolution to the one perpendicular to it. Analyzer angular resolution along the Nth angular axis. Create one such entry per relevant angular axis, corresponding to the angular axes in NXdata. For hemispherical analyzers, angular0_resolution corresponds to the direction along the analyzer slit, and angular1_resolution to the one perpendicular to it. Reference to the last transformation describing the orientation of the analyzer relative to the beam, e.g. transformations/analyzer_elevation. Set of transformations, describing the relative orientation of the analyzer with respect to the beam coordinate system (.). Rotation about the analyzer lens axis. Its zero reference is defined such that the angular0 axis is increasing towards the positive y axis (analyzer slit vertical). Path to a transformation that places the analyzer origin system into the arpes_geometry coordinate system. Elevation of the effective analyzer acceptance area, e.g. realized by deflectors, or as one angle in a TOF detector. If a resolved angle, place the calibrated axis coordinates here. In-plane analyzer coordinate along a dispersive direction, e.g. along an analyzer slit. If a resolved angle, place the calibrated coordinates here. Scheme of the electron collection column. Reference to the end of the transformation chain, orienting the sample surface within the arpes_geometry coordinate system (sample_azimuth or anything depending on it). Set of transformations, describing the relative orientation of the sample with respect to the arpes_geometry coordinate system. Rotation about the z axis (azimuthal rotation within the sample plane). Offset of azimuthal rotation. Rotation about the x axis (typically a manipulator tilt). Offset of tilt rotation. Rotation about the y axis (typically the long manipulator axis). Offset of polar rotation. Path to a transformation that places the sample surface into the origin of the arpes_geometry coordinate system. There is a field named data that contains the signal. There are three dimensions, one energy and two angular coordinates. Any coordinates that do not move, are represented by one point. Values on the energy axis. Trace of the first angular axis. Trace of the second axis. Could be linked from the respective ``@reference`` field. Represents a measurement of photoemission counts over a three-dimensional space where the varied axes are energy, and one or more angular coordinates. Axes traces should be linked to the actual encoder position in NXinstrument or calibrated axes in NXprocess. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXmx.nxdl.xml0000644000077000000000000015047414777236751025216 0ustar00rosborn These symbols will be used below to coordinate datasets with the same shape. Most MX x-ray detectors will produce two-dimensional images. Some will produce three-dimensional images, using one of the indices to select a detector module. Rank of the ``data`` field Number of scan points Number of detector pixels in the slowest direction Number of detector pixels in the second slowest direction Number of detector pixels in the third slowest direction Number of channels in the incident beam spectrum, if known An array of the hierarchical levels of the parents of detector elements or groupings of detector elements. A top-level element or grouping has parent level -1. functional application definition for macromolecular crystallography Note, it is recommended that ``file_name`` and ``file_time`` are included as attributes at the root of a file that includes :ref:`NXmx`. See :ref:`NXroot`. Describes the version of the NXmx definition used to write this data. This must be a text (not numerical) representation. Such as:: @version="1.0" ISO 8601 time/date of the first data point collected in UTC, using the Z suffix to avoid confusion with local time. Note that the time zone of the beamline should be provided in NXentry/NXinstrument/time_zone. ISO 8601 time/date of the last data point collected in UTC, using the Z suffix to avoid confusion with local time. Note that the time zone of the beamline should be provided in NXentry/NXinstrument/time_zone. This field should only be filled when the value is accurately observed. If the data collection aborts or otherwise prevents accurate recording of the end_time, this field should be omitted. ISO 8601 time/date of the last data point collected in UTC, using the Z suffix to avoid confusion with local time. Note that the time zone of the beamline should be provided in NXentry/NXinstrument/time_zone. This field may be filled with a value estimated before an observed value is available. NeXus NXDL schema to which this file conforms For a dimension-2 detector, the rank of the data array will be 3. For a dimension-3 detector, the rank of the data array will be 4. This allows for the introduction of the frame number as the first index. An optional scaling factor to apply to the values in ``data``. The elements in ``data`` are often stored as integers for efficiency reasons and need further correction, generating floats. The two fields data_scaling_factor and data_offset allow linear corrections using the following convention: .. code-block:: corrected_data = (data + offset) * scaling_factor This formula will derive the corrected value, when necessary. data_scaling_factor is sometimes known as gain and data_offset is sometimes known as pedestal or background, depending on the community. Use these fields to specify constants that need to be applied to the data to correct it to physical values. For example, if the detector gain is 10 counts per photon and a constant background of 400 needs to be subtracted off the pixels, specify data_scaling_factor as 0.1 and data_offset as -400 to specify the required conversion from raw counts to corrected photons. It is implied processing software will apply these corrections on-the-fly during processing. The rank of these fields should either be a single value for the full dataset, a single per-pixel array applied to every image (dimensions (i, j) or (i, j, k)), or a per-image correction specified with an array whose slowest rank is nP (dimensions (np, 1), (np, i, j) or (np, i, j, k)). When omitted, the scaling factor is assumed to be 1. An optional offset to apply to the values in data. When omitted, the offset is assumed to be 0. See :ref:`data_scaling_factor </NXmx/ENTRY/DATA/data_scaling_factor-field>` for more information. Descriptive name of sample This is a requirement to describe for any scan experiment. The axis on which the sample position depends may be stored anywhere, but is normally stored in the NXtransformations group within the NXsample group. If there is no goniometer, e.g. with a jet, depends_on should be set to "." This is the recommended location for sample goniometer and other related axes. This is a requirement to describe for any scan experiment. The reason it is optional is mainly to accommodate XFEL single shot exposures. Use of the depends_on field and the NXtransformations group is strongly recommended. As noted above this should be an absolute requirement to have for any scan experiment. The reason it is optional is mainly to accommodate XFEL single shot exposures. Name of instrument. Consistency with the controlled vocabulary beamline naming in https://mmcif.wwpdb.org/dictionaries/mmcif_pdbx_v50.dic/Items/_diffrn_source.pdbx_synchrotron_beamline.html and https://mmcif.wwpdb.org/dictionaries/mmcif_pdbx_v50.dic/Items/_diffrn_source.type.html is highly recommended. Short name for instrument, perhaps the acronym. ISO 8601 time_zone offset from UTC. Optional logical grouping of detectors. Each detector is represented as an NXdetector with its own detector data array. Each detector data array may be further decomposed into array sections by use of NXdetector_module groups. Detectors can be grouped logically together using NXdetector_group. Groups can be further grouped hierarchically in a single NXdetector_group (for example, if there are multiple detectors at an endstation or multiple endstations at a facility). Alternatively, multiple NXdetector_groups can be provided. The groups are defined hierarchically, with names given in the group_names field, unique identifying indices given in the field group_index, and the level in the hierarchy given in the group_parent field. For example if an x-ray detector group, DET, consists of four detectors in a rectangular array:: DTL DTR DLL DLR We could have:: group_names: ["DET", "DTL", "DTR", "DLL", "DLR"] group_index: [1, 2, 3, 4, 5] group_parent: [-1, 1, 1, 1, 1] An array of the names of the detectors or the names of hierarchical groupings of detectors. An array of unique identifiers for detectors or groupings of detectors. Each ID is a unique ID for the corresponding detector or group named in the field group_names. The IDs are positive integers starting with 1. An array of the hierarchical levels of the parents of detectors or groupings of detectors. A top-level grouping has parent level -1. Normally the detector group will have the name ``detector``. However, in the case of multiple detectors, each detector needs a uniquely named NXdetector. NeXus path to the detector positioner axis that most directly supports the detector. In the case of a single-module detector, the detector axis chain may start here. Location for axes (transformations) to do with the detector. In the case of a single-module detector, the axes of the detector axis chain may be stored here. Suggested container for detailed non-standard detector information like corrections applied automatically or performance settings. For a dimension-2 detector, the rank of the data array will be 3. For a dimension-3 detector, the rank of the data array will be 4. This allows for the introduction of the frame number as the first index. name/manufacturer/model/etc. information. For a time-of-flight detector this is the scaling factor to convert from the numeric value reported to the flight time for a given measurement. Many detectors consist of multiple smaller modules that are operated in sync and store their data in a common dataset. To allow consistent parsing of the experimental geometry, this application definiton requires all detectors to define a detector module, even if there is only one. This group specifies the hyperslab of data in the data array associated with the detector that contains the data for this module. If the module is associated with a full data array, rather than with a hyperslab within a larger array, then a single module should be defined, spanning the entire array. Note, the pixel size is given as values in the array fast_pixel_direction and slow_pixel_direction. A dimension-2 or dimension-3 field which gives the indices of the origin of the hyperslab of data for this module in the main area detector image in the parent NXdetector module. The data_origin is 0-based. The frame number dimension (nP) is omitted. Thus the data_origin field for a dimension-2 dataset with indices (nP, i, j) will be an array with indices (i, j), and for a dimension-3 dataset with indices (nP, i, j, k) will be an array with indices (i, j, k). The :ref:`order <Design-ArrayStorageOrder>` of indices (i, j or i, j, k) is slow to fast. Two or three values for the size of the module in pixels in each direction. Dimensionality and order of indices is the same as for data_origin. Two or three values for the stride of the module in pixels in each direction. By default the stride is [1,1] or [1,1,1], and this is the most likely case. This optional field is included for completeness. Offset of the module in regards to the origin of the detector in an arbitrary direction. Values along the direction of :ref:`fastest varying <Design-ArrayStorageOrder>` pixel direction. The direction itself is given through the vector attribute. Values along the direction of :ref:`slowest varying <Design-ArrayStorageOrder>` pixel direction. The direction itself is given through the vector attribute. Distance from the sample to the beam center. Normally this value is for guidance only, the proper geometry can be found following the depends_on axis chain, But in appropriate cases where the dectector distance to the sample is observable independent of the axis chain, that may take precedence over the axis chain calculation. Boolean to indicate if the distance is a derived, rather than a primary observation. If distance_derived true or is not specified, the distance is assumed to be derived from detector axis specifications. Detector dead time. Elapsed actual counting time. Boolean to indicate if the distance is a derived, rather than a primary observation. If true or not provided, that value of beam_center_derived is assumed to be true. This is the x position where the direct beam would hit the detector. This is a length and can be outside of the actual detector. The length can be in physical units or pixels as documented by the units attribute. Normally, this should be derived from the axis chain, but the direct specification may take precedence if it is not a derived quantity. This is the y position where the direct beam would hit the detector. This is a length and can be outside of the actual detector. The length can be in physical units or pixels as documented by the units attribute. Normally, this should be derived from the axis chain, but the direct specification may take precedence if it is not a derived quantity. True when the angular calibration has been applied in the electronics, false otherwise. Angular calibration data. True when the flat field correction has been applied in the electronics, false otherwise. Flat field correction data. If provided, it is recommended that it be compressed. *** Deprecated form. Use plural form *** Errors of the flat field correction data. If provided, it is recommended that it be compressed. Errors of the flat field correction data. If provided, it is recommended that it be compressed. True when the pixel mask correction has been applied in the electronics, false otherwise. The 32-bit pixel mask for the detector. Can be either one mask for the whole dataset (i.e. an array with indices i, j) or each frame can have its own mask (in which case it would be an array with indices nP, i, j). Contains a bit field for each pixel to signal dead, blind, high or otherwise unwanted or undesirable pixels. They have the following meaning: * bit 0: gap (pixel with no sensor) * bit 1: dead * bit 2: under-responding * bit 3: over-responding * bit 4: noisy * bit 5: -undefined- * bit 6: pixel is part of a cluster of problematic pixels (bit set in addition to others) * bit 7: -undefined- * bit 8: user defined mask (e.g. around beamstop) * bits 9-30: -undefined- * bit 31: virtual pixel (corner pixel with interpolated value) Normal data analysis software would not take pixels into account when a bit in (mask & 0x0000FFFF) is set. Tag bit in the upper two bytes would indicate special pixel properties that normally would not be a sole reason to reject the intensity value (unless lower bits are set. If the full bit depths is not required, providing a mask with fewer bits is permissible. If needed, additional pixel masks can be specified by including additional entries named pixel_mask_N, where N is an integer. For example, a general bad pixel mask could be specified in pixel_mask that indicates noisy and dead pixels, and an additional pixel mask from experiment-specific shadowing could be specified in pixel_mask_2. The cumulative mask is the bitwise OR of pixel_mask and any pixel_mask_N entries. If provided, it is recommended that it be compressed. Counting detectors usually are not able to measure all incoming particles, especially at higher count-rates. Count-rate correction is applied to account for these errors. True when count-rate correction has been applied, false otherwise. The countrate_correction_lookup_table defines the LUT used for count-rate correction. It maps a measured count :math:`c` to its corrected value :math:`countrate\_correction\_lookup\_table[c]`. :math:`m` denotes the length of the table. True when virtual pixel interpolation has been applied, false otherwise. When virtual pixel interpolation is applied, values of some pixels may contain interpolated values. For example, to account for space between readout chips on a module, physical pixels on edges and corners between chips may have larger sensor areas and counts may be distributed between their logical pixels. How many bits the electronics record per pixel. Time it takes to read the detector (typically milliseconds). This is important to know for time resolved experiments. This is time for each frame. This is exposure_time + readout time. The gain setting of the detector. This influences background. This is a detector-specific value meant to document the gain setting of the detector during data collection, for detectors with multiple available gain settings. Examples of gain settings include: * ``standard`` * ``fast`` * ``auto`` * ``high`` * ``medium`` * ``low`` * ``mixed high to medium`` * ``mixed medium to low`` Developers are encouraged to use one of these terms, or to submit additional terms to add to the list. The value at which the detector goes into saturation. Data above this value is known to be invalid. For example, given a saturation_value and an underload_value, the valid pixels are those less than or equal to the saturation_value and greater than or equal to the underload_value. The lowest value at which pixels for this detector would be reasonably be measured. For example, given a saturation_value and an underload_value, the valid pixels are those less than or equal to the saturation_value and greater than or equal to the underload_value. At times, radiation is not directly sensed by the detector. Rather, the detector might sense the output from some converter like a scintillator. This is the name of this converter material. At times, radiation is not directly sensed by the detector. Rather, the detector might sense the output from some converter like a scintillator. This is the thickness of this converter material. Single photon counter detectors can be adjusted for a certain energy range in which they work optimally. This is the energy setting for this. If the detector supports multiple thresholds, this is an array. Description of type such as scintillator, ccd, pixel, image plate, CMOS, ... Group containing the description and metadata for a single channel from a multi-channel detector. Given an :ref:`NXdata` group linked as part of an NXdetector group that has an axis with named channels (see the example in :ref:`NXdata </NXdata@default_slice-attribute>`), the NXdetector will have a series of NXdetector_channel groups, one for each channel, named CHANNELNAME_channel. Which field contains the measured flux. One of ``flux``, ``total_flux``, ``flux_integrated``, or ``total_flux_integrated``. Alternatively, the name being indicated could be a link to a dataset in an NXmonitor group that records per shot beam data. In the case of a monchromatic beam this is the scalar wavelength. Several other use cases are permitted, depending on the presence or absence of other incident_wavelength_X fields. In the case of a polychromatic beam this is an array of length **m** of wavelengths, with the relative weights in ``incident_wavelength_weights``. In the case of a monochromatic beam that varies shot- to-shot, this is an array of wavelengths, one for each recorded shot. Here, ``incident_wavelength_weights`` and incident_wavelength_spread are not set. In the case of a polychromatic beam that varies shot-to- shot, this is an array of length **m** with the relative weights in ``incident_wavelength_weights`` as a 2D array. In the case of a polychromatic beam that varies shot-to- shot and where the channels also vary, this is a 2D array of dimensions **nP** by **m** (slow to fast) with the relative weights in ``incident_wavelength_weights`` as a 2D array. Note, :ref:`variants <Design-Variants>` are a good way to represent several of these use cases in a single dataset, e.g. if a calibrated, single-value wavelength value is available along with the original spectrum from which it was calibrated. In the case of a polychromatic beam this is an array of length **m** of the relative weights of the corresponding wavelengths in incident_wavelength. In the case of a polychromatic beam that varies shot-to- shot, this is a 2D array of dimensions **nP** by **m** (slow to fast) of the relative weights of the corresponding wavelengths in incident_wavelength. In the case of a polychromatic beam this is an array of length **m** of the relative weights of the corresponding wavelengths in ``incident_wavelength``. In the case of a polychromatic beam that varies shot-to- shot, this is a 2D array of dimensions **np** by **m** (slow to fast) of the relative weights of the corresponding wavelengths in ``incident_wavelength``. The wavelength spread FWHM for the corresponding wavelength(s) in incident_wavelength. In the case of shot-to-shot variation in the wavelength spread, this is a 2D array of dimension **nP** by **m** (slow to fast) of the spreads of the corresponding wavelengths in incident_wavelength. This group is intended for use cases that do not fit the :ref:`incident_wavelength </NXmx/ENTRY/INSTRUMENT/BEAM/incident_wavelength-field>` and :ref:`incident_wavelength_weights </NXmx/ENTRY/INSTRUMENT/BEAM/incident_wavelength_weights-field>` fields above, perhaps for example a 2D spectrometer. Flux density incident on beam plane area in photons per second per unit area. In the case of a beam that varies in flux shot-to-shot, this is an array of values, one for each recorded shot. Flux incident on beam plane in photons per second. In other words this is the :ref:`flux </NXmx/ENTRY/INSTRUMENT/BEAM/flux-field>` integrated over area. Useful where spatial beam profiles are not known. In the case of a beam that varies in total flux shot-to-shot, this is an array of values, one for each recorded shot. Flux density incident on beam plane area in photons per unit area. In other words this is the :ref:`flux </NXmx/ENTRY/INSTRUMENT/BEAM/flux-field>` integrated over time. Useful where temporal beam profiles of flux are not known. In the case of a beam that varies in flux shot-to-shot, this is an array of values, one for each recorded shot. Flux incident on beam plane in photons. In other words this is the :ref:`flux </NXmx/ENTRY/INSTRUMENT/BEAM/flux-field>` integrated over time and area. Useful where temporal beam profiles of flux are not known. In the case of a beam that varies in total flux shot-to-shot, this is an array of values, one for each recorded shot. Two-element array of FWHM (if Gaussian or Airy function) or diameters (if top hat) or widths (if rectangular) of the beam in the order x, y The beam profile, Gaussian, Airy function, top-hat or rectangular. The profile is given in the plane of incidence of the beam on the sample. Polarization vector on entering beamline component using Stokes notation Polarization vector on entering beamline component using Stokes notation. See incident_polarization_stokes in :ref:`NXbeam` The neutron or x-ray storage ring/facility. Note, the NXsource base class has many more fields available, but at present we only require the name. Name of source. Consistency with the naming in https://mmcif.wwpdb.org/dictionaries/mmcif_pdbx_v50.dic/Items/_diffrn_source.pdbx_synchrotron_site.html controlled vocabulary is highly recommended. short name for source, perhaps the acronym ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXoptical_spectroscopy.nxdl.xml0000644000077000000000000015571715046415443031032 0ustar00rosborn Variables used throughout the document, e.g. dimensions or parameters. Length of the spectrum array (e.g. wavelength or energy) of the measured data. Number of measurements (1st dimension of measured data arrays). This is equal to the number of parameters scanned. For example, if the experiment was performed at three different temperatures and two different pressures N_measurements = 2*3 = 6. A general application definition of optical spectroscopy elements, which may be used as a template to derive specialized optical spectroscopy experiments. Possible specializations are ellipsometry, Raman spectroscopy, photoluminescence, reflectivity/transmission spectroscopy. A general optical experiment consists of (i) a light/photon source, (ii) a sample, (iii) a detector. For any free-text descriptions, it is recommended to use English, as this ensures the most FAIR (Findable, Accessible, Interoperable, and Reusable) representation of the information. An application definition describing a general optical experiment. Version number to identify which definition of this application definition was used for this entry/data. URL where to find further material (documentation, examples) relevant to the application definition. Datetime of the start of the measurement. Should be a ISO8601 date/time stamp. It is recommended to add an explicit time zone, otherwise, the local time zone is assumed per ISO8601. It is required to enter at least one of both measurement times, either "start_time" or "end_time". Datetime of the end of the measurement. Should be a ISO8601 date/time stamp. It is recommended to add an explicit time zone, otherwise the local time zone is assumed per ISO8601. It is required to enter at least one of both measurement times, either "start_time" or "end_time". An optional free-text description of the experiment. Users are strongly advised to parameterize the description of their experiment by using respective groups and fields and base classes instead of writing prose into this field. The reason is that such a free-text field is difficult to machine-interpret. The motivation behind keeping this field for now is to learn how far the current base classes need extension based on user feedback. Specify the type of the optical experiment. Use another term if none of these methods are suitable. You may specify fundamental characteristics or properties in the experimental sub-type. For Raman spectroscopy or ellipsometry use the respective specializations of NXoptical_spectroscopy. Specify a special property or characteristic of the experiment, which specifies the generic experiment type. This refers to the coordinate system along the beam path. The origin and base is defined at z=0, where the incident beam hits the sample at the surface. This is the default NeXus coordinate system (McStas), if the transformation does not change the coordinate system at all - i.e. it is unity. Otherwise, by this a respective transformation of the beam reference frame to the default reference frame could be made. i.e. exchange of x and z coordinate, rotation of respective coordinates towards each other. Link to transformations defining the sample-normal base coordinate system, which is defined such that the positive z-axis is parallel to the sample normal, and the x-y-plane lies inside the sample surface. Set of transformations, describing the orientation of the sample-normal coordinate system with respect to the beam coordinate system (.). Contact information and eventually details of at persons who performed the measurements. This can be for example the principal investigator or student. Examples are: name, affiliation, address, telephone number, email, role as well as identifiers such as orcid or similar. It is recommended to add multiple users if relevant. Due to data privacy concerns, there is no minimum requirement. If no user with specific name is allowed to be given, it is required to assign at least an affiliation Devices or elements of the optical spectroscopy setup described with its properties and general information. This includes for example: - The beam device's or instrument's model, company, serial number, construction year, etc. - Used software or code - Experiment descriptive parameters as reference frames, resolution, calibration - Photon beams with their respective properties such as angles and polarization - Various optical beam path devices, which interact, manipulate or measure optical beams - Characteristics of the medium surrounding the sample - "Beam devices" for a beam path description - Stages(NXmanipulator) - Sensors and actuators to control or measure sample or beam properties This can be used to describe properties of a photon beam. A beam can be connected to components, via their "inputs" and "outputs". It is required to define at least one incident beam which is incident to the sample. You may specify if this beam parameters are actually measured or just nominal. If this beam is the output of a source, chose the same name appendix as for the NXsource instance (e.g. TYPE=532nm) Select the reliability of the respective beam characteristics. Either, the parameters are measured via another device or method or just given nominally via the properties of a light source properties (532nm, 100mW). The path to the device which emitted this beam (light source or frequency doubler). This parameter is recommended, if the previous optical element is a photon source. In this way, the properties of the laser or light source can be described and associated. The beam should be named with the same appendix as the source, e.g., for TYPE=532nmlaser, there should be both a NXsource named "source_532nmlaser" and a NXbeam named "beam_532nmlaser". Example: /entry/instrument/source_532nmlaser Angle of the linear polarized light, with respect to a fixed arbitrary defined 0° position. Note that the zero reference should be a direction vector for a :ref:`reference_plane </NXbeam/TRANSFORMATIONS/reference_plane-field>` normal in an :ref:`NXtransformations` group within :ref:`NXbeam`. This can be used if no definition of respective coordinate systems for beam and sample normal is done. If coordinate systems are defined, refer to beam "incident_polarization". Description of the detector type. Contains the raw data collected by the detector before calibration. The data which is considered raw might change from experiment to experiment due to hardware pre-processing of the data. This field ideally collects the data with the lowest level of processing possible. Raw data before calibration. Specify respective hardware which was used for the detector. For example special electronics required for time-correlated single photon counting (TCSPC). If available, name/ID/norm of the light source standard. Details about the device information. The path to a beam emitted by this source. Should be named with the same appendix, e.g., for TYPE=532nmlaser, there should as well be a NXbeam named "beam_532nmlaser" together with this source instance named "source_532nmlaser" Example: /entry/instrument/beam_532nmlaser Defines the reference frame which is used to describe the sample orientation with respect to the beam directions. A beam centered description is the default and uses 4 angles(similar to XRD): - Omega (angle between sample surface and incident beam) - 2Theta (angle between the transmitted beam and the detection beam) - Chi (sample tilt angle, angle between plane#1 and the surface normal, plane#1 = spanned by incidence beam and detection and detection. If Chi=0°, then plane#1 is the plane of incidence in reflection setups) - Phi (inplane rotation of sample, rotation axis is the samples surface normal) A sample normal centered description is possible as well: - angle of incidence (angle between incident beam and sample surface) - angle of detection (angle between detection beam and sample surface) - angle of incident and detection beam - angle of in-plane sample rotation (direction along the sample's surface normal) Angle between sample incident beam and sample surface. Angle between incident and detection beam Sample tilt between sample normal, and the plane spanned by detection and incident beam. Inplane rotation of the sample, with rotation axis along sample normal. Angle(s) of the incident beam vs. the normal of the bottom reflective (substrate) surface in the sample. These two directions span the plane of incidence. Detection angle(s) of the beam reflected or scattered off the sample vs. the normal of the bottom reflective (substrate) surface in the sample if not equal to the angle(s) of incidence. These two directions span the plane of detection. Angle between the incident and detection beam. If angle_of_detection + angle_of_incidence = angle_of_incident_and_detection_beam, then the setup is a reflection setup. If angle_of_detection + angle_of_incidence != angle_of_incident_and_detection_beam then the setup may be a light scattering setup. (i.e. 90° + 90° != 90°, i.e. incident and detection beam in the sample surface, but the angle source-sample-detector is 90°) Angle of the inplane orientation of the sample. This might be an arbitrary, angle without specific relation to the sample symmetry, of the angle to a specific sample property (i.e. crystallographic axis or sample shape such as wafer flat) Set of transformations, describing the relative orientation of different parts of the experiment (beams or sample). You may select one of the specified angles for incident and detection beam or sample, and then use polar and azimuthal angles to define the direction via spherical coordinates. This allows consistent definition between different coordinate system. You may refer to self defined coordinate system as well. If "angle_reference_frame = beam centered", then this coordinate system is used: McStas system (NeXus default) (https://manual.nexusformat.org/design.html#mcstas-and-nxgeometry-system) i.e. the z-coordinate math:`[0,0,1]` is along the incident beam direction and the x-coordinate math:`[1,0,0]` is in the horizontal plane. Hence, usually math:`[0,1,0]` is vertically oriented. If "angle_reference_frame = sample-normal centered", then this coordinate system is used z - math:`[0,0,1]` along sample surface normal x - math:`[1,0,0]` defined by sample surface projected incident beam. y - math:`[0,1,0]` in the sample surface, orthogonal to z and x. For this case, x may be ill defined, if the incident beam is perpendicular to the sample surface. In this case, use the beam centered description. Rotation about the y axis (polar rotation within the sample plane). Path to a transformation that places the sample surface into the origin of the arpes_geometry coordinate system. Rotation about the z axis (azimuthal rotation within the sample plane). Specify if there is a lateral offset on the sample surface, between the focal points of the incident beam and the detection beam. Optical components along the optical beam path. Every object which interacts or modifies optical beam properties, may be a component, e.g. Filter, Window, Beamsplitter, Photon Source, Detector, etc, This is the optical element used to focus or collect light. This may be a generic lens or microcope objectives which are used for the Raman scattering process. Polarization filter to prepare light to be measured or to be incident on the sample. Generic polarization filter properties may be implemented via NXfilter_pol at a later stage. Physical principle of the polarization filter used to create a defined incident or scattered light state. Specific name or type of the polarizer used. Free text, for example: Glan-Thompson, Glan-Taylor, Rochon Prism, Wollaston Polarizer... Spectral filter used to modify properties of the scattered or incident light. Type of laser-line filter used to suppress the laser, if measurements close to the laser-line are performed. Blocks shorter wavelengths and transmits longer wavelengths. Blocks longer wavelengths and transmits shorter wavelengths. Blocks a narrow wavelength band while transmitting others. Reflects certain wavelength ranges instead of absorbing them. Reduces light intensity uniformly across all wavelengths. Type of laser-line filter used to suppress the laser, if measurements close to the laser-line are performed. Properties of the spectral filter such as wavelength dependent transmission or reflectivity. Which property is used to form the spectral properties of light, i.e. transmission or reflection properties. Allows description of beam properties via matrices, which relate ingoing with outgoing beam properties. Sample stage (or manipulator) for positioning of the sample. This should only contain the spatial orientation of movement. Specify the type of the sample stage. This allows a description of the stages relation or orientation and position with respect to the sample or beam, if an laboratory or an stage coordinate system is defined. Description of relation of the beam with the sample. How does the sample hit the beam, e.g. 'center of sample, long edge parallel to the plane of incidence'. This is redundant if a full orientation description is done via the stage's "transformations" entry. Type of control for the sample temperature. Replace TYPE by "cryostat" or "heater" to specify it. Hardware used for actuation, i.e. laser, gas lamp, filament, resistive General device information of the optical spectroscopy setup, if suitable (e.g. for a tabletop spectrometer or other non-custom build setups). For custom build setups, this may be limited to the construction year. Commercial or otherwise defined given name of the program that was used to control any parts of the optical spectroscopy setup. The uppercase TYPE should be replaced by a specification name, i.e. "software_detector" or "software_stage" to specify the respective program or software components. Either version with build number, commit hash, or description of a (online) repository where the source code of the program and build instructions can be found so that the program can be configured in such a way that result files can be created ideally in a deterministic manner. Description of the software by persistent resource, where the program, code, script etc. can be found. Pre-calibration of an arbitrary device of the instrumental setup, which has the name DEVICE. You can specify here how, at which time by which method the calibration was done. As well the accuracy and a link to the calibration dataset. Path to the device, which was calibrated. Example: entry/instrument/DEVICE Provide data about the determined accuracy of the device, this may may be a single value or a dataset like wavelength error vs. wavelength etc. Was a calibration performed? If yes, when was it done? If the calibration time is provided, it should be specified in calibration_time. If calibration status is 'calibration time provided', specify the ISO8601 date when calibration was last performed before this measurement. UTC offset should be specified. Generic data which does not fit to the 'NX_FLOAT' fields in NXproces. This can be for example the instrument response function. The overall resolution of the optical instrument. Minimum distinguishable wavelength separation of peaks in spectra. Properties of the sample, such as sample type, layer structure, chemical formula, atom types, its history etc. Information about the sample stage and sample environment should be described in ENTRY/INSTRUMENT/sample_stage. Locally unique ID of the sample, used in the research institute or group. State the form of the sample, examples are: thin film, single crystal, poly crystal, amorphous, single layer, multi layer, liquid, gas, pellet, powder. Generic properties of liquids or gases see NXsample properties. Free text description of the sample. Chemical formula of the sample. Use the Hill system (explained here: https://en.wikipedia.org/wiki/Chemical_formula#Hill_system) to write the chemical formula. In case the sample consists of several layers, this should be a list of the chemical formulas of the individual layers, where the first entry is the chemical formula of the top layer (the one on the front surface, on which the light incident). The order must be consistent with layer_structure List of comma-separated elements from the periodic table that are contained in the sample. If the sample substance has multiple components, all elements from each component must be included in 'atom_types'. ISO 8601 time code with local time zone offset to UTC information when the specimen was prepared. Ideally, report the end of the preparation, i.e. the last known timestamp when the measured specimen surface was actively prepared. A set of activities that occurred to the sample prior to/during the experiment. Sample temperature (either controlled or just measured). If no sensor was available for the determination of temperature, selected a nominal value which represents approximately the situation of sample temperature. Temperature sensor measuring the sample temperature. This should be a link to /entry/instrument/manipulator/temperature_sensor. Device to heat the sample. This should be a link to /entry/instrument/manipulator/sample_heater. Device for cooling the sample (Cryostat, Airflow cooler, etc.). This should be a link to /entry/instrument/manipulator/cryostat. Arbitrary sample property which may be varied during the experiment and controlled by a device. Examples are pressure, voltage, magnetic field etc. Similar to the temperature description of the sample. Medium, in which the sample is placed. Array of pairs of complex refractive indices n + ik of the medium for every measured spectral point/wavelength/energy. Only necessary if the measurement was performed not in air, or something very well known, e.g. high purity water. (Measured) sample thickness. The information is recorded to qualify if the light used was likely able to shine through the sample. In this case the value should be set to the actual thickness of the specimen viewed for an illumination situation where the nominal surface normal of the specimen is parallel to the optical axis. If a thickness if given, please specify how this thickness was estimated or determined. Qualitative description of the layer structure for the sample, starting with the top layer (i.e. the one on the front surface, on which the light incident), e.g. native oxide/bulk substrate, or Si/native oxide/thermal oxide/polymer/peptide. Specify the sample orientation, how is its sample normal oriented relative in the laboratory reference frame, incident beam reference frame. If the sample is grown or fixed on a substrate, specify this here by a free text description. Here generic types of data may be saved. This may refer to data derived from single or multiple raw measurements (i.e. several intensities are evaluated for different parameters: ellipsometry -> psi and delta) - i.e. non-raw data. As well plottable data may be stored/linked here, which provides the most suitable representation of the data (for the respective community). You may provide multiple instances of NXdata Spectrum, i.e. x-axis of the data (e.g. wavelength, energy etc.) Spectrum, i.e. y-axis of the data (e.g. counts, intensity) Calibrated wavelength axis. Parameters that are derived from the measured data. Light loss due to depolarization as a value in [0-1]. Jones quality factor. Reflectivity. Transmittance. Commercial or otherwise defined given name of the program that was used to generate or calculate the derived parameters. If home written, one can provide the actual steps in the NOTE subfield here. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXraman.nxdl.xml0000644000077000000000000002202315046415443025637 0ustar00rosborn Variables used throughout the document, e.g. dimensions or parameters. Number of scattering configurations used in the measurement. It is 1 for only parallel polarization measurement, 2 for parallel and cross polarization measurement or larger, if i.e. the incident and scattered photon direction is varied. An application definition for Raman spectroscopy experiments. This application definition supports a wide range of Raman spectroscopy experiments. These may be as simple as acquiring a single Raman spectrum from spontaneous Raman scattering, or as complex as Raman imaging with a Raman spectrometer. The scope also includes surface- and tip-enhanced Raman techniques, X-ray Raman scattering, resonant Raman scattering, and multidimensional Raman spectra collected under varying conditions such as temperature, pressure, or electric field. The application definition comprises two main components: 1. Structures defined in NXoptical_spectroscopy: * Instrument configuration and data calibration * Sensors monitoring sample or beam conditions 2. Structures specified and extended in NXraman: * Description of the experiment type * Metadata and configuration of the optical setup (e.g., source, monochromator, detector, waveplate, lens) * Detailed description of beam properties and their interaction with the sample * Sample-specific information Information on Raman spectroscopy are provided in: General * Lewis, Ian R.; Edwards, Howell G. M. Handbook of Raman Spectroscopy ISBN 0-8247-0557-2 Raman scattering selection rules * Dresselhaus, M. S.; Dresselhaus, G.; Jorio, A. Group Theory - Application to the Physics ofCondensed Matter ISBN 3540328971 Semiconductors * Manuel Cardona Light Scattering in Solids I eBook ISBN: 978-3-540-37568-5 DOI: https://doi.org/10.1007/978-3-540-37568-5 * Manuel Cardona, Gernot Güntherodt Light Scattering in Solids II eBook ISBN: 978-3-540-39075-6 DOI: https://doi.org/10.1007/3-540-11380-0 * See as well other Books from the "Light Scattering in Solids" series: III: Recent Results IV: Electronic Scattering, Spin Effects, SERS, and Morphic Effects V: Superlattices and Other Microstructures VI: Recent Results, Including High-Tc Superconductivity VII: Crystal-Field and Magnetic Excitations VIII: Fullerenes, Semiconductor Surfaces, Coherent Phonons IX: Novel Materials and Techniques Glasses, Liquids, Gasses, ... Review articles: Stimulated Raman scattering, Coherent anti-Stokes Raman scattering, Surface-enhanced Raman scattering, Tip-enhanced Raman scattering * https://doi.org/10.1186/s11671-019-3039-2 An application definition for Raman spectroscopy. Version number to identify which definition of this application definition was used for this entry/data. URL where to find further material (documentation, examples) relevant to the application definition. Specify the type of the optical experiment. You may specify fundamental characteristics or properties in the experimental sub-type. Specify the type of Raman experiment. Metadata of the setup, its optical elements and physical properties which defines the Raman measurement. Scattering configuration as defined by the porto notation by three states, which are orthogonal to each other. Example: z(xx)z for parallel polarized backscattering configuration. See: https://www.cryst.ehu.es/cgi-bin/cryst/programs/nph-doc-raman A(BC)D A = The propagation direction of the incident light (k_i) B = The polarization direction of the incident light (E_i) C = The polarization direction of the scattered light (E_s) D = The propagation direction of the scattered light (k_s) An orthogonal base is assumed. Linear polarized light is displayed by e.g. "x","y" or "z" Unpolarized light is displayed by "." For non-orthogonal vectors, use the attribute porto_notation_vectors. Scattering configuration as defined by the porto notation given by respective vectors. Vectors in the porto notation are defined as for A, B, C, D above. Linear light polarization is assumed. 3 x 4 Matrix, which lists the porto notation vectors A, B, C, D. A has to be perpendicular to B and C perpendicular to D. Beam which is incident to the sample. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXrefscan.nxdl.xml0000644000077000000000000001055014777236751026201 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. Number of points This is an application definition for a monochromatic scanning reflectometer. It does not have the information to calculate the resolution since it does not have any apertures. Official NeXus NXDL schema to which this file conforms Descriptive name of sample Count to a preset value based on either clock time (timer) or received monitor counts (monitor). preset value for time or monitor Monitor counts for each step ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXreftof.nxdl.xml0000644000077000000000000001145214777236751026047 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. xSize description ySize description nTOF description This is an application definition for raw data from a TOF reflectometer. Official NeXus NXDL schema to which this file conforms Distance between chopper and sample Array of time values for each bin in a time-of-flight measurement Descriptive name of sample Count to a preset value based on either clock time (timer) or received monitor counts (monitor). preset value for time or monitor Total integral monitor counts Time channels Monitor counts in each time channel ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXsas.nxdl.xml0000644000077000000000000001763714777236751025363 0ustar00rosborn The symbol(s) listed here will be used below to coordinate fields with the same shape. Number of pixels in x direction. Number of pixels in y direction. Raw, monochromatic 2-D SAS data with an area detector. This is an application definition for raw data (not processed or reduced data) from a 2-D small angle scattering instrument collected with a monochromatic beam and an area detector. It is meant to be suitable both for neutron SANS and X-ray SAXS data. It covers all raw data from any monochromatic SAS techniques that use an area detector: SAS, WSAS, grazing incidence, GISAS It covers all raw data from any SAS techniques that use an area detector and a monochromatic beam. Official NeXus NXDL schema to which this file conforms. Type of radiation source. Name of the radiation source. Name of radiation probe, necessary to compute the sample contrast. The wavelength (:math:`\lambda`) of the radiation. delta_lambda/lambda (:math:`\Delta\lambda/\lambda`): Important for resolution calculations. The collimation length. This is area detector data, number of x-pixel versus number of y-pixels. Since the beam center is to be determined as a step of data reduction, it is not necessary to document or assume the position of the beam center in acquired data. It is necessary to define which are the x and y directions, to coordinate with the pixel size and compute Q. The distance between detector and sample. Physical size of a pixel in x-direction. Physical size of a pixel in y-direction. This is the x position where the direct beam would hit the detector. This is a length, not a pixel position, and can be outside of the actual detector. It is expected that data reduction will determine beam center from the raw data, thus it is not required here. The instrument can provide an initial or nominal value to advise data reduction. This is the y position where the direct beam would hit the detector. This is a length, not a pixel position, and can be outside of the actual detector. It is expected that data reduction will determine beam center from the raw data, thus it is not required here. The instrument can provide an initial or nominal value to advise data reduction. Name of the instrument actually used to perform the experiment. Descriptive name of sample. Count to a preset value based on either clock time (timer) or received monitor counts (monitor). Preset value for time or monitor. Total integral monitor counts. Name the *plottable* field. The link here defines this name as ``data``. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXsastof.nxdl.xml0000644000077000000000000001524114777236751026061 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. nXPixel description nYPixel description nTOF description raw, 2-D SAS data with an area detector with a time-of-flight source It covers all raw data from any SAS techniques that use an area detector at a time-of-flight source. Official NeXus NXDL schema to which this file conforms type of radiation source Name of the radiation source The collimation length This is area detector data, of number of x-pixel versus number of y-pixels. Since the beam center is to be determined as a step of data reduction, it is not necessary to document or assume the position of the beam center in acquired data. The distance between detector and sample Physical size of a pixel in x-direction Size of a pixel in y direction This is the x position where the direct beam would hit the detector. This is a length, not a pixel position, and can be outside of the actual detector. This is the y position where the direct beam would hit the detector. This is a length, not a pixel position, and can be outside of the actual detector. Name of the instrument actually used to perform the experiment Descriptive name of sample Count to a preset value based on either clock time (timer) or received monitor counts (monitor). preset value for time or monitor ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXscan.nxdl.xml0000644000077000000000000001060014777236751025500 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. Number of points xDim description yDim description Application definition for a generic scan instrument. This definition is more an example then a stringent definition as the content of a given NeXus scan file needs to differ for different types of scans. This example definition shows a scan like done on a rotation camera: the sample is rotated and a detector image, the rotation angle and a monitor value is stored at each step in the scan. In the following, the symbol ``NP`` is used to represent the number of scan points. These are the rules for storing scan data in NeXus files which are implemented in this example: * Each value varied throughout a scan is stored as an array of length ``NP`` at its respective location within the NeXus hierarchy. * For area detectors, ``NP`` is the first dimension, example for a detector of 256x256: ``data[NP,256,256]`` * The NXdata group contains links to all variables varied in the scan and the data. This to give an equivalent to the more familiar classical tabular representation of scans. These rules exist for a reason: HDF allows the first dimension of a data set to be unlimited. This means the data can be appended too. Thus a NeXus file built according to the rules given above can be used in the following way: * At the start of a scan, write all the static information. * At each scan point, append new data from varied variables and the detector to the file. Official NeXus NXDL schema to which this file conforms ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXspe.nxdl.xml0000644000077000000000000000656114777236751025356 0ustar00rosborn NXSPE Inelastic Format. Application definition for NXSPE file format. Official NeXus NXDL schema to which this file conforms. The fixed energy used for this file. Indicates whether ki/kf scaling has been applied or not. Orientation angle as expected in DCS-MSlice ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXsqom.nxdl.xml0000644000077000000000000001063114777236751025537 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. Number of points This is the application definition for S(Q,OM) processed data. As this kind of data is in general not on a rectangular grid after data reduction, it is stored as Q,E positions plus their intensity, table like. It is the task of a possible visualisation program to regrid this data in a sensible way. Official NeXus NXDL schema to which this file conforms Name of the instrument from which this data was reduced. Descriptive name of sample Raw data files used to generate this I(Q) Input parameters for the reduction program used Eventual output parameters from the data reduction program used This is the intensity for each point in QE Positions for the first dimension of Q Positions for the the second dimension of Q Positions for the the third dimension of Q Values for the energy transfer for each point ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXstxm.nxdl.xml0000644000077000000000000002454614777236751025565 0ustar00rosborn These symbols will be used below to coordinate the shapes of the datasets. Total number of scan points Number of photon energies scanned Number of pixels in X direction Number of pixels in Y direction Rank of data array provided by the detector for a single measurement Application definition for a STXM instrument. The interferometer position measurements, monochromator photon energy values and detector measurements are all treated as NXdetectors and stored within the NXinstrument group as lists of values stored in chronological order. The NXdata group then holds another version of the data in a regular 3D array (NumE by NumY by NumX, for a total of nP points in a sample image stack type scan). The former data values should be stored with a minimum loss of precision, while the latter values can be simplified and/or approximated in order to fit the constraints of a regular 3D array. 'Line scans' and 'point spectra' are just sample_image scan types with reduced dimensions in the same way as single images have reduced E dimensions compared to image 'stacks'. Official NeXus NXDL schema to which this file conforms Detector data should be presented with the first dimension corresponding to the scan point and subsequent dimensions corresponding to the output of the detector. Detectors that provide more than one value per scan point should have a data array of rank 1+d, where d is the dimensions of the array provided per scan point. For example, an area detector should have an NXdetector data array of 3 dimensions, with the first being the set of scan points and the latter two being the x- and y- extent of the detector. NOTE: For each dimension > 1 there must exist a dim section such as: <dim index="(dimension index value)" value="(size of dimension)" /> Measurements of the sample position from the x-axis interferometer. Measurements of the sample position from the y-axis interferometer. Measurements of the sample position from the z-axis interferometer. Label for typical scan types as a convenience for humans. Each label corresponds to a specific set of axes being scanned to produce a data array of shape: * sample point spectrum: (photon_energy,) * sample line spectrum: (photon_energy, sample_y/sample_x) * sample image: (sample_y, sample_x) * sample image stack: (photon_energy, sample_y, sample_x) * sample focus: (zoneplate_z, sample_y/sample_x) * osa image: (osa_y, osa_x) * osa focus: (zoneplate_z, osa_y/osa_x) * detector image: (detector_y, detector_x) The "generic scan" string is to be used when none of the other choices are appropriate. Detectors that provide more than one value per scan point should be summarised to a single value per scan point for this array in order to simplify plotting. Note that 'Line scans' and focus type scans measure along one spatial dimension but are not restricted to being parallel to the X or Y axes. Such scans should therefore use a single dimension for the positions along the spatial line. The 'sample_x' and 'sample_y' fields should then contain lists of the x- and y-positions and should both have the 'axis' attribute pointing to the same dimension. List of photon energies of the X-ray beam. If scanned through multiple values, then an 'axis' attribute will be required to link the field to the appropriate data array dimension. List of Y positions on the sample. If scanned through multiple values, then an 'axis' attribute will be required to link the field to the appropriate data array dimension. List of X positions on the sample. If scanned through multiple values, then an 'axis' attribute will be required to link the field to the appropriate data array dimension. Values to use to normalise for time-variations in photon flux. Typically, the synchrotron storage ring electron beam current is used as a proxy for the X-ray beam intensity. Array must have same shape as the NXdata groups. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXtas.nxdl.xml0000644000077000000000000001606114777236751025352 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. Number of points This is an application definition for a triple axis spectrometer. It is for the trademark scan of the TAS, the Q-E scan. For your alignment scans use the rules in :ref:`NXscan`. Official NeXus NXDL schema to which this file conforms Descriptive name of sample Count to a preset value based on either clock time (timer) or received monitor counts (monitor). preset value for time or monitor Total integral monitor counts One of the ei,ef,qh,qk,ql,en should get a primary=1 attribute to denote the main scan axis ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXtofnpd.nxdl.xml0000644000077000000000000001261514777236751026056 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. Number of detectors nTimeChan description This is a application definition for raw data from a TOF neutron powder diffractometer Official NeXus NXDL schema to which this file conforms This is the flight path before the sample position. This can be determined by a chopper, by the moderator or the source itself. In other words: it the distance to the component which gives the T0 signal to the detector electronics. If another component in the NXinstrument hierarchy provides this information, this should be a link. distance to sample for each detector polar angle for each detector element azimuthal angle for each detector element Descriptive name of sample Count to a preset value based on either clock time (timer) or received monitor counts (monitor). preset value for time or monitor ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXtofraw.nxdl.xml0000644000077000000000000001360614777236751026067 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. Number of detectors nTimeChan description This is an application definition for raw data from a generic TOF instrument Official NeXus NXDL schema to which this file conforms This is the flight path before the sample position. This can be determined by a chopper, by the moderator, or the source itself. In other words: it is the distance to the component which gives the T0 signal to the detector electronics. If another component in the NXinstrument hierarchy provides this information, this should be a link. distance to sample for each detector polar angle for each detector element azimuthal angle for each detector element Descriptive name of sample Count to a preset value based on either clock time (timer) or received monitor counts (monitor). preset value for time or monitor ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXtofsingle.nxdl.xml0000644000077000000000000001317714777236751026562 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. xSize description ySize description Number of detectors nTimeChan description This is a application definition for raw data from a generic TOF instrument Official NeXus NXDL schema to which this file conforms This is the flight path before the sample position. This can be determined by a chopper, by the moderator or the source itself. In other words: it the distance to the component which gives the T0 signal to the detector electronics. If another component in the NXinstrument hierarchy provides this information, this should be a link. Distance to sample for the center of the detector polar angle for each detector element azimuthal angle for each detector element Descriptive name of sample Count to a preset value based on either clock time (timer) or received monitor counts (monitor). preset value for time or monitor ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXtomo.nxdl.xml0000644000077000000000000001443414777236751025543 0ustar00rosborn These symbols will be used below to coordinate datasets with the same shape. Number of frames Number of pixels in X direction Number of pixels in Y direction This is the application definition for x-ray or neutron tomography raw data. In tomography a number of dark field images are measured, some bright field images and, of course the sample. In order to distinguish between them images carry a image_key. Official NeXus NXDL schema to which this file conforms In order to distinguish between sample projections, dark and flat images, a magic number is recorded per frame. The key is as follows: * projection = 0 * flat field = 1 * dark field = 2 * invalid = 3 Distance between detector and sample Descriptive name of sample In practice this axis is always aligned along one pixel direction on the detector and usually vertical. There are experiments with horizontal rotation axes, so this would need to be indicated somehow. For now the best way for that is an open question. Total integral monitor counts for each measured frame. Allows a to correction for fluctuations in the beam between frames. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXtomophase.nxdl.xml0000644000077000000000000001520314777236751026557 0ustar00rosborn These symbols will be used below to coordinate datasets with the same shape. Number of bright frames Number of dark frames Number of image (sample) frames Number of phase settings Number of pixels in X direction Number of pixels in Y direction This is the application definition for x-ray or neutron tomography raw data with phase contrast variation at each point. In tomography first some dark field images are measured, some bright field images and, of course the sample. In order to properly sort the order of the images taken, a sequence number is stored with each image. Official NeXus NXDL schema to which this file conforms Distance between detector and sample Descriptive name of sample Total integral monitor counts for each measured frame. Allows a correction for fluctuations in the beam between frames. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXtomoproc.nxdl.xml0000644000077000000000000001163414777236751026426 0ustar00rosborn These symbols will be used below to coordinate datasets with the same shape. Number of voxels in X direction Number of voxels in Y direction Number of voxels in Z direction This is an application definition for the final result of a tomography experiment: a 3D construction of some volume of physical properties. Official NeXus NXDL schema to which this file conforms Descriptive name of sample Name of the program used for reconstruction Version of the program used Date and time of reconstruction processing. Original raw data file this data was derived from This is the reconstructed volume. This can be different things. Please indicate in the unit attribute what physical quantity this really is. This is an array holding the values to use for the x-axis of data. The units must be appropriate for the measurement. This is an array holding the values to use for the y-axis of data. The units must be appropriate for the measurement. This is an array holding the values to use for the z-axis of data. The units must be appropriate for the measurement. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXxas.nxdl.xml0000644000077000000000000001174114777236751025356 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. Number of points This is an application definition for raw data from an X-ray absorption spectroscopy experiment. This is essentially a scan on energy versus incoming/ absorbed beam. Official NeXus NXDL schema to which this file conforms This data corresponds to the sample signal. Descriptive name of sample Count to a preset value based on either clock time (timer) or received monitor counts (monitor). preset value for time or monitor This field could be a link to ``/NXentry/NXinstrument/incoming_beam:NXdetector/data`` Detection method used for observing the sample absorption (pick one from the enumerated list and spell exactly) ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXxasproc.nxdl.xml0000644000077000000000000000642214777236751026242 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. Number of points Processed data from XAS. This is energy versus I(incoming)/I(absorbed). Official NeXus NXDL schema to which this file conforms Descriptive name of sample Name of the program used for reconstruction Version of the program used Date and time of reconstruction processing. Original raw data file this data was derived from This is corrected and calibrated I(incoming)/I(absorbed). So it is the absorption. Expect attribute ``signal=1`` ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXxbase.nxdl.xml0000644000077000000000000001635014777236751025666 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. Number of points Number of X pixels Number of Y pixels This definition covers the common parts of all monochromatic single crystal raw data application definitions. Official NeXus NXDL schema to which this file conforms The area detector data, the first dimension is always the number of scan points, the second and third are the number of pixels in x and y. The origin is always assumed to be in the center of the detector. maxOccurs is limited to the the number of detectors on your instrument. The name of the group is detector if there is only one detector, if there are several, names have to be detector1, detector2, ...detectorn. This is the start number of the first frame of a scan. In PX one often scans a couple of frames on a give sample, then does something else, then returns to the same sample and scans some more frames. Each time with a new data file. This number helps concatenating such measurements. Descriptive name of sample The orientation matrix according to Busing and Levy conventions. This is not strictly necessary as the UB can always be derived from the data. But let us bow to common usage which includes the UB nearly always. The unit cell, a, b, c, alpha, beta, gamma. Again, not strictly necessary, but normally written. The sample temperature or whatever sensor represents this value best Translation of the sample along the X-direction of the laboratory coordinate system Translation of the sample along the Y-direction of the laboratory coordinate system Translation of the sample along the Z-direction of the laboratory coordinate system Count to a preset value based on either clock time (timer) or received monitor counts (monitor). preset value for time or monitor Total integral monitor counts The name of this group id data if there is only one detector; if there are several the names will be data1, data2, data3 and will point to the corresponding detector groups in the instrument hierarchy. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXxeuler.nxdl.xml0000644000077000000000000000766514777236751026101 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. Number of points raw data from a :index:`four-circle diffractometer` with an :index:`eulerian cradle`, extends :ref:`NXxbase` It extends :ref:`NXxbase`, so the full definition is the content of :ref:`NXxbase` plus the data defined here. All four angles are logged in order to support arbitrary scans in reciprocal space. Official NeXus NXDL schema to which this file conforms The polar_angle (two theta) where the detector is placed at each scan point. This is an array holding the sample rotation angle at each scan point This is an array holding the chi angle of the eulerian cradle at each scan point This is an array holding the phi rotation of the eulerian cradle at each scan point ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXxkappa.nxdl.xml0000644000077000000000000000745614777236751026057 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. Number of points raw data from a kappa geometry (CAD4) single crystal diffractometer, extends :ref:`NXxbase` This is the application definition for raw data from a kappa geometry (CAD4) single crystal diffractometer. It extends :ref:`NXxbase`, so the full definition is the content of :ref:`NXxbase` plus the data defined here. Official NeXus NXDL schema to which this file conforms The polar_angle (two theta) at each scan point This is an array holding the sample rotation angle at each scan point This is an array holding the kappa angle at each scan point This is an array holding the phi angle at each scan point This holds the inclination angle of the kappa arm. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXxlaue.nxdl.xml0000644000077000000000000000514214777236751025677 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. Number of energies raw data from a single crystal laue camera, extends :ref:`NXxrot` This is the application definition for raw data from a single crystal laue camera. It extends :ref:`NXxrot`. Official NeXus NXDL schema to which this file conforms expect ``signal=1 axes="energy"`` This is the wavelength distribution of the beam ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXxlaueplate.nxdl.xml0000644000077000000000000000400514777236751026722 0ustar00rosborn raw data from a single crystal Laue camera, extends :ref:`NXxlaue` This is the application definition for raw data from a single crystal Laue camera with an image plate as a detector. It extends :ref:`NXxlaue`. Official NeXus NXDL schema to which this file conforms The diameter of a cylindrical detector ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXxnb.nxdl.xml0000644000077000000000000000704314777236751025352 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. Number of points raw data from a single crystal diffractometer, extends :ref:`NXxbase` This is the application definition for raw data from a single crystal diffractometer measuring in normal beam mode. It extends :ref:`NXxbase`, so the full definition is the content of :ref:`NXxbase` plus the data defined here. All angles are logged in order to support arbitrary scans in reciprocal space. Official NeXus NXDL schema to which this file conforms The polar_angle (gamma) of the detector for each scan point. The angle by which the detector has been tilted out of the scattering plane. This is an array holding the sample rotation angle at each scan point ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXxps.nxdl.xml0000644000077000000000000012762715046415443025373 0ustar00rosborn This is the application definition for X-ray photoelectron spectroscopy. A name of the experimental method according to `Clause 11`_ of the `ISO 18115-1:2023`_ specification. Examples for XPS-related experiments include: * X-ray photoelectron spectroscopy (XPS) * angle-resolved X-ray photoelectron spectroscopy (ARXPS) * ultraviolet photoelectron spectroscopy (UPS) * hard X-ray photoemission spectroscopy (HAXPES) * near ambient pressure X-ray photoelectron spectroscopy (NAPXPS) * electron spectroscopy for chemical analysis (ESCA) .. _ISO 18115-1:2023: https://www.iso.org/standard/74811.html .. _Clause 11: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:sec:11 In traditional surface science, a left-handed coordinate system is used such that the positive z-axis points along the normal of the sample stage, and the x- and y-axes lie in the plane of the sample stage. However, in NeXus, a coordinate system that is the same as `McStas`_ is used. `xps_coordinate_system` gives the user the opportunity to work in the traditional base coordinate system. .. _McStas: http://mcstas.org/ .. image:: xps/xps_cs.png :width: 40% Link to transformations defining the XPS base coordinate system, which is defined such that the positive z-axis points along the sample stage normal, and the x- and y-axes lie in the plane of the sample stage. Set of transformations, describing the orientation of the XPS coordinate system with respect to the beam coordinate system (.) or another coordinate system. The transformations in the ``NXtransformations`` group depend on the actual instrument geometry. If the z-axis is pointing in the direction of gravity (i.e., if the sample is mounted horizontally), the following transformations can be used for describing the XPS coordinate system with respect to the beam coordinate system (.): .. code-block:: xps_coordinate_system:NXcoordinate_system depends_on=coordinate_transformations/sample_stage_to_source_azimuth coordinate_transformations:NXtransformations sample_stage_to_source_azimuth=beam_azimuth_angle @depends_on=sample_stage_to_source_polar @transformation_type=rotation @vector=[0, 0, -1] @units=degree sample_stage_to_source_polar=beam_polar_angle_of_incidence @depends_on=. @transformation_type=rotation @vector=[1, 0, 0] @units=degree Note that this ``NXtransformations`` group is not needed when the defined :ref:`transformations in beam_probe </NXxps/ENTRY/INSTRUMENT/beam_probe/transformations-group>` are used. In this case, this group shall not be written here to avoid circular references in the transformations chain. Description of the XPS spectrometer and its individual parts. This concept is related to term `12.58`_ of the ISO 18115-1:2023 standard. .. _12.58: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:12.58 Reference to the transformation describing the direction of the beam relative to a defined coordinate system. Should point to /entry/instrument/beam_probe/transformations/beam_direction. Beam direction in the XPS coordinate system after rotation. Incidence angle of the beam with respect to the upward z-direction, defined by the sample stage. Azimuthal rotation of the beam from the y-direction defined by the sample stage. This should point to the coordinate system defined in /entry/xps_coordinate_system. Reference to the transformation describing the orientation of the analyzer relative to a defined coordinate system. Polar tilt of the analyzer with respect to the upward z-direction, defined by the sample stage. The angle between the incoming beam and the analyzer is given by beam_analyzer_angle = beam_polar_angle_of_incidence + analyzer_take_off_polar_angle. In practice, the analyzer axis is often set as the z axis (analyzer_take_off_polar_angle = 0), so that beam_analyzer_angle = beam_polar_angle_of_incidence. For magic angle configurations, this angle is 54.5°. Azimuthal rotation of the analyzer from the y-direction defined by the sample stage. This should point to the coordinate system defined in /entry/xps_coordinate_system. Peak model for XPS fitting. Each `NXfit` instance shall be used for the description of _one_ peak fit in _one_ XPS region. As an example, this could be used to describe the fitting of one measured C 1s spectrum. This concept is related to term `3.29`_ of the ISO 18115-1:2023 standard. .. _3.29: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:3.29 Input data and results of the fit. Dependent variable for this fit procedure. This could be a link to entry/data/data. Independent variable for this fit procedure. This could be a link to entry/data/energy. This could be a link to entry/data/energy. Intensity values of the fitted function at each energy in the position field. This concept is related to term `3.15`_ of the ISO 18115-1:2023 standard. .. _3.15: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:3.15 Type of fit function used. The user is encouraged to use one of the options defined in the enumeration, but in case none of these fit (e.g., in the case of very complex line shapes), a different value for the ``function_type`` field can be used. In that case in particular, but also if one of the suggested values is used, the functional form of the peak should be given by the ``formula_description`` field. The user is also encouraged to use the ``description`` field for describing the fit function in a human-readable way. The Gaussian function models peaks with a symmetric shape, commonly arising from instrumental broadening and thermal motion in XPS. It is defined as :math:`G(x) = \frac{A}{\sigma \sqrt{2\pi}} \exp\left(-\frac{(x - \mu)^2}{2\sigma^2}\right)`, where - :math:`A` is the peak amplitude, :math:`\mu` is the peak position - and :math:`\sigma` is the standard deviation. The full width at half maximum (FWHM) is given by: :math:`\text{FWHM} = 2\sqrt{2\ln(2)} \sigma`. The Lorentzian function describes peaks that originate from lifetime broadening due to the finite lifetime of excited states. It has more pronounced tails compared to the Gaussian function. The Lorentzian function is defined as :math:`L(x) = \frac{A}{\pi} \frac{\gamma}{(x - \mu)^2 + \gamma^2}`, where - :math:`A` is the peak amplitude, :math:`\mu` is the peak center, - and :math:`\gamma` is the half-width at half-maximum (HWHM). The full width at half maximum (FWHM) is given by: :math:`\text{FWHM} = 2\gamma`. The Voigt function is a convolution of a Gaussian and a Lorentzian function. It provides a more accurate representation of XPS peaks by incorporating both instrumental broadening (Gaussian) and intrinsic lifetime broadening (Lorentzian). It is defined as :math:`V(x; \sigma, \gamma) = \int_{-\infty}^{\infty} G(x') L(x - x') \,dx'`, where - :math:`G(x')` is the Gaussian function with standard deviation :math:`\sigma`, - and :math:`L(x - x')` is the Lorentzian function with half-width :math:`\gamma`. The FWHM of the Voigt function is approximately: :math:`\text{FWHM} \approx 0.5346 \cdot \text{FWHM}_L + \sqrt{0.2166 \cdot \text{FWHM}_L^2 + \text{FWHM}_G^2}` where - :math:`\text{FWHM}_L = 2\gamma` (Lorentzian FWHM) and - :math:`\text{FWHM}_G = 2\sqrt{2\ln(2)} \sigma` (Gaussian FWHM). The Gaussian-Lorentzian Sum is an approximation to the Voigt function where the line shape is simply the sum of a Gaussian and a Lorentzian function :math:`GL_{\text{sum}}(x) = \eta L(x) + (1 - \eta) G(x)`, where :math:`\eta` (ranging from 0 to 1) controls the relative contribution of the Lorentzian component. The **Gaussian-Lorentzian Product** function provides an approximation to the true Voigt function by multiplying a Gaussian and a Lorentzian line shape. This model is often used to describe peak broadening due to both instrumental resolution (Gaussian component) and intrinsic lifetime effects (Lorentzian component). The function is defined as: :math:`P(x, \eta) = (1 - \eta) G(x) \cdot \eta L(x)` where: :math:`\eta` is the **mixing parameter** (:math:`0 \leq \eta \leq 1`), controlling the balance between the Gaussian and Lorentzian contributions. This method ensures that the resulting peak retains characteristics of both functions while avoiding excessive weight in either the Gaussian or Lorentzian component. The Asymmetric Lorentzian function modifies the standard Lorentzian shape to asymmetry on either side of the peak. Oftentimes, the the asymmetric modification is achieved by introducing asymmetric broadening through power-law scaling on either side of the peak. The **asymmetric modification** is introduced using exponents :math:`\alpha` and :math:`\beta` to alter the line shape differently for :math:`x \leq E` and :math:`x > E`: :math:`LA(\alpha, \beta) = \begin{cases} [L(x)]^\alpha, & x \leq E \\ [L(x)]^\beta, & x > E \end{cases}` where: - :math:`L(x)` is the symmetric Lorentzian function. - :math:`\alpha` controls the asymmetry on the **low-energy** side (:math:`x \leq E`). - :math:`\beta` controls the asymmetry on the **high-energy** side (:math:`x > E`). This asymmetric Lorentzian model is particularly useful in XPS to account for asymmetries arising from inelastic scattering processes and core-hole screening effects. Note that this is not the only possibility to introduce asymmetry. The exact functional form should be given by the ``formula_description`` field. The Doniach-Sunjic function models asymmetric peaks arising from many-body interactions in XPS, particularly for core-level spectra influenced by conduction electrons. It is given by :math:`DS(x) = A \frac{\cos\left( \pi\alpha / 2 + (1-\alpha) \tan^{-1} \left(\frac{x - \mu}{\gamma} \right) \right)}{(x - \mu)^2 + \gamma^2}^{(1-\alpha)/2}`, where :math:`\alpha` (0 \leq :math:`\alpha` < 1) controls the asymmetry. When :math:`\alpha = 0`, the function reduces to a symmetric Lorentzian. One major challenge in using asymmetric peaks is ensuring that the fitted line shape correctly models the peak intensity while being confined to physically meaningful integration limits. Standard asymmetric peaks, like the ``Lorentzian Asymmetric`` function, may extend indefinitely, making it difficult to compare intensities when peak areas exceed the boundaries defined by background subtraction or experimental data constraints. The Asymmetric Finite function is an empirical modification of the asymmetric functions that introduces a damping parameter to gradually suppress the asymmetric tail, ensuring that peak intensity remains localized within the relevant spectral region. Typically, the asymmetric parameters are modified depending on the distance from the peak such that the overall area under the peak remains finite. This function is especially valuable when standard background approximations like **Shirley or Linear backgrounds** constrain the data to a specific range, making infinite asymmetric tails impractical. The functional form depends on the implementation and should be given by the ``formula_description`` field, if possible. Human-readable description of the peak fit function. Area of the peak. Width of a peak at a defined fraction of the peak height. Usually, this will be the Full Width at Half Maximum of the peak (FWHM). For asymmetric peaks, convenient measures of peak width are the half-widths of each side of the peak at half maximum intensity. This concept is related to term `3.28`_ of the ISO 18115-1:2023 standard. .. _3.28: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:3.28 Position of the peak on the energy axis. Total area under the peak after background removal. This concept is related to term `3.16`_ of the ISO 18115-1:2023 standard. .. _3.16: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:3.16 Atomic concentration of the species defined by this peak. This should be a value between 0 and 1. Functional form of one of the fitted XPS backgrounds. This concept is related to term `3.21`_ of the ISO 18115-1:2023 standard. .. _3.21: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:3.21 Type of fit function used. The user is encouraged to use one of the options defined in the enumeration, but in case none of these fit (e.g., in the case of very complex line shapes), a different value for the ``function_type`` field can be used. In that case in particular, but also if one of the suggested values is used, the functional form of the background should be given by the ``formula_description`` field. The user is also encouraged to use the ``description`` field for describing the fit function in a human-readable way. Linear background, i.e., a simple straight line from the minimal to the maximal abscissa value. The Linear background is the simplest background model, which assumes a straight line between the minimum and maximum binding energy values. This model is used when there is a gradual, uniform increase or decrease in the background across the spectrum. The Shirley background is based on the idea that the background intensity at any given binding energy is proportional to the total intensity of the peaks above that background in the lower binding energy range. Essentially, the Shirley background estimates the contribution of the background under each peak and adds them up to define the overall background shape. The Shirley background is commonly used in the analysis of high-resolution XPS data when peaks are located near edges or in regions of significant overlap with the background signal. While the exact mathematical formulation can be complex, the background is represented as an integral over the lower binding energy range to describe the cumulative contribution to the background: :math:`B(x) = \int_{-\infty}^{x} \frac{I(\mu)}{1 + \mu - x} d\mu` where - :math:`I(\mu)` is the intensity of the peaks at binding energy :math:`\mu`, - :math:`x` is the binding energy at the current point. The Tougaard background is based on the concept of universal cross-sections and is used for modeling the XPS background in situations where the background is integrated from the peak intensities at each binding energy to higher kinetic energies. It is useful when fitting the background in spectra that display significant low-energy tailing or when the background exhibits a non-linear rise with binding energy. The model incorporates the notion of electron energy loss and the behavior of the photoelectrons as they travel through the material and lose energy. It is a more sophisticated background model compared to the linear and Shirley approaches. Mathematically, the Tougaard background can be described as: :math:`B(x) = \int_{x_0}^{x} \sigma(E) I(E) \, dE` where - :math:`\sigma(E)` is the universal cross-section at energy :math:`E`, - :math:`I(E)` is the intensity at energy :math:`E`, - :math:`x_0` is the threshold energy for the background. The Step Down background is commonly used to fit data when a sharp decrease in the signal occurs at a certain binding energy, such as in the case of an abrupt edge or a "step-down" feature in the spectrum. It is modeled using a complementary error function (erf), which provides a smooth transition from the higher intensity region to the lower intensity region. This model is useful when the data exhibits a sharp cutoff, for example when modelling the Fermi Edge. The mathematical expression for the step down background is: :math:`B(x) = A \cdot \text{erfc}\left(\frac{x - x_0}{\sigma}\right)` where - :math:`A` is the amplitude, - :math:`x_0` is the threshold binding energy where the step occurs, - :math:`\sigma` is the width of the transition region, - :math:`\text{erfc}(x)` is the complementary error function. The Step Up background is similar to the Step Down background but is used to model a sharp increase in intensity, such as when a peak or feature rises suddenly above the baseline. This background is also modeled using the complementary error function, providing a smooth transition from a low intensity region to a high intensity region. The mathematical formulation for the step up background is: :math:`B(x) = A \cdot \text{erf}\left(\frac{x - x_0}{\sigma}\right)` where - :math:`A` is the amplitude, - :math:`x_0` is the binding energy where the step up begins, - :math:`\sigma` is the width of the transition, - :math:`\text{erf}(x)` is the error function. Human-readable description of the background fit function. Reference to the transformation describing the orientation of the sample relative to a defined coordinate system. Rotation about the sample normal. Polar tilt of the sample with respect to the upward z-direction, defined by the sample stage. Azimuthal rotation of the sample from the y-direction defined by the sample stage. This should point to the coordinate system defined in /entry/xps_coordinate_system. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/NXxrot.nxdl.xml0000644000077000000000000000741714777236751025564 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. Number of points raw data from a rotation camera, extends :ref:`NXxbase` This is the application definition for raw data from a rotation camera. It extends :ref:`NXxbase`, so the full definition is the content of :ref:`NXxbase` plus the data defined here. Official NeXus NXDL schema to which this file conforms. The polar_angle (two theta) where the detector is placed. This is the x position where the direct beam would hit the detector. This is a length, not a pixel position, and can be outside of the actual detector. This is the y position where the direct beam would hit the detector. This is a length, not a pixel position, and can be outside of the actual detector. This is an array holding the sample rotation start angle at each scan point This is an array holding the step made for sample rotation angle at each scan point ././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.7849882 nexusformat-2.0.0/src/nexusformat/definitions/applications/canSAS/0000755000077000000000000000000015060352601023706 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/canSAS/2012-minimum.png0000644000077000000000000002032514777236751026500 0ustar00rosbornPNG  IHDR([ IDATxXSOsC Rj2`iGsD4u 73-T2.^+N-6mc,Vk%A/-+uHȏgǷ='||ós֭[ ru`~A< ( B< ( B< (JftED] ;'"[nLW(vwF}Y2L:a.yxE,IfK͊OE^`GڙPLzʦJ ~+Tl})zȹSjP z<\7VNIvkٿQL|LZ$ʦJ[xSi6vb냧]*Iۚ)ˉy;t5:qXYeX,y?ȟ}Զ~3na} ~NjzơٔPh5rr^r"CPx7[:~O0>kvb#."rK#f@q1_'xʦSMy"ixMjt\qFSC"B"C! fS.zhy?puGl7$&Q茾GG[^XNUDIe;~Y#.}ow˻^{Mی?;fEP8־0_6^:\_-ss[~?]JSn?14$'Y{Ë*^ǒѱO+C8ͯ܋>shxqɴl.\BDl.)+5vez2/#ffv_usMu[Kןٳխ@z]}]^QR+$8gOW]`;{~Ssv GIeG)hxTazz{vN']S@8 AAwν]'[4ogkϒ om:n wQΦojZ,?[UaKR"ڟ/oƀj=";Vʴey,SY=o#"mVWVjYsusśV!x"MZZ SQ*IF2e,YUZN\mocFM/޸?w`5kҶ~KgBH4"bgeXLM(fvqkm6kia!'I \|Le3 LVv/8ADlKKo6? juk_r閬YD462]D$F1kAϦ<+O[7Xlcnyq8]*:\?ȟ-gp_X\ Oo`WbV@A&)Aaq׈h;tFTLT9o`_ ̂>Ϊ 5:]w .SPlgpݜz{R0ILۭnNLM۶n]Ŏ7F.4fۃא3Kۭ=j8Z\]bj6e,#"[f*]*99vt%/Sf*M&ݤmMu_i>ՖV'W?vuCfV}K]ʜx}|YWrFspx0띰唨K7nJñ3 ,wlduM El4/=P,yÉ|fOm/\z72g]NG$Jׅ~rA؄X.|x!-%O曍 qvWej[V<s[R,|ɥs+=V)T/WoKƖ[\F)jtP.jhC[b.Rk52 mRل3{U檗)aC!6!-E.W͖SOX@kl6*զ+9Ӟn9< [vމ,z{._g?2OQd(sGo%4k0n D.$LrpXC`u_&}}|#"6[( oKOTq`V舧H5OIU4t$={7g)u떳ꚓD"N=}0} /NI @$}4a-r9y͛9vX,=*~GfR[bU}Q1B,_zї^Ax4O Z4UN062V{jq_W_`WXzFG_{^x4E988h^>='-aN'*V|7,;?wF?jOà }g^~m7k}r -xzzl!_r˛y+OS>xX߅|yˇ D-E/D3%(H8FGGIZHjٟNm ;7ߡU%W||gL2{rap?ɿtY~x)i#髁27n|R 5lkmo3:.v΍k  ޚ|M+pG:АK.=8hp,?9iϜn| vfԾs8ƍ~a{C3::uDlp߄+'1+lBsӏT?hQ1M߻[|~8* \Rhg蕻ӷ-o'[CBBY1=_,z͘-[DT߷=""YܒQې2~ȊݸKD 3O%YV<fݚ6[La:e޾=tOҩPA{^xW=+'L$tLV0>:;Og;BAȥ򘤃/f*>$4t weK8Ymgz|ZK{zzQlSY:<o^n{-?q_m.9V'Myf έ`Z[XS˻UQQ>Cw_6Ku^94U֛7zE߷5u[<0%AxL[wwCÃī'iw3_ǭKWAw߷̟tuCs< 0 B< ( }<p|}|\ |}|8608&P B< ( B< ( B< ( B< ( «aFc;:\ vS[fV['su0l4W2>FFds\ݡ:]B3j(zVEj[al4O6g63ƊMV |6pWޞDtec\JmHD$L*2G]fQ/PWXbj}IChNYN\ S)3Y;($"L[vg`@IR7}zomEmlBllɪ%|ẹmMDJ*PusH]l YjGjt k5?-Pp@BFDu>w/e"n-YbMzNz4"2ꍥ٥uGy Cm 5!!fSц0jĠyxy@+ָnﯜ,;iL`mG QG5x])2\W?[sKB%RgtZ֤q8kMmFMf674GK%\-&"f‡ڛGtPnݺ6D.|V8P|T&e+:s#"U=l4v?Ej~Eulm؄XSR6W(&> 655S$ersUD7pc/υ+Dq<fĵØ|@D˒p脏q8d6/_<240>9vM/wVV^[Y?|ՏI}1Cw*<0} 0B< ( η< W||}] p)\K < ( B< ( B< ( CB):6խ銊j7::.p7'su# IN kפmMsu+QlNLDL2S\[Q^vu_/.Vd(f`}A*L[¶C&&KO"ʤ9MnU 9nb[*iiPɹ7 *3<htx>4YkW k< (,.XrZeg7<=SRt ^(l`NAL̞wpHD $a&m<=u5:[j׶`ͪSMxSىybMҺ$IĵL@0EMW-yjI$ խ&u떫0$tM4:9].SI9'N@Vvћ.i =`q P3ॖnM<480&vjA!x@PA!x@PH):6խ銊j7::x<<%0Bר] S0w x@PA!x@PpIDAT`^߼'9_'.^0 x&֮;;Q$Jq)T0B< (׈G 0nݺ6"Ov#q8 Cm ( 3 0]>>nżXz]*KIENDB`././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/canSAS/Q-geometry.jpg0000644000077000000000000003013414777236751026467 0ustar00rosbornhdepiction of the defined geometry that defines Q for small-angle scattering (art work by Pete Jemian)Photoshop 3.08BIM}xKdepiction of the defined geometry that defines Q for small-angle scatteringz Pete JemianP Pete Jemian720040802JFIFC   %# , #&')*)-0-(0%()(C   ((((((((((((((((((((((((((((((((((((((((((((((((((( " W !1AQa"2qR#348BVWbr$CSs%5dtuTc01!A2Q"aqB ?J" """ ""/ǹc$j-aEVhj:L,0|!a, ;֫}uhԴd2>p9_YfvrWIމ>PSiMH.$=<\xxJQ̟mz^3k;]0~O=ž}*"gk =ȿzhV )lJZ3 u}G}o:7Ug9s_BaeT]%YUI\T"FENYK'$}wNϫlZuͽ%Mĉ+wDpN=V;D)y5H"ϼB^m3Cc *ZvBoT<:9Ǹ I> *!Q%c5r}>AuE@ -dz0OevrDL̎kKwV!55Z55HDDD@3h=m]rJt,/tx怹⤒IixO+]X{>%ʀ""'#-DyG(DU[tmOg˃D12I 'n4g> # HE-D1O 2J1"68p""" """ 8*`h৅K#ZƎ$yP{XmyWUŽQ(8Uuߵt9Y7I#acSJZ/lJ븽+GZ^$Epst ~ilTG M g&)9r",">h;ߦLѲJy] n >A֪uje΅O+<1kۜŻ{=R1_\i5*mm]c/w="a"" 8qk! HZA6?ؔIB+R""Y""u5lG5{884Z+*詤*zx_, kG<ƶ)u]PJ꣣`vibniマPZ" u6{cMooon>9v#vQd4VKn܌ws;š]a].tq{8Wj2{knv{v{Ϩy|nk$0O:fi Y!{UQu]ύL0)d;K7dDG#<q@a3fFT`oOnOp}}m'vOEg!՘8j(0sv#_3vVr>YMEHOS+ccrp2IZij4ZS) |Oq)kZk`iW<e}=d^X~.hsH-# EA-p`A:祘حκX0F< VlH-phBvT~Q-Ii:HՌuLC2 sq;o)ulDD][ƊA5mҮ :8FO czp T{HQ3gT^n+ƪ;e,`sZY+G]ӎ>sFVMO -,xzm6h kZ0 D@XԾ-~[KG忻 D@DDD@DDGhJ*A֕rl' AS3Ek⑥kCATmdTΨ92A_Z?*]CDUJAKžjָ+ h$y.]GwԳjFIIxNIXs`d^E6q<DqC3{Ê]]DTS{%DgvH>`V%/mjJX=ͫ_edtWiC x P^E:FdQWKl o>nO.C >wEXe cxkmNQN](7E򳝿,s*+)4֦ ,SD{IC c}xݽYro5Ω 9v[g9<:{]~INOJ{լzMu1(%vwOЉ G-OcKK38~i[fҷ=YA}l*Vv:v΋xIu<z;$ARܚ(psR9Qm/CrFX7!z zus ᛾qny0CGǵc֘ ]w-9k.1я[Ƶާր.YW8зwKY<(DDum?t#/cۇ0>u=Dc}*j<1/'࿉})F%%kR(bKO 8v A TDkiŽɵ1`<;g_,O|T/_,28 9O -Cz4Tj_O’ȏV~R&kUt4V=4M.YO?y<׻m&&+ ?q -_5TW-_pk]$>#,} !COcGu@dvJ]˨+w@9`׆m48-R7c14p Iw4x={8áBӷ*+^sh{f PCep rp@ma耲⤨i,1FsH# @Z[Z !vq:Gs}vQRh5FmUx#j ceC[i{n;mE{iGfj _,?c c-gUV&FOvG;i="{2G~Aq>WN7t"G,j_\?-[Rvl݄Ԉ" """ ""?rMVbXzyĺCk;SzZA *ew F{Z}23|"&^l6Mee'wiݦ,x7.tJr'mV8Eu'h~&OƭHXI{Ym/{p%}Yoo6b=e9-)@e ]u}m8M;hԬ[{p>ibZ C6,/F Dv:d8)u@.yUεUu mINwG؏8w-=*J8PDִIIO֫+m[W':"*" 74 D@8hO1r#8OƮJguzj΁KOʎ/"L""m o=4j {+si'03‰7:z՗hvo.V ^_}sכ`8D)ލ$dpAֻsLRYjk̒]MUuF;IFxIDUv[h+U?QccUvuۯF;~??+Ԉ" ڗvԱ]}p[(a""32]E=Γh c[ECR 9'=J_>jE/u}o>rϺuƀڑb9K_[O]4imQ?;psshχz⤲[D)M- )!΋x,##yk@ᣞ\@rϺuƟ9K_[@mJW ]+˄sIIEk+a p=-_>OdNϯmW][ 9q{㟈n sE[E͖k7%Afpk 𿟺/aTrmo"a yzd[7hjv.v7ə }@iV QYbj[ ,$K;Op.p2z)NMGHu胧 J8g xM[Z;'qWzO=r85g)`""" ,x>dNj摐 v=f4De 8wRGHQwVW*_b)"*կhǿ=m=Ӳtͪ!+U`Wz,iq4lWmYI $O|.̒&3xs ҅ J.Y݄XLk:Jm!^_U^=^w.-'R4dή}s/3nUYbԴˣQE4@ iq/#8Fł=CuIL&Akk <^WheuN#͚2Dq Ft|E$BK͎Rq̅G]3IN)#eWpi j5#R<ŧRپvՔNֻofZncիf[lΧRxsR3{tqڎLj5ʚ׼MmIa.p0" +BcƑn\ctl^= ѽpA 6M╡ѽi0/,rZX|Ge8|sVFEDDD@DDD@DDD@DDD@R;hʶJ)|e2&Tn[Y])%BI*w B8B"-`ZkUA-4NW;hiDjzM\,J[W`%Zqy!($py[ctq4yas>8*vu3٥ {dk~CǵTC4֣WzF**ӖdVZƕhF+դ8y"ԖԵJ۽Ę' 1İ}[vcږ5 -7C~Y V.ud{ 伃ȜNE%',ѥkRڹ,aq˩$l{r##D]#!TkZNK m\Ƈ@ KkTVq[^YizIQ> N{(w-d:«WXj_s6MJ(-kx Шwu_ jM^+kxԽ""y" 3frKҞT1Tx3-ZpDEpDDD@DDD@DDD@DDMپXz7}t6sCY2y|n )" ""}m޻[lLS0sW8oO FRQYe;:׵ooҗhjmuZ04J>jY4%s-uc4R= 19d3's ؤBQW%xvU5VD:3hq;m(cs-d5R8tg UiEӽZ)J1\.̈́D@Q{:V_/Q: 7aHF:9)žY䈊|""" """ """ """ *Lwml[q?7CbjPWH"`љg4\<>Y="-%p" /,mrSA}^)m5}hzpMGK=LC%E>L2<xxPR;Y5=ϼYxk4KLlo'Hx[N")Iɹ>XDD0y{kuiWI25oŭsZmzD˅uLtSL787wȍ7j5UVuStlb#.lS0ZK kO6gioU]0KI@H5U:ƌ%oRuח{Kv>籦"x, PO] X!w&'%SOgobiE˟4:N<|fwL9!UiDWOի:ӕJ-k""" &YSYZmG7r7Fn^GΧA+Օwh4YuW"##Ee7Mjж {>Go{8%oG=dZCw.5n3$yq9sy8I<+" """ """ """ ,{ȃS NwW⌒DR%#t7$রT,2A]IqeM w2 { nZ'N*U-(+_UѹԳ$E>ңߥ.^uRԹ=ǎI.weIZ%A2UoSЋ|82*i&q?' .SDD""" ""!8<\}6YZK_UI .{c'J1rxDƺG%U|O<$' 6l91U#,= YpVGrT՜c܆Œ#x8ǫ'־ۧuEG՚Xa,tEJ F OnlVMGVzV31ߵ߯#tՎas%z{WRB{# ~IqUFث'}-Ll9ho޸ng3J(6ԴEki1;1LjyPhՎٴDhq8w?QW}Hl_gtsitĈ| ςh^5Զ*cU5x#wnwU4.QGzsҚe=88'1ࢢ\4ݖh*ˆ82? ?sS}!eU ȩ E ymcQ?<>.K0u*/"MY^_"k;1b?9øl(C#5`h_hDYQQXALD@DDD@DDD@DDD@DDD@DDD@Ak#Nj2nX4 Zz`ן=vp2SҾx+-sjF5:?h<˳ѱ*,¯ӥu 6Qzk&|EoZIeW~" I : NX_NUMBER @units = Q : NX_NUMBER @units = NX_PER_LENGTH ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/nxdlformat.xsl0000755000077000000000000002304014777236751025533 0ustar00rosborn (overlays NXentry) (overlays NXsubentry) (base class definition, NXentry or NXsubentry not found) : NX_CHAR [] , --> @ : ( base class application definition ) ././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.7852354 nexusformat-2.0.0/src/nexusformat/definitions/applications/xps/0000755000077000000000000000000015060352601023410 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/applications/xps/xps_cs.png0000644000077000000000000044273015046415443025437 0ustar00rosbornPNG  IHDR)sRGBgAMA a pHYs&?IDATx^ UW*W<ّS~d2kԡ$)18IJIR` !QAoAo{u={f~׬Yf^sgYұ!PQ.CY( o٭E1^%Ymlf!PQ.C- jf(iӦ h"]24d݄tܙBB-\0d(hZ P_ jB:.l[nBKۘ j?fWJ)[VS !)(x jeXU;#)7Œ@%L~bٳg;YiO!.(=z(^lV 3ۀ(ua*^LbIV $wԢ#Z2X&ă]U(jfCr5\oׯW&%ڵBos{UbVO{q_jۄ+n<dso|rO>agϞ*2n8 袋(TT4֭[g\̚5BpP=~w1?zARْB/]`gV(\ꪊB0Tع{%I\+x#X P +l/&]=Un(P#\xaH. s >m|;N%8' # 'Ls9묄F< H s]fy (~Klm:E (P|Uݰ\z󰊸R\Sv!9 goRv-"0SV@#:v&ԞbIVPpa>m(F}kAp<Òv P h5Rח,YB߇BX(>*R6Ʊpj!f\ǖ%PGij/P5PE HD#9X`:f )alѢpLɲ0# 9׽4,K5;*RàgS!G2f:(T;(ǏsN YV.]Z|L2!:bE(WH'Œ@Q֛|flY"^ݮd~ѺG]˿t'FnEf*iX(>vj~ϳP2roS(>T̙c/o`4AE g\j/߹mqK`-nڴII)dO0k_GZ<)x1Z8p3vX bIVTpfsq[<5!q(j1ŹѰkel/{Wm{S^ AE 's-q^z(TɆ (x 8,Œ@B)'\pGEr JRX/\e}xᒭx6()&wn?lmoY8L1EwPUjY^zŒ@Bz^=…|Ԧ()d)8(aB?(d} &:ү_? AqŒ@5ݪ᥀yXCmu|o%uU(a<1NJǎ)T$LU=0zh ?N?{L^KqLظ m5(T 7m?qtrHHӼڎfzaKQ)[=܉jZy]~Y^)Ԓw?Hd)d) "L?چ=(=Bposh gaNR, 90CyAggEZqj𷳬 j!7t%YcSș_fKvjZg&o^L!ڳ} bIV 2l0 UZe_5yZAorT%@ *e(>rUZ{ToXP1hnI *e(>V{BеpmBfߟPrуBej9r#2\XH/0m7?NmrzUrll &^ %G$+P| 3)TÉ'_xBs qYZ6(<Ecc]p_xF{($KT0'j\Mt0o(YuyB:th wV\CN9-1˗/̧~P<7O scMRl0xzwa[%I}md5!!Qk?C'~9vwcv|?JE ؗ|G=)fT-!_\zo~)rAAfCa%W9Sc?5Ǫ@3e{G m4@- 5LũqMeQ(^(TnÅYݺuP tTuAѯPx7[S ]CzsI5\myJsMwSȲm|Be7γ-ZDkEg'Iq_aϴ(7{ƠS* o1j} 4A*e_UXrQ | d26\Ϻv)|se>Pr (NkfVKZ\azKahnH 5םV+}B'Y^2Tj@#%\"n<6!Mzρx楿S6^ӵu.0p@ *e(>T+զ/X~%)T 5lKa/ݻwh0*e(>S:hY:R Z;Ggl7~fPm__A)͠I'Dkq aXد/wT &MI1DoLbjoJ`%YC!b iuBTymFja?N-6%aO|ͽ馛}U Y q_SƵ2 ՖZvBL|!9TQBE GBpfxm'US͂Bv Pc-7".v{KnO` 9uݯaRŤ&Vy40(Y#%L/+uąۇc%LQ1c:~aPQ.C{ x[#/ _KJ]&=_&BA2Omw=>}*6tyEL/l1 ǂ ʸq2nU ZXu&-VVz&p*e(T9)).^0#h)M\-:K.N: PQ.C刂 u m8[T8|&(P w jCj- v+8B@E 'Bs)n+MA^|l|}'3\e]*՚0_^{$qύc,X1nA02^`A\ւ8Q^ոlBkZ0|4ROE ǂ:l6"mle^\cG tu{$;TP|l7h$]{u(ؐ/NeA!;BE ŷ wAr`߲[m,@E \Jvۯ~L[!PQ.CY5AH;Œ`*Ⱥ B\fĉƂZ!4'(A &T[hZۄR, o,Ȫ)I\u4mX(:2fՄ"_ڳEf䠢\mLYse`*̺ߟ 2oU #N߹_e`zk\Dq}7mDk{dp~>f)G%oD/0좮\@u=86SL (H۶m+ o(9~:׭XiN<Xv]˅JǎKT-0=qky szunڇe4Ҵ_(K%ZqyD-OV5N_g3g"M7]YzY[>u)t;Ck"$G$+P|Uw* 3۠A)V8zcģGWW bd {)0{Rؤgªsǝ@ćq}17V럱]'o^yc:ͥ, ejBK{w- nzD/f?ưBDK{Tu*jU n `d ;[5}S:LqljVFA"g\j/=GRY륧nh;Zغ%[(exڵkG!!PQ.CkH!qRAw}F &JTP|@}?}>ozv޻UZ rOAQ 5 |)o [C$Q4iݺ5҃]U(>/o8^oX5g*; F~^keJqXu;(d*e(>1؞ݴ%~ЮSҨGvߦOFz_ / sX{# oQ簆(7,abxz)/K7%Yjz#6*㲭 m5(B 0\*/8#nݺQ(PQ.CBee}xu|0m䭲|)A<72_Qu όR[SSVU.a4h^^>^F]U(.hjj냿{͆\4jPQ.CiLA#S2_ps&ԹoP((SG ꤽ7v`ݹ=m&j6k]~ǪbIVHa] tȴV qU8$HLUB5Ǥwbɒ%D5g?PQ.C8(Qs_8au{_{eV{blذBbu5G`@9kJ wyVYo4掠xo۬NydItgWޣh\#r7azr*9m2qQSsֲ WML:N s%)T:~w/UFJ=ڻ)^z頑Y5s g<%Yc'¬FR9߸l**AS|{9h${rֵfҚ?>}=*a^x\ %k;fB͛7S([K炾}RS S=wҴ_d54A2W_Bè{#+܃oBP, _sF!wmţ޷捒mۖBDᵓr/qKaNDeX Y:^miemv G/l_;udK8@}xObn$'(wR<ªq93cjI+ jJZO- 4z︖h=/KI<]U(fTQ}\zy^n[Xa` |F:=PQ.o :QfXrڵ+y ZWQaN_P5Ыm<f;7l*eX/n[YF'Ԕ<#?c/ƍs?ȀZ*O^~'#;h!^ Z G{[,˿Tl{_FگBmčc&ޱtjJưQA+)B6%E% 5F@+Œ@q:qx臧֊ie ˸3qpOY'HҥKEf;msNcکSQ.CٶӹŽYw5! WpgB}׊F{PirkP }{8y楿Svz}e5 (~ j E.*?`~!0/T- hFOBuVS%Yk:d[k@_Ӧc::rCv50(ERvD$+P|hQ ?^9nyp5O+Aa@by۟8y鸆\=Ikt(W"O Z%7qCE {k;XbR,Ao€1R-OA\&5TP|O/MZ)^zkN4f{! * ǟ("*e(^(&ZsэiDQ/TamE48*e(>6jYH=QkWS(8~T):q8LMIPQ.CuӃꁳ) ([dѴm Jбk̤(q: w]NSK ɍDE ה$PԺp$ x+{FE ŧ'_x-Vu ̗E(IGP+w$[PQ.CBذYprRjΈirZfm, d B w f9ڷgAW;CAKd;gzAA Dss#6:fA|P. Q:o{1FA@D~+FǾD ?;ClUlr~l~uhZ7&lge .?V޽) Eo+ѱcGkcfoC!^LbtNf(KJW%Kׯ >XWa#5} Dcg(kU!(&Ƥ\ yJ_ot!,b #4:(NONGQ.P:Wx_O8F66](7^ό5nX!5 JW$59`F׊GUCWt>x-褫gu4 dA<ѪU;i(G!o`.UKnӶ08'i~(yܸqVϞ=i-s s8O\HᾺC<3d~>غvJ9 yt'`Ӷ, -Qcu z*RڵB<1<c:6;eQ#(&{Ş={,M& xx!49~.X=aEE06zh:|0k,y6 DFqJźB))-[ұI/X!ʻ;.0 U!8 6=]>C Y>uс𻏺xb8u]3挮=٦z [ʏ;=RUj5\%u묓O>َ6As#uGW 煥U+#nӦMv :r…vPpoܡt@6U2iT[{o(7!+LU?Rn25J}3O쮺ꪒU?;9u;D=v9;eq #pz~Œ_.Hip E Jderj4F\\!5ʶ;.2W|q(ux699P{m~46z~)inݺYd\U 8M* ޮ٠C"|q8j'jOO ~ ubz4,\~1Sx?vK!~+w(],rُZ8_'dos&Ԋ|F 3@C=Ṕbj3|S.P؀59`?/Ԇy  #9/&\qF7}8<%t]tØ_}u,3r RSS樣6=pj]Hqلܱ3.#.8dA3YzP; c}wqmgqRaqF`'*/8|v BRG%lg  G|h.[EÂWl 8jQTEj CM!tЁBrs)ZmOyb?xF ܱ3nK.}4tϞ=m%rf8[&d zJ?l6,ŮP/ZOC!|xav%:1(8o1CQpdrEo;G(h>٩ ΓIjvܱ3.yǩږU\촥ܹ҉3 Tyl}󡷬j7J P NC=}c/CכU:M7Uo"Y AqhVGǚ?yߚlv JWW'A\;8OΛ)Xq8Wa]tBuYCAQ(츃~4;TQѢU C WEot?lx۱D<<;veTͿxl ൃ ޒ 23b B0c.y[CyBQ bW(о}{ e]R%{졐 v_ܾzw+9ܱ3.@IrSRUnMk}}`}y o\]6i ֢_6n,;K{Xw,^c]s,{wnp.!{hE{-/.cF<ҡ<3vjԪuԅwnP)mZ)䝴w rPLi.ՔEZa~nI{]"e#)HľvurxXH]tX ƗNcJ.](ԟa]r|S%(_>ֲMgY TƷMNuˡ7Jp/ uV gz-ZD!oL{e՛ ?6GvW4s8ҳכإArAN-o޼ڹ {p?;z9ya`CPs 'T{d9 J)TX U3` %GV(T#!iY=^hϾPd~So6)腨_VY荝%Ơ(ԒS_N?δ{< yW^ F3*mۖB~A G-^,TG̺unj 1zi.h@*RMF$˖b].\|ܯ0QjSWgrz_ SL3I6Cݼ^uFu_1:ݨi-MrPT懫Ceذa)?j&S(yva1)cA`__;^F栓h);C"yeN~[4_MuQ2VIu`Uߚ?k[5b|cT 2B֩^>Zꐢ7vҥQ+)!/af`ܹ3ЬtÔ6G޴I-/_BZYyö 3p5^u?.kYTk}䎝t1}LKQ(]^c5_,Y.5U'tXiwֵ9k+?b >qB9ˍ[[:^k)Zn~"А;vҵ28SGwA8x(ٷbJ]UrWwkڣKeVIxQ-59e'3ݻ7:l3mJ;6ض]tĩU0cH;fYSU[qxH )S(9:h'κ{߬pn~z;~ѫu D:2ڼ9ڦzNκ]@"4НȫڇE TK?,A=V䠙;Pg:lŠo,iźW) a Oon}z{ l2N7k~zc=OSEg=,Y_ wla;Vvj5x[ۜ3bj-W?Z*p)T$3tP`$W9J'`Fy O}gᾧ;~:s_)uYl֊6`p9h, K*X~1O]tRMQa4TUX6,x^MlvT1o _?F,~$2?> %Cmt_ ?[ 1*nuQ' O!Q^1}v&Ask!}!ngU#rrY -GϔC<<_xkQ*bF(G118IL;oSJ/iWp`QuA3;7>4짿o/Gy5yrͪS_HI9AJ 0csZQo6샗[TVA_۸B/mQݳjkm xb$*4[CRÅQ(yԱxطt7)&Ժ5Iڝ43oemThds{njC!gR8o<oc> q?&b  %Zpw(]IaBfρxgQouY/Ib8h<~38ffhQ⇑#uQ&JUZ;ve/#A9J IH ~Zq^i'iǐ1n9EQiM狳 @J)(nq`u*zr&LufU7nX5hi1 Zm-i%8\NZDGZR.PLQN|)%<6I#Moo|Fq.F,'-f \ѝMNX3Q'\fsiI rP̃if/{1dGWK3iZz}:41_Vۂ'ӊmx5fZw׿5Mrǂ$_rP 2GcnG*7$s6!Fx]cg(]AAyfwp/☣uP@5"Hz۸GZYZ䎝tukCZhܶ˾Z xqoow^yFoJ2+`KkɂoJy䎝to+4?iMqz`ʶZ̪*jo{M𻽶{7ZGsuy.?m90NMJ)~0]6ia1`И+*Ivw-[d .7O׺4\"u ^{+X2$gBܱ3.s=Dq;h!ͼ-(!w ⠅8i⠅X w ,p⠅@gz* cAAA⁔ P#;CAAJ' rP:O eKA!lgsrُl'6qD* ܱ3HSS6GU8h|JAcg(] Uk۶-AR.PZXx18{,% ܱ3Ξ=xitnd! ]4<脽ZssAH+䎝s cp B0;ӣGkC ~ w }ct~l/P@DF(;Ap-M^k7[v BR.P:ɚ{kV-mGN֯_O[(zc( 1-KACuҪIbW( VMׯmذr27o6:hLzFPw JW6:_?sLFl\b 4|CJWLׯu֍rݻ!W|ҡJ=䎝tCGA`~yuFG 䂢7vUcr~!{@909_6{rM6 AZM&tطzuM7Q}JgdW7ds&/M6 CTLN,C`bUR #;uۜ9s(GX|FmU AOmx_RWcW˧|r)FMcǎtdA䎝tL<|+m6ϩ[)G49Ըӧ?o+yAEosLRͤՔP2n#۾+t ~JWlu'pBlrI,!;B骂N?xJLcۢ0YȱKz4)]w('VYq~S-|R}MNT5uD0v* .V\IkfsΡP8܎3nܸPpܡt"U:e\'Oi&\q{PVL郘Ϣ\pPO>d{i& Un^ݔޱ3]n袋%XNԼ9RtjH>CCfCMu=l)7!KwύNTUٜFCӽVT#ڠ ΒPXr^,uU# tn#Ը9/nzjZr;.07o6:_iLa LN㝶)N9?`:lRmqm&yX_u588djz:~[?U]c_n;.|anT۽OPG;PUI= 00lc~LtRQt ω;.4o- 8ñia#LNm~)#ZΝ;,!?ʻ;.4Z2:_sA-uUVQBٰaс/~tU zճKhguJ.]h&S%(l@JNz3G~ (&~,lM4NϤ3Ku!w K`EUCEvnPLoKh3g,Z4Lq@ !ԇ6lk9ۓN:ɚt=N:GEJ )#-.tܙBe(dfh;폃[KoX;JB1Q ~(zc(].|Hjۥ0yu/`_}lY[ěc564Yh܌<}y6mrÔSz_>}THSHP!w &PP54»g\j8a7}`鰿lmrp!em`]t!%i5h-9[yo&|Gz]tB?gW8\uF:A\ (䌚)7TG}nX3]tҳgϊ%wq (zc(].A4ÊDoC8a,bǽnGEZ9G +jAiF! rP\Dd9wgumojLk3Δ,;j8gW ֑fΘUZMӚ78P7;CrKԗC o{5Cu;X~=j JkFg kzlLرc).ƇFOQ[%m IګFqVy-[caܑT^?*0B-j433p(6쨑NP|K O@r 1^H\/ͨ mpȈ:h|tD uꦥ'r+>B?兊%3i6{ ' v=MJ{Fa/Unj}iBmݡ:[UG S5`E'Bߦwj)rԋ/Guva(zc(]]V.}Q vB}p+4h_*k/j8 ErP`޸Y.j3y)oƏOl' ϓ;nK:k1U4P䰊yhn݄~̗sՆa ҆8oT$*z|xa_֝ODQSxaܢ׬Fwo߂JWWe{,UgAǚJIyT?oj64:+ A>dȖPYM;;+ .SD Y` cE3N:d/(׬W-XѾg^;8IhtN(0Gt ǫ&:Ce͍Z^F~(T h6f j3Dõ|ߓSfÞmO4pmg vFAv*ܱiQ :a}Y Te#FP(;^:,)uYψ/Fpݡt{P럝@Azb&cNeU=_ߙ{/ [[W޶֜n;.9j7  rnmk 5k4Cs.Uڿ}rP"|߹-Y:N= G0\j_. J4k}V&Xv)hu(/k4:N/a? vMZmv]tgvO,/l#L,_B!ۙzsIcYxM`b$ J &o6l]ˣK.4N4t"w{NBθ}0APݠtbs4|]}R(ôu_%U/M6*xQD& I J9揰=g %C-z.zj6`y?=xt*:3WEY2:5%[: yg<_w3׃vs}Bި) 8 E etVOGv[nꨱ/TG ԗAб BZPMnI&sk[E y#{y`ʜ7^qc#EovI;iٶ٤hW<:k7e"vnK7z9lu|h_amRpznJz-_XQݩ]/ .zkU{%۵kG2i+ױ0/?kذa]K0 %?/]MD5r=}䎝t[z1CNKzQ;&QqJNJu}f^[7ʗW}'%]m0(gï;CYxUG]ͩ_Y۪1}xH`|N' ?E!gzKuIdIe|ҹ\|݈QzpEo삝*;d7|ACXV2|p  *%) =las)"tRUө7jcwrPfL!3ӧO;aoԗ׊7OEr;~E<|C~su'Nh=3[v[Mrԓ\M|R.PԐ6Ak2e V{r {sBg;y/vҥ ai3*> fG,ý:Ejc6;vҥ&-P::<5_mc[k:ڱmkh;/3f Q *mP% -'ŋپsҌ:I'd/U'}'usq;꼪jrP qct UnH~X۸Bb~SCIuJ[p퍕J u1}?H5 _qWʍw#5:g*n:jmM9k?Eok0ZwVCgf>&'̞%'{+[ n 2m9{GQ  3[veiz1q);#;g*}{ǃ Z9k?âf7vUNv˨uQ.<;Ɔ&ǁm5s gff.gڶmK"N4MCl^XA@JWSjUԤGv2wE1ELnݚBfx#F˼GI61Ov>!cJ:HUp:o JWSj`àUCޠڰgκ@vt#q? -΃fFm~$ KQ1av%:ju6ͻbcr{Jq&VW}r\3_)춗P2]ew҅B%MψoFA^ƱzzgEwo%z݋wTyvh9 Vx4<㸞g(:d'E :jݹ 6Q#^a<9q)Wׅ}55t|DBnK4ڰ,&G=oeU>HܽrsCﶡͤ9vUG= ^^PsuQVG77q9ᩗ'q9cM'ɖ"GxRTgmN#qpV5G m3hB+3W*Wq#;Cj lӝ3UG֏>NA{:j#PIN8+y ÂGVuªO~j mI:FgϞrӦM'lo7nǎYڼO\BjF*fnr{(_8kR(_Q_fQ ] ql/~#uG;c'QQ&G~R53Y{A\iyNHHI4rX]߷v&^jnY0QWuYTcg(]MۖN&.עثxEg]z>m[4aa)J'hQWs.Nf0gkZKF%UUX^M~l#fWQLip w(] e^Uzl꠸9KO%S9v`|n ,J'©עκd|)y۟PujQV? JWsm1cr(pև"BdJeP(}!pqv쬋g0 usq4UGN@RAZ&?~|`cVxb$Cä V'ƕ7it̪qNj5lQG5 J j `,i4ZMStՒrCT*Ymi굨Z6m(eDkf5Len߿v;v",c޼y#GÛ7oՉB\?Nۢ;.5$9$Ns7Fu xNZQRˎ8쬽UX_&[F/ݵk[NI4營]˭ȯsWaQ8j>XݺuP1(JMM]^줽[3To⨫SH=Ij.NdZ^lS匧QfoKSz~ z"s~Kn=3֮JnɊppzkvlQi z~Z*S3P-:;jv^5h׮cj7aXgR]Z7ݳ.Sk5/5!.P 3fFÎu8TՉ߶jz8\ulrgrl&0S$ w $ zzZD5(mT*u;;jƏfV\8vcg(]fA5!*􏆵C$ D!~8T7L[ \'NV cUrP#:֭c !ݯdu58Tv7m/Uti~U&*pۭi,y`8ShT[VSő;v6[툇M~DW>KYj}0'';TzlZ?䎝tbG!Bu0;w##^v{nqL@AA}_;Cr '.6kj^Ib4AIWrÂYy䎝t_2eA]OGaZYZ/h.Vջƽc>a;v (DiD7Ip_͆ƺrJq㉉!n+Mkܱ3|8̝;(?1 Kz䠼^eK  #e!Ly@Rjé Nʭ w gMI" ? >|Z3S w n t60~׿⤅!w N8i!nI q@JyЍY'⤅ w ,cNݖ8i!N;C2 R %NZrPLє-S D W=,rǂ     =[AA|AA.!Y'6ƏD}+  頨C@DƁv"z־e왩  lQ'ӧO mK$ZAAH (㛎;?_m ߿rAA`0P>UYd-|ʧ9!:   $-@ڵ-zxQGaj5b:   $KQAm1N7.xf7K.t  EU=z"b7){ZjE%  PT!@(roEAAa|R#ai  Bآ8 VXje8[ҙ +so|:#֭[Н  4q((KEncMFg&[Q֢k[X}cǎԂ BQT!|*ׯ/Q&m8}ҙ c>(u>f-۶mk8prANQix"7iC9^p ~С 3g/ϟa )SP B)P>F엉I&mh]tAJ_LQ(̱<餓 B^(pP> I&mID UX00>q>[A6ʧ*HqMB7iùH|At$ Wnst& B(pP>0S$rVGa\Lzg5&;IZNAH3(㙮]ZwQ&m'ְaAWFmpFq[k޽; 68/FiY czKv ԩ ifyF_M;kll+Aj-@~)D_ymRֽ /ZjEg&BfhL2 ,إ}AjG w2\'3› x1If0*I C Q|Bl0IꆴmǫqA-K!97(rXۣ_;G 87ô'O3!̚5naynYm=A!^ 6Od 0:g"ɸ .uCE3m3ٷ9W^tf d/vQt ~6m|,-ﶯAA )vM>j&iyinH;m&mҙ 5s4j6>v?0I?gVǎ~_^^o{,jUW]es ˰_Ϟ=%>`wE[ƒ֭[Gk@~[qњeu]LZ8(ᶎ&gƵz[k/a= N7s %M6" `5 X磧mz~:@x#A5Wy]Ts#'Vpo4\? kSj}AH﷟St3c<1MM|StP@sM)@:Us<`PύQӻ^S PKAĢ㫵z|q. >)?c!OU(38lcIP,6QK,hv.6\7 0}#HRf`E-Ip5zib b!1W b4ؓ2&pP>piYf&;TjO` vmEealjE'ť7hԎ骍iͶWy PZjeV4W40m i`}xk`8Ԁi]{)%ھ7)hRKpB(pP>itqx b ,dĔVO ,x'~e+vahs}aѭff&NvL2koQux:q P/rʧfv/Qj/)ɐB_f^}4E.VijI0#߼y3!.0*Q,\:jt0)PŃGq:cnSA:6]Pؼq|,sgˆ"8>x^G>N J9^xԅ}"qm5wJ3qoc?L>}zAm&s}Fמq\[ƅ5gFצN-|d}SkMk3֪PE8Aw<8E:!W9"/X3خBq6] 7ep8=W}]LI8(T0p@˧|(r 3mC4oM1~ͮVAK߾}֙m^΁i571ElMt) o̙cȇ"W7d`NO^UO4 ]v֐sgF0p\Wx޼qCsssթS' B)pP>bΝ$r xFycyvzAgS7ٴMM*nu<ƲfS;$z1:ZÆ ;  Jpz&k2C,JR 4*[FmaƘka^n:]m)Qr)BpP>u icULMtf 8~y1 NiڼTDejӈ#.KXr04N؆x఍Nswñ867༱tzN`pP>SՍG0D/&zZ'Cә YҚ50Ŵ]7ϴdH+oQšt6uglz:^<]ݦ捰j~:A³'viֹQ:D3.Ƴ&"U:iQw24$ T2|p'#Q?dzqƻ61BzE.@:! s0Ѕ{ꂚ&Y8UP ,cǎ>1\jO ׮qoCtf t:[Emkhށ㛶նm[Bށ0V N֯_(umQm/Zw4S@quqP |p\݂V>} Y.)8`M"d~Kd/ _Qtjk߭-jqڴitASx$8}ZMp.POܛɜ k1ոu=65//mv|nJw@A'F\֮]Kg&evy7 N![G 86T-5 Adt'gEn҆NG31yVĹm͚䣘1eɃIp n$﵉EfHܲN/ 䓂y h8 aaղ8FϮncM/N# {3A尙Z oM6QEs!mJ!RA/G8(\ W0I&mj u) 'd wkӯX0`!tVDKCzռb8@A! |reDn҆)sx:EgX#yp>vԌ1 g pP>ff@5 N'0>jbEi[P)aAgUV;  ;#O.m{Q&m8&:3AH?{˭Ip .vBd᭦jjS'mMfgtAzAcs Mо{֬Ytf)Pϝ[ {Q˗/kiMdp%YiLirqVA? ?O֭ov5ܤwGg `a^;bS<fq8>>Z:;r.ռs& :n?l&A3 SIY &өצ&C:q ; O;v=FI&m.coߞ, 1U !bytc8p>8VӫA Tq-;Z?yQt::!5Cؔ^juNUHÆ{uQA4wL8(`Æ K$r~w}ƨXOmZ=.9 1&q }0 tyۅTQaq>i P{1U=߮;=/F Bf)SA _&M QhaLu"? x5ߘqtAz SwZ<(؊?^iO瑃a $8ki8'QF2  |\m~  W#xsez1"ill˭Ipx}FC;~s3A»!OrI'Y|(l_ܑ Xjr56u>Da,y;s5,'Z3MA狛uxf6B Mʧ4h'3~21ѡC5]([m?iyt YXC0v|lFsb )CMGWoEgZ i{5sFne/,A%Oݳh"ՑG4fXiӦYh 0\hnƐ Ba%(GXm:sbbԎr m,EP b! Iĭ yA $-@[UaٳZ_jqj@!"A'=<$JhSG=h_ _(#Tva$ 'F̣i.#i!K,(f#4 ,E\i ,F $GQ!܆۹(/خ^,kTZDu00m>\-6״;}p1 BrUq(!} M:Y5y2mp@v-E "3}t[\ClQG[s̡|!KC@Al0]/vB,fphlIc' BN%a0P>B, ci"`Tq!RDPСCmQ/iq./v,$ih"ҶmQP&D>|ݙ(7>GG|#+>ZrOQj~ ЩS'kOJ82I^B]!+D&lQG1|V~hM+QZNl4Ml#?B ?)Bk *w1x`;Q<ǎK{ aj[Rj,{Ed󸵺{)Tdh;(^ٺu]1݂Iϴض~zJ-YfY= k+7ġ||/Zg\J1cu:>@_gѫǿf^:P]M޹w`K ew>o 8gͼqk__vl~6oޜhN߾}?ܫ%A R B5CA)?FOOT|%뼝V@VE/q,yq;>煥z %[{ӆ-FІrMSLZA2 Uq(!`(UVZm`Apօ}ٷ}9[(MvÏ[F9$jVG"FKQRLqw5yQdvul% ^,d4"A YGH9Ǐ:wLkуj30mh9AIZNȆ]oe>ڽkD\ YM$1N C@`Æ vhf[fQ%0۸s !-&~*M;u-?dٺ:x*VUxqƍ6mDkٓBuEQH? ְahMc0P>BFa6UU/xUB9/uv6d8/>~F7_@xA@04 V2/'L0UԪ`F]45%PAT03ʕ+iMQx߄2t`q̳E Sq1"ę*c΋t#UӚݹ$KoY]/_S^ufƒ_r؆0blW69/} 8AK.GM8(!X`D3XE+9pԼ jӾ@IPVGUA |(D-@cǎxYP߭[l-/v3l߲[HѢg4ZA!j8alݛj/.̼(l7e{;<6mMG Z(3mA"C{ q@88q-Z9בFd?:K~/qh"6 y]8vsVZ=_S(B&<3^Pz(oA9U05a ^C{vyo+ֻ h֡g%JXOs-7a0\*58mAX">6mZf7Cm[8k[s ~?ig<; 6Z%P8(!G?[fɪA0E\YE.`1K̢E2bs"` kXua 8ѷo_kʹ= 0m{K뀅5/ kF,@Qr~7Gvm!٬C)e NUɓAaCڵkG"nQe~랧wX-ras*LQrH6mEKOg^*H^j2"6/h %>ΛbIH/6ߨg8Sz!ӱ!QwPemM2&A4;` Ԗ-eQ}#я$cLj!̖vڷyhPP>B8qbթcyUŲ^۔9򬊦⦄zKOz ^;VeY[22<ܹ36`q}`]b`!@im;}4:/LqF=5|i?7Ίc623D4Ih5<i>ua8x-R[PQa#{f ,.3j!\s5RۗSVGP@87=A\BHw:{^.c ~(P>B0rH{)?{Xd5bZXMMM  o/nTG={}U8q޷!EUGXP4g^2djU1`4O jSi!-O" >0tj$85P5yq{]򓯤{,QT!|:@Ԡcǎ8B6eNCCZ®BT5yԂ oTa_'A5LS(|T^nWyq-_tA PÉleCj5҂ a2ޖX54 |MNOhj/"\-@ jV?iq# (4&dmpX\mљQ!)S^qYn2^㲭vw7jTF»51p_j-4v^gqYPZϓźV^_&Adʔ)ִih-:Z[Œ:R ҹ{&)!Ղ #~7AHH'G_~ݻSH!9д9.L{vMm^7u@tBMV;s~v;4HbW޳`ns[2꺞F|.|xY@i{آ8 PxbϞ=&t9}tZ j 'ihRhj] hb˴|݄ʀ* kUFz _Zd p祺flc~F;J83iph[-Ԗ=z£G BUf@&Zbܢz?>ZK58!jj: Qzh8|x `SGD?@I[V'^AhDqR\?R-76kN\5!EUG|uv^W8 jUtc;>Q jq1ޱ,Aj b,b~k- =4|`)wAu@A вRӐkL.bZZ||svb/ZUHꀠ/k׮҂ ԚCZVcl̨h<$5YC@5BmVPZv4[k[~ٚZkCXf>j]6im玾d߸/%S/eۗޱxߊuy>-Y-Z!-!> MOkf7&[v (#DS"j1 jNSaڱMHpI_!̥ '̫xQv?By ˢ[Ocak=ol5*A PWojזSq.JY߼]s;xq& m!n2~N5Zlx@34ꯕ PA9' "Qw)>1`H= 'Cc-kTu0 BqaB8ڵkG!o>, P#7Q³% O"Ta|:IP76#D>A6mhMGn_/}f˞-h(/&0?h|֪}Xk[ݤPLqF>u?â,~g)<|O 8f0ypA흢*#Ln55}請l'sT7м}ִi(VvtnI'XtH2ꭗ($'&xsL>ÂP͇M|uPYF :BD  P"Y2,' jcj,P["DO:/-[GD?>Q3ܛEچڄ'wP3`;lzfDw?jf3 dj JP8*kWN܇]4D4»7!|k>/uDzfs{͝׃Jn馊W:uVJy۟PGg׃Q />Lm۶P5F05ÆuhMZRx熃"D?[Ur.^IBP8^,޽{˨uv͛ך > $M&TZPaf ^07jO7Eęw=ST!|3m灡zWw:lF2P(8vc/S DM>LH1a{Gِ}Xя7G.vzfømI svҀ}<·NP>B'-j$5@畓N:+ؗPULd!AÇ Ɂ{]taQCSL> "Vֺ+IIP"%}Uq(!`lT8tĉ5@z,fhFQs*ʥ|M{ԇAHG5/fl]xFZsF|*#ڷ_N{W~afꥨVN5g^@^LuF|?h@kawDHi665M&8QT!|s`uwڃ_g|R(n~=z4e䧳a`3йLjÄxر=0H xݶ2JjLM>8nU-KQa]X˖%֠h.BTUXs'?3[:lؐ d_֪ehOZ 7a'N5U@!oTa%L@ 4D:4q0m3O&·"(1]al bnYy j5UwXG~*%?Џ܎Qk:HTV%ǞuQҩS'k}O;f;v,jmY5Z&v6D(Z (}ıq$tA #?ġU+),o*l! ŷGCԼ B1jPK/ ]?<HݛB2l0[n] 6Iҝ )[~' YC|XAE@iN>lkh:)>( PUE2DZ(^5 _އ5ꨂQq  jkn&LDoT,_hiQ:)щvQ(X-̄l >>PׯUɇAH|<|W|[DeJɮB|X}P!|eK t^v E fK >FP Cz˯]*[t5䥔nćEƂVWЃ]W>4Ya׋砃&wfyr &N5#>,Uq(! ,Hg ` eZG5#>,Uq(Xd4Ic{%Q =kTpJAAq8i/Ӛ3Nm⪍*玾G.1ê3jY5)(BӦM YM}kbC 7i4u ص`45yNaC@ЛS@Xҡi8maq REMxW+0淋q3uVsj\m֓hMt&®~kua: faWl{Xe 6*u~M[Do]K58,bաXHcɝ..88#ˆW-icf/k .Z N=6Qό^U$ANCHo>ۘP_rKHaeie x֊(ANi9kEyf4T}HQ4XMp.9/h5&y4vu(=3|HV5m8B3GDkCO3J-ۋYGj/7݇Q> muѷMh JӮ];#[Y>ݺo%Z8ȑ#i%jS_MyS_4F'M>/u`5#>,آ8 @>a;Zҥ ‘D1R&XFJEj EO@}ZEN;4ۇݵBD]b740H;1ٝv>Tg{-} ò-@MKNzLB-Icc#EUWGZӆ-.w+Oay76Tď7R>ARS,+MZikzazg :1 6x`gM(l#CW `&C1UhlN飤uj4UA će hPP>y"ޒ|k778;Қ;.~uQߝk 3^[m־ݕ){߳6=Z@hZFڔjHv=A'y+_5ֆ> n>lɶlmF,dΜ9w^C 4@sJ1тD ">,;آ8 'tq<:-: 0:b?ã8/=ުw6m4 wRYTЫ|ժUv"$ha3~zrmKN#jeKǺqqQLiGm@m=jŇZiaK^'^o@iF~nalona:W}Wk/h EZK73}Eò-@B:q6ӨiԣZfO+TYЇuh.;5?=Kw=s Ç%F16m"_S/>Le{7 ga>㋧$~3*pcuCyi 0t;|v73v guܽSڴa~CA$ zts/K"_Xw{kuJ"Фgik|: :D1ܔ 2BR#&xzaS^bb\#0&:-qS_aFaqրh0}l|c2fT ~C=kuNmST!|ZlYk{d29õ϶t۔AeUDϪh脗ٱY%hV/>kR"D"XOμwv+ȨQ;Iæ>1>ќc֬ra}Pa[D[_x=?Iח$IPa8O3vzċ~%1+OQ3h ݻ3}ZvKGjsc> ,^ Ejxɻ뱦,?篱Ϳߚ-0jQs5tXg>S>}3_.Sik?pGpB|XzEq`zgBuo`j _̀XW;oR^g^IH76TigJӬgncJsju-Zdy,iڑ^kC·S86]IVdMy ! }i"|جm+m9屿۵ѻРm߾:uSZ3Y+ʿ{NlQʧiUEx-`A}㖲&kxtZz/0vpZf +4AkbQ К ~i{oiLv57F2F-]m~72A| ".z!8O]ϥa(Po|b,M6kY3}UP'͋)T fuQ"[RM>0KVq밨/>"n֪m1wY}.no76b/q j4E{gnpޜ7Qәo"NA 7md k6il0 \tQKl0`yzϞ=qƕ* SLx՛5EXE/1=z=F޽vȘE5ӯ_?o߾V {~$ߦ\f|8tkhh&Nh eۼy3mzj=VgE\d Ϫ^P8:6TAxWY@ﰈ6w>zb_]+KsΘs{EX;,=sS ixVY elQʧ9s>G5AոxwKm41 ),xw^)" 7o & j.o!ڔ%}CM~zV:,uSҎRT!|?[eM}ZT?$:źâVmqt]1BɁ![5VH3ya,:ʶF_ad?3KcM}yv49q?NyI4Q>Uq(J˸@m=C 1s:kGiM0wb+ozA UâCţoj>uk|X'*4y"nƒ1um9%ݴƴTZgµ 3LZ_jZ¢ QߝK[ fmBهE.Ux.,H}]nA};Wn6nW;,ڇ9yq0Z`a꘵mogE6los갘[,IPg݇3(#($Q4{"PV;&jgZ 'xc-5,o3b\li 7f ZP{M;Po8uk;\`?q>f>LqTiE|X6Eq(A/$K&i0>tSy'{f^N[s_'Q(? '_x͞V[O4⥲0 8u}[D_wuV׮]HÎ]^.{9 j;ի}-i1yayhhPP>Pd`iףB\FgO#^m B0͇z{!fP#}AZ(:,77vϧ\t:i-^|5Zo|&Vmذaرc)SXͳ֯_oܹI0 NpK4 @Լ*ָ~,RpP>ս,*p^yװOޝΆ.0vKξVh}: ǚxj#48  a`~ۻ5:|E8ڴCc`#ˆ6q޽>LPxV1wNmXu#"mNYp|G4%Zhܻ.k1Jŕ-5! b@m^vCT8y{{>}h@0f;qӇ΅կTKߢ-8^}گ׮]kEٓF!B8lQGB+n^ؒ!FZ&#O=?hM<0/J?D=iym!ީS' u]t5ps&T:~}Xb0P>0({3h->$"njߟZyqL Vͫ )vPS"": BZ۴iCk΋;v"h?oPTaYiaܜCP>м;UԶƌ-km{kH$=QކK3 fQ`x\۽e.'n5Z,{?uBtnpvVUiKCB/Ňҩ=4w@d8^mw G f$@qj!=2!y"VHӎڃOiR+]CaYm[ߥ5AջtBk|ZK'ia;:=lpցօv&#xe"pB:I2x e$aEFZF׀Y:7XT!|Z>gÓlY0W-@Gt6*苃L5aqN|$CRߦP^WH{r8o i^5&$!`ԨQ0oQ$ućK ,#D >CA6~@6n BZ`nC[ogt9&> Y: diF>PIźI0(F5*8 uACP3%XP YGH '̳?i!TX]uոm@|FHC1 Ĩ*BVGW}8nxuZ$NA͠gMkIb1aC88P:dI5Ml'Ep/TN~p5A'UVlFYwU7JNbZq oSn$!e}wVl,.A->L0A88Pc?p/&6 @kBީKwm+OTnQQMAt8ߦ"uK -(h{M7y# Äj,#~xwPHL.+s~{>tU$@8J1 >LP>BYjm1DC($m;v9ÈΊ_LR8|lOκk׮aBH2oxvܾb!M;vDϡKJ/ƽGOA?3Ä(!YG0s}v(ĊvNzd/BW9VZҋiI+/>l B">L|ܫzrx0UH/w-l .oZ?kρҁΞ7QjaBҐ,#Dӛ{Aᜮp˄dYakI|yA~;`2U!->,P>BZ#O7`h^V~; /zB_L-8:! FTl!>A881"*Xޓqi1 *5qoK/'XEi鰈 Â!>,#d/Gx ֹ)9&-/e:6Pm ^(z^V/"ՄSO#>mϵfZ.bH2jrp; YSz&N.+ֽjC7/DO;g:sh͂Cg dّHǁ0aAx?idqp(!F*_'Pr׋? g/{3cEmRk"0MnLHo<3LE ?8O.>A|X&>>_@H?$C1 TKHWA| idqp(!26F1 Eć HbgRy &">L,A88P#Z=pA A$C5/]AE| ydqp(xbd .BV&B^ YGHvY5#ć 'H        u5AAdqp(AAAKHAAdqp(AAAKH򉕵kZ]v5AAAH$Cm$mkn)iAAta0P>ӫW/[D[j5jݺ5mAAtPT!|"cʔ)OjС-VO` 2AART!|1p@[H|Q<;Y  Bdآ8 /̙c3|(ٰs{Y;vAAvUq(O`ػVZYm>Qb٫MMM   Ԇ*SN:"x4 dav~  PKlQǑÇwqk[ӧO#  BUq(\$04q9AAA[)~{FCL‚qMB8J;~AA!YH֭]caqy: AAAH[;fqƱn׮}A  $EU>8MptY   *An҆iq.  $*f,ǽ"7i;mӥ  B,ebI%ZjAA!QlQd2x`~(rT{ Dɞ={($ eHkwڋ\0 BT`hN.]P  &c-ZȞ $p>jӦ Bxڶmk묳#h PUq(VZY _jINmժUtf Y~SM^[?юkhhT BM Ǧ~nҶy d渥#8Үff  4q((h_8OwMNÇә 3~ZiՆ_{[tуAꉢ*SMp 1h}g'NH{ @`ȑvI&mwչsg:3At:Ffs-)'A!Uq(`1Dn҆sAnAM4|I0{o߾=( 䕂|fM/HAҺukkIF.:J0rA-@Aw mI[#ϟOg&ʕ+;L9}Wla=k,: 8djIfqr 6so|(uŬ& dhPP>`|Q&m~S֠AAZ2l0_;|([m;QA,ST!|\AKdISN08?7tP: E <+MڮqoCtf e:ud 7NOb ˗ә YC@TIOmIetf sN7o6ECg% dhPP>UHnIm hlI:AM KEn6GYSL33ge2;zh:KA!Uq(`MI2 C 0IN8D֯_Og+ ~YgtQ&mҿ[{3 t$fb3-E5&:p 8/['EnPm s c!~04/Ͽ>_AHz>jA _1n\#G:.:JxM}kOI?AtP||]WJkȫG֗<̎SӸJDA/0t&}`͂-uL50 Aɗu3& cA24,"V Ԏ;Z|(rMZhHi5qnex*A&Ol{qFUߗ~oРAt BR@ 0 \!I$tLdrAxd$Ln_LWϟOW+ M ̐!C/t<(puBGh';[_!gy1j0css3] ( dF;8zT3g:3A3ny~u};w;  A׆ Œ%KVGa]xĩTCZm5DSutf M3vV~V.] qM '4F4L<njnq|r:3Aڵkm_`y6\ /_'4hL׋F UR{[M Lc o̫pȑ# qQxDŽ򉄮]Zfni/]Kv>[C3!`HLK̫C.ZApoAD4 \7>^CuFj P,Dɾtv32> ''2Pɸ=蠈m&oٓ] L +`/1M e."ܴi TPNAD m=(ru#цkZ64 da^QæoLF߿?/xM7v*S|ֱkاgP%AG[oƍGkяϕFN5զm04Ai{5k[f͢3! `||F~K~3~`LSkt8?!=D5\{UW\+u8Cqz!|Q#%= iy骉] 5,(^4|-|}wz 7aӏyQ˿5 887~)pP>3nc-{O!;{cFjK6+Lm_mʫv1Y'N; E6BԔNovN^rQP "B˾8&Z?guøO1Yx^=G،㸸^kVqO 8(XիjqhfH0̃EaN|Gktf !CXSdjh_mʫV6uԃy Q~O!fcٔa8 ڹF6^n 9oGp&Aalz:uYP#^7~)|bؽOF:5 肙'ymO}AH?xVMd'(6b8FBT_6M5D*N遚>ij@ zwW Ι!OnW~%`QԂC8(ؘVAH#?3N7PysQ_mj8mpVE") ApE*U'1t ΍)'sUb:GU,:5o5_y1H_ ZwN_ $O0kQz1 [E/<H 3j^M*צ4i3ﭺ&Xg u7Z`uSz7s6Xb$}aSXkq,U{x\Ԧ)N O5>b,~6u_vB9+8IV36mkLOgwEPy_ߑbPԎpwzRyoAFP|D u2,~m2On9h4j!OuA4PynYmnPIj1!pP>Ù!=:* #uC'Ʉ/]*8&H#ЖZOSNMzvm} Bm(#A$>kb:5NڴdEf#Я_?Itƣz#z~Z0tUlh" 8$&Z1\ݐ֭zeK/ mA< It iƐuqq"'?y41 B'LA|r8(MLnqͳ!;jM6tf rFi20vQCEqw\p}mv'Qvi?x&k2̘lNcQwJic $=LmN} MTEZ67z6v2(wYkСt41 D9 )#)>8kĈtf $M7d{qFf#{U3u8>FNcZ{{cv>B:ɳkBP e8OMM׫a|jNGa}uo xLqC0A-i3H#8Z|9!. g-:۞:"Ѥqخq>C5(ruCCS.E7?ӖA/ZL(Yjݎ$:M2jyli)mC11VHo]hqo D0S6ז jvY=nSjZ 70[Q NEyrNq`׀cse-ZJ) S1 \/}y4^ ORr[!wٚ9nQtmxS\6#}~ǝ`=܁Miz-( >f8bbԶ Uq Ta:,/ө8kA^n1 Q8(ϡFf9D1^ O Dg&B`h?(:M,vxM0T<}yS;l?AMWI8u24>I\x۩T4n}AVTWPK_5ѕT|M\IQOAJIWTLTD4'AEE]Y{=u5{Ϟ?{z^{f͚5k泟̳\2{b]6~wU޽M!QׯvQNgv:Xa#"檃rWN;գGs!d Nf@Z?)r:| z ^j> u׮]kzF RQ.C]+-3u0m?( u7ol!,Sa {r J_Q'h=?C'(/`DHpqNI^i;t-ӓbҾK|4 LJZޕ YƜBbd(0dm2 m.ËtB'` ,BG3Z p='yż9!HSU^ i"3b jaP0Þu{f {0{fEo=5P-G'}!їJ?C9!$^Jߵhv2 ̳"k {:ÆE7]eyNbϜ!-XwۮggO !;23Ê(Hm.C @`{5j9$M[/-zhyېuoF}&v[2!$^J߻hv2 F=LJ:En5oS(.d~fGbzFA;|):]&:d]۫2kntKzxE+Zm6d[3 څo!QEôyUdp)e׺>!dk@fxkyQbǬOb1~< ,0gd\?"l!>^l{+Z feƲء ^.qڂ1nt S]4L;kB(>/vаhzFH-9`;E$q m0NWܶ d ZO\3<Ӕv~Xep`o2*+D rkXm`Cc˂]Ǜ*&$>J߻hvrK"kYΔghcӦMg462KtL7\a8vxl1n):ބbR~Gô ΝmSzMBtm%~nLilRrg9E _|~`"x?կ_?sH# !0xiN58ijuMTI4"H%KtMWkbF|6 lC̴kj} !Ҙ NnX~$GQlͼxS% W):,A12vqYǛ3@!$0䊾}})r&>\=>7n!RHiWf^\j\%"MW%RJz4L;]w 4,ǧH.B#$\qҲjw.ta!&܁[v zۘaלF#PtC0x!7K[I_>L!t߈i'k_6݄4HϼKt ¸8cŢbJnŵetR +V2%RLJc|4L;Ezv zfq)E?\}}wN?ݬx@)ee敗 ):E$;]a"&AG&I&3@!h 0 {_sz>{~^9,Epi!E ic[P| Gٲ] ,qDyIAݛz;EuWGX8L⫃N,* !Pa=x+.eJ`~b ?55v>)4lDg5;g}\bVwPnA*):(i$C:ۦ=%hv r zۆ%Lr>÷\)<&i\ۓ6 %2^dú)5{ls!=#B1tPuW췷2d!) ~~o3IK^%erlk{5z_B!Ci܏ipC66<ϮKtV3 se&O{nlck1n:s!4?1c Nc Hx̰kx0[f`Ӯfg q rjJv?S}1gBHPgDôSHKȭ/+W4=#$۬YFf]e[I? ]8DZQBHQa)$k׮7H^~>n~iBARYE,Ktz qҨ5۳h10o<6J3Ċ3ƜB!D Naݻ:GC"]vRͦga(G #\D0~BVb]ۢ=Sb9~B= BiXl3tҦݶ,C vLȂ6^eqM"*Ә]{L(0 Q[.z! ^C:E Bi4Jhv ѣW9:x0`Y6R.^v|q =}<{Ӓx .2 !0x e!eALS:CI!q)7a)0Xv=$(uD<ו F>B5{A4L;gkmfE9-rHl'!ăjԱT| >'<):` UQfPhtyao!Ftoi!ߺM:)ta{|v-bK +e6R&Bx_j]lVKtbCGG.C;BH~ NCu]b7I3l> LO|^uB$ZLzT*/;Yw!ԅ$_~j!;oo8N1R&YfĉN:Eg0Wf{kqR!Jhv m^[xݶ:Ą;Kte+eGtPwx11FM T^e!j[IRjb\&a2 ̇2j+E>qs;v[̚GceWj6[9!tii@KDZ?_ׁ'zf-& ?Iy9 hG<@ڕWl,+m2o9ep# ikYuά7]umkk3gNBG> NC3i$;)?zjS <5Ϻo4.Xl{ %薐 [PSFnF!uO>q,{hOgyjjj2g#-`ixp*VϞ!mlw/ڡ,Hyvr)cߌxCºuJ(_idVZB^ FIҽ"Uxk~w}͖ഴ2|Y,:a}f.;BI+0ޛoHe69J {}]9ҜB!S)[a!%z0ܸq)ҭG{@twfP(ݐ_vӴN]ݶ;Eg 1WnKH]b.d~5z4SJ 4q$L;$&k Q<8Ͱ92܌nzeY+&r ,uSs$T^#SV0A6C\/Tr.2#FP{St.)A,>F%f#c!1G;AnFE #.Yd{C  -`!sf1, Ij7#P=vStՎ::= !y&#c!RԝrJy;lRSHMmEg5?pCⳈa =~Yr)%A(v/9GLtR;xmMy )#v3j$0gE1>?h 9" !#`!OSS&Sy#4b8Kow[HfL 4]M)HlxOHQ&UqL;{̲˕)ìtu岠쵗Y QͲe˴ܽSՐg{)CHA&UqL;8Uռ27@lîp#/EfTcQtS.8 9Ԅԗ*iTvW۱cۼ3$ ;X&›Q0뇁$ӒQf8%$kPPR_(iT^JSvEUCiۇ4z%$vx3 D(ی?\I )Ԅ#c!ըvws:&k5^ͨvϟA%W3+r#EEqL;$ 6qIT,%Z oF5jT#O .'^R( /eU ìYWT"ƳTog Hf^zia=Ws6M;u)"Ԅ-`!aki1_.'ÛQ1?(id\vFeN<---;\?KW8ma4*PgV%Т8 Z[[#Y1#ܹsP% 9Bzaʕ:JUqL;$#S-ZȬFEiKǍv;,gK*1Fש[i&id衎J-`!q^a/ ug݁7V;תprʷhZn6mڤc֒𹿢y~:CH#Cutu!BM ÇWG6kp_mI2{ˏ_Xi޾Nu{ʥhh`Jd?* ;.gZz&cQ3[iL衎N=0oʪ81\[|bG曵uG1`rG2^![P=Se]mxwYi4u?)-o8~-!L!tŋ+h+ jiCe_ory;j.}"諑w~:kPm!'cwhZI<ϸCB҅fR+eU i_"[\[Kּ;/Pcɒ%jĉf`UqL;$ iQoA m{NQL^3DmsϵO=1:6$ eU0Lȫw!#3O)m;_?of!!ـ3fZzY#$8eU0 JFQ;Prqj5{qdzkSY8T%)ba?y0 ջ^bOt;$$;C]*$)6eU8Ӓ'= *1Yԍ݁xvj1<.1!ق[N 2ĬR;eU;լE~O3f"EPc..Җ2{ݮA؇WPlָ)Fwx%: Oaׯ{챇~%tPΐhQHT%Eb?-W\&xҶ]mۂLr4wgѩ\GLqfQež{u0g,c>ӶHrAi4ٳՌ3!(ka!9Ŭ"tj{DԶhƲxqz8;Ⱥ4acƖڰmT1U2[lYo'ZAmG,BCiDQ4L;$GDl"^S jʲK=i_і-mu%+M6l2آYk{E U5!:#FPk֬1kti &5G%xu~.MhzY5zG_aҎ`_/mHrl.x\MPcK]O6-j%A l!-}(I#CueZ^!(ga!9nӦMf݁(*"UD.hu`[lA 0/H}Wi66!!ޫ j?OH!B$4ZGCrUnq݁"@ZeXֽb^q<.wۇJ$GPBH8Т8 Cw﮳ 4m|]m~1cզ{Tozz6\y\݁^A-jn.A dԵW`{Ka52lC?/$nʪ8CKϯTN\}@cw'h*;$$CfҤIzfWB⤬#`!9eРAjf-[|KjӃ7 מhI;n* :|v$lcLrFHܔUqL;$Ǥ}?jz?A͉a,-ڃB֬Z*8>sԄTcI-`!9fʔ)_~f-Y r7s foầLkBքc?iuOf@x'{mxguB ǰ ̱o߾fx)[a!92_=4&3|u͕w'x۞8qZ`Y u!}hr ~r<{;!EA|YL4L;$紵U+p}}޽sZx לn`,RNuظC{e!.A2cIg j} `BBdBzTY}^5 YQ!n.hSe E$8"m ,QV0!gtgX!:GZLp硆8ԲpٷV.]ʸCBrJ={޵A{PאݣȲZD01 j{_iSV01{lu=Bf˷LړR}C]D0xX'$dC]ޮhAm?V<|K[$Ȋ`FYGC .틏-S{ojV^? =pرڙ;!1fD9Ic[DkfkRV0퐂nݺ:<Ԉƃӈ;f 'c+Q_l֒9[ZZWJP jR>}3fƣ=Ըqb ú- a]ur@qN,a}O{P<ͩA3 )(|C';y P{sI` O]dq I%=Z^ڬ3Tͷ<׳BjM )(cƌQC5kEz; Y#m^"҈4֣GD!B':կ|y4zP+\(}Ԩ+K@#m{2ԃp^`=+$&R`-ZԐѻSWHs-b. {ڵ *νP\Z^u:S " lMAMr-&m֋w`ȑլQ^ش !HP 0v6S:ﰨ|uZ$:^AmOk֯AE;$w7`h={%BHHb PHs,djTbEyzUr3f->A5@=,SP\2`5qDV|CԐq40zCp⮚AdG iD98yJH~i GYGCFnkkSÇ7kQiEyYijԫ-"A@4  ;l'>Fj<*i4j}5kŦQiBj(cX5 $^#a!1bVk{˰ݮ#۽ʺͶ ՘:uӧY+Er},!lR1 e3k7k-C??=vni;WF 9[> Am{Q Z:qׯ7kš_hY !٥cX SxxOmy{wP{AqN%- i ":%FX:zIDATA\lyޝSc ) Ep?~Y- {[-n_jR;% iŲ-\B>Uxŋ-U +ASSS@Ѽ;Zab hm ;/?(HK}cɟOTJhvH";Mq(wBf-<&$GưqƩ˗dpM qk|O{{;qUPyWJ(vHJd1B9Ҭ"ywiBǰpdQXO%-7}^ Z}Q;辷+(zW7:xыWl춤} ˮc v>*iM>E`• &ęj^޽;QWZJ"!$>}_T[&rb?0%afwHY2}5#i^*Ϯ/.A-qWoQB5!$y C(vfWSnxƬG4O4L;$FDDv|/,WԲ $<ٻc_0pZqBOǰ={|5wWzS=#,,D 92]KPË"E(K[eԑ18瑼zwfϞNjjjҥfg:!ST^vngZy[nA>LNOCdx(hvq=z0k"ޝ(_%BHf5|pOEwf`3=kHQТ8 38rzE,cH'\uPu;I >lzv1!oyjag_o ^Mw nFF[ݱ˥.ō7$G'a?&]o_Hgn`7'!$=8f/"Q70O+D}rYwձ Oۓq鬻vjւkV|VAxhpsy;n$qgS/7sӞ_}w|u9,<{Z^zyB07'3Ƭ՟w`e3T~ITJI;EôCb;SbXA @`.]jwӁW[cTYMu^!hnRָùs皥h@LB:11,MZ?{aG+}ɝkM )*r4L;$FJEXAmc3O8oN)/<5?'^~]ߌCdmڴI F\)6jY#1VJcYhY_<:,%ǭboRdJ&RX鱩>!uw\"q~ff) =V;264E=<~J[ mT_Y"(vHA  ?ޤ5r/-2dyrرz^|N7y<Bdi$aY'c2>Aưp8 k|O{ᝎ |PV0xAbPOz^pEWW׿ngLSu:AH߬mw b I:Lm/i1iW7w,y׆W>^:Cy_EH˫[wc2r9&%I= r, UqL;쉎'2O=͖#dYL0ͿƄYV[ɘiRXaY&cXnR0u kZ4,2w 2y@ڂ붘lWm"ewvl׳8+Iuʪ8 YOsw! YeջShܸoaa Ͽb<(Iшk 2Y S ,aư$^iTD Z<ζv d+mLA];eUI'^xiv"&5{lߤ~^O tܘ0a/T>oòJǰ8eC1lOg~@A[` ^A-'GSyȥKH=eaݻw7K!cnxU-xܑΔ0O=J:j;yݪ}aVȒw`?"%5A4ǰ1 0U=tcرWƬҙҽ7#8ޙeJr%Vq׃6K gϞf-}ݩUÃcbk!*㎇L)!" cX; d֒e+-DÞ_Jd IRFôCb^ Y# dŻ3fj*޽{kT`c1L)!1,Kde = aư_b?6%c?d7I>0I]ușAec/l!UV;=z0Kn7*Ι7E^- !~~2R,aY" cy2eYKZ6A@CHCP |M x]&/\,xwmW5.7| x%$i2e,a k ?k Ch4B=i$EȺ^W77GJ]ֽvj*id%ޜG+m<\_ekCS Cǰ,MIcR4d =qaR؂؂E ^lalבW:$eU(']@ݬŏK<(,Y$$ E&1 b:4-d Z 1a Hr ص-ʰR.%]LցC laGSV0퐌 9S_.]ZHӻW Scć,NnSBHu4MZcH{')aď*i$ħS g(4>jQ;fuxzMݔFǰ46x`3nq뵘^fia"/ʪ8R0]ۏVm2{cR|&NgC;I|HsL C#aiP1 0)W!~J[ܤ1y3}2 aH}(vH~=[Yr)iqko8wgҤIjܹf- 7\NU0nHzƔcXDFV}+[;_Q;r=ԿnRn@B` RssYRp_JdW>& ǰSV0턢ނZ I$&@hjX/UJo;1hfSSY <3ސ ǰ5Zmײַ^:cuz7n-?0دxaŦ#`!HK~S{qW>Ixw8p@V9syy/ m$âcx]7+6p3o t 䖆,yať#`!!6Z5y}f-~~-QFaIxFJ-7^Jn*aR\mgl T^&& :RwO-we?BN\aNv-^}ה'kjcX118<hV*N;}b&M ͈>; q{,XsV\:b|GƆo$^8u*0 ^ikK?b$1 wm7՚%j1UqL;a&<_'vOIg1-yuMPtyoo7$ê1xdC4L80dTK{zH}y {]>yeܦI\cu5sG̓0J~m~x'ʺZV ʪ8@ !|_pY˽mf[| ȶŲmgaq !'›DA a(M#~FN89~ŝooh\ 3 և_]D]q[?4m.4[ zpaA2Ww z2#y0 >^?o$NϾ>Aɳp ZGyԘB$Ie

A>CwrEZh1'yTc?D}Ӱj(T}Y…^bʼn-+MBda8W, v j I@DuLv2Iuo+ԁC9~lxwHӃ.zFfTư"Ȫ=1̛oq~Xf1FܡԾi!̃1فXh1aQ/>xZv\8,v㾳(捙>gԱWUϲA7C1,@G´ ;Gh_Ao C3QekϟߑrSD55\؀1Oɟ:mY#~} ;-kf){ڜj5xEĉZ2!TMxWz)PBTPdfkzg5yCm1,UqL; OasOv6bڛ^鍛7HCbΜ9jѢEf} ÏJjbV1G% gG6_i1Lkz1쟺lMz+ ;? Sopnࡖe, xw A l-6EPa٦#`ix~2Oh-֗7(Aw_!7\5ƔVB; @HI]Q#Fۃ 2k=م7} ѵ#S"Ƴ///ws[P ϜZ%N0;fzԕOnl3k1b^ ;.-Hj1,@G´4=1Fs`pb3VbK ٞ={%7GVC 1kPqxbpi|/{¬/EDp!;DV)vgռt:_{|Yl5LfQ71S듯<[8mE`X8e*Ŭ3:Hv2+c}.x(.ϴx'vg9 aygbAHq)<" b n<~?Y?$a >DgW3饾oc'k-ϫg>S2}Ob\8.ǰlSacKv&ma'\Q9Fl>j[xM?vjӾz) O^SN5KAh+CC]W72L} \ƕ떭c.*C=g6EOR"Ǧ>^w$t k P)ǰi ^Ј-F!R!h XIiwCԓ6R_2N'oe{H-=A[Wh#[9_iXЉZX֋je@L^W0;x?7a3 bFhÛ"a?"h1L@۩-~ahSScjK_>b~CiL#wz=Ԉ>|;zԎtz}ϻ6t,ۤYt[rԱ.m#mJj v{:@ A*"ma)B:RfoElW7JN!}1^x1}飂L ɰ3 <,m"|;zTkkM_7.)6pegeV߿g' nԴѯRߩf,VқW^1_}kS|VwS@5B]~.u!"Uį-!zm,Xm޶ ),6Mu M@ u1"flc ]W)Ɍum2=Cc-fõ'N 4cƌ"ڦ_~ڟC}~l$ǯ"a"0NyE'Q,ooc?P; 79x<ަ,y}[~@3WxEKPm jW`X{ "S^IPcXv&Dj 4b j0m\ڵ]&k v-xv3JBAto6% &1ArXxL0A/ #5fTt 9oy%94B@떹zY;>m:bF%O/v_W+΢W~e5QTXe Z-W ^Amo!]cXv&O -XEDJ[i[BQP&۽(݈~Ŧğ'!S9Zdjsmj5w5"UPs2yȑ#UJ{ i"noܕW_zZ|Bpӝ[͢wI&1,@cΑ,Ehm}U1Ny|mկ?W3u~\|:l>MIOHLxPR>Fx1GV{UP7?WV<>|8'9WWrSR8eHv$oFA~ZȺB51,UqL; M=<2 jN,r 0[`E- %]%mI.~ŔPT;CN\>jo}۹}:ӊ ah1%|G9(9"n,AC>sgv?Vzk,SZ* jÌױ -`ihp3zsr.] aHA,K= j,ʕ+L0|iQ o4A@_q_._6Y#BcX{wKo$ؔ3S;{;;ՃmEAZYy +c֔UqL; ~1.{?^)˶dYȫxɻ;Ǜm+VfJCO9s,ts뜚BGH})'6 Iai2tUYl̻Q?kZ]|ݝO?ש ,r(cXvѢ8 掇ԙ30k#SY@u!2"~%~s~O?3CTC`G!Jj])*S1[WfS#?tYL-(1dO}ڹ Y{j~dE"1 ټLx4w" dڳ'"mH<_ֽig7lA9v1b dA<7Iw@"4&wK]mpCO~9ɹ &(fe CJD6k֬1K'1̖s~B.2 bYqeن}=Sz0YAͦ"S_}Q k?8T<W4k$ } c2E?ET_foj(1o2¹;bcMn;-C~$,jY>(w4L; 5\ t7'~ÔV~Pv֠Wf-}u$= FǰC@ "̢v)O.P6,iaR$u=0H:[y%C-5/(L}DôCJMꠟ'H^rH#R̵?%Fo.IbҖzsv?3ñS1,M a/̢xov 2>Opfq͢X1Swox>"cdqxL;PJ]KL9CTG y!lzQ yFpE=cH5LJFӢQf6Y4x!qCĻHz ;Zװ(ja#`!9MuYK[< j$-Rn6?pSfK0;Nvr/m^lH蝮zaY&LߗX% ፇgo8`rza$+8/v^iѶ0s?--mqЎ}̼Qz0#[;U Q t@Bh4fOc [3Iy3λy~8D=yZ{!Z?>7ð "cWP)ȅp".p j8R.mQP_ Az[lǛ67߿gRh\i!HӨcܱO뭮΢XK:V K1h$OQ3F݄ #je{ FܓDuo:6l:ӜiyAdW#G5ǰ|cdqxL;$֞lwn y#g:~0[Y37s9s[W5òO W ^Ttq[7S 3~=wbPm ˛:Kc]8(i7IZPsVk3f:a[~b[oUY#IR1,/W'?E6-e̦8}tpp:naߜ2y!eb6"*º(hvHK'"a "+ j?/uzeGIm3 HgQwp|8GSSrYKaoٲ4U"]@P 4㍀Q0*+C-״5<<dS-T?8U摤ư^SB@1,3f AL˲rغ_!l#{ABS)<aVR1 ;KbP5:LGôCs_yMG9FJO^ǰzy/!b}tk u?!.m2yA9+6sX[P˗s窩S`D DQ06,iԁo\}ߔdx3M`fLx{x.~=aiLlQ s=p( ص{ @ _Y5A5]5kh/u-;p #.,iԉ_ySqQSMY̘iRe?>sh5?e F ʼlz0vhmn׼, {ZP5Pp #6FǴC!g^ٿOd|$]}NMx::l!BǰM'f[J6XPf2-Ǻ~NZ7(Wuj1x18<W-~DxUS>^K-Fw|=7G8dq [f);@ڢVDUzK=GƻSA ֮]k$F\YI7YH+&OYd5K+S޹6C˾+Ƶ ԩzR[?`)$F*adqxL;$edFrDR @<!Cx4iaYA"`aϘ(|Ӳ:glG춄y}-455ia]8jY 33E% S?nU?lJjy_3N?Ul'1 wd 6(i؈[M1m:6וj ssŮ;Eu޽R48Y+Z)`*q?ޤ?=;,8\}aRUR1lW%W Sm޼ٔDc#c!?,¢1% WT!(ǰz΀H?fΜ(ja$ FǴC2 6Ej*  ^~}]s6Yx( \ˎ7+0 Oń qgjc1퐌Ɔw|zy}vKׯfP=jA|")6qagia]<F⠬#`!9ipSZYn%4Ln9ՕKLIYڣ!cJI:1Y;wY 0'FǴCr=xɲǶLC[ Lp괅sNVjZM f c4HY)ȩ)H꿨Hc8VyP;5sM4Aǰ!ɍ(B 0BH08<3^C߀x#" a`dqxL;$rX)!da`dqxL;$oH1R,iԙ/t|Z[f+!da"adqxL;4lE o@\1R$,&B!B!B!B!B!B!B!B!B!BB!B!BHaaA!B!B!0n0 B!B!`7qz~כ%B!B!B!~7qz~8njvm֬Yf+!B!B!I&cѢEo߾}g7OU{|v]6~xSB!B!BS#󴷷quDIwn[5~wk /Q}VvW :Դ@!B!B!F;#,]T_;a{~~7xiNFޯ_~jͦUB!B!B!>T16mR&LPݺuӎ]QcZwd:M>inG: B!B!BH$NӏXrw}ѷD96ûkWzjsdB!B!Bil#Nӏ(閖ս{Ӹ6j;qujs7B!B!Ҹh'q~$ ð50HNҐ*d'9!B!B!42G`B©S8nlq:m_tFezL!B!B!|ĩb65t4"9Y08O&B!B!F>T1Ō3TSSSSrgQ١ޫW/B!B!B S#k׮U#FpHS6,΃!6KnԚ5k;%B!B!q~2gaKNgo^+R]lҥK;'B!B!bq~tn:5zt9; ( fE=#u !B!B!SX`ӧOSz]"{|v}ƍ/!B!B!dVɴC\/}U7o6B!B!Bv :1w\ݶöSK=#B!B!ibV^vw^2mD[<4}NpnVZe!B!B!$N -?GNm#Zr9s昳E!M,YԌ3B!R$Nӏ#yiܑCF^v̎L8ќ-B!l1uTWvCa#FPk֬1!B!LB~lСC췷aۨϞeȑLB!dcj{EWuՀzfϞm"B!42bdܸqG̞MmXraۈCe}5gB!$]9ۦ=vçt}بQԺuLKB!F ]L?|ABTtԺ[';hgP}^qƍlB!ԗM6>}h]r?s:+٥S{ϟoZ'B!t1Ȳe]Qݜ-B!d#}㤥Nr6o鈮F]M!BH)t1&,mD$_&}^0>!BH477k{So=˙\Uʹa i!B!f0;v}F췷>/IB!$NFQvu8-CtFt#HwB!lSb#䳻\B!$*7oVv:d%j]vUVwC!B%͞.?mmU;h>R̬ !B€MM4b'<β]j7/hҤIN!BINOӏH^ZuUqNm# 3B!B[[[ƺNpǜzkF2djmm5B!RoJ<]L?"DĠIDhm7r9s昳E!REiݶ۫[t9 >a={TӧOgt5!B!u#c_~)t6!?7t` B!JL2iWu˥+ݢm)LvqgaÇQB!(it1CooöQ{3B!3f }?ӑ(6[_ pϞ=ۜ%B!BH\v~/kڰ2ömy0`_%BH' ut6!#Pw>?#Gr"jB!Bb#f̘@|jFs "B!ͦMT>'vIKb5W}͝;לMB!BH-4u~$Ʋe]Q״f'BH>4iiWu˥+NZ#<6c s !B%-.aذaZ^NmXdhb:*3ڈbw} O!l3zt)|ԤîhߑzٲeB!/Jz6]L?2¿6 K.s:lLj#6ԣtm|moi;q;Gn|B&;Ԥ~Ku֭ZfB!䏒Mӏ1k,-?}vNmf^SڎU/]tt={Թ ! 6mڤz ;Ԥp}q{ꥯ;!B!ym#QItkmԃWteHc)28DZꄵ[~snk׮՜-B!ڵku$-gtjOR?^vաφ|z RB!"PҷbY|Qƕ <оX\Qv;/VϞh{lB!E---R}QiL I {]O_uu嗫:c༡x|v.BSB!(%b dҡ#alu\dDLK#0쮏1zhs!42sۦ=tl&iF7`ftu|6jmO44`qg[ES#pAΙ3Ǭ\$c۟:}ijBH\ƒt1 p¢y6abCLvaXw j–`IDO{!B!3l0};i"e^4 κѹIozjs /~{NW8ъWʎp­zў_d-ّ^>Igٱ\; }:_>j?~9* h68=kv?H^^+ >G6A%W+2?{C)q ]L?rYHoKZ͛&"m]:wD#t(QB͛7~tjf==bȱt L]:#G|?.v‰ uI iN/~ZN-/ g׷۱}21LZ\>}g3\ #ڒjO5u9y6V!z?8}q>v񧒽-Վ%{<ʱ(6>i~ !PG#~a+_n3][ƪomhZ6∴{Ǚ ˩fM\1);x8A+|yŸS4.Ư\sVG2RW/d6m6Rr&ǁv%M8Sq|5 ^1"*r=q>]&6Oԩ-,>" ZqXcdߣcɟa !$ߔbKZ[[#xM: cp.[O@Tl՞(kX)@ˎVBH@zqOFrCZD:a=y'TDٹ'LuV6mBB8`6~8*Si~N0>~1cװ [ؑA#k\a\xM'J}3VXZUF!46GnA4SϞ= {?t:lψ#yGt՜08~qw"纮dk]>ݽW{ƌlB!V-L \Nͨ&z9a ][wLIHV6~傟LA/$\crQk@}{Ao$b&aιq9BόZ޷&L[W g%.pNAt, WwJeǸ/!xƅt15v>1928]Q(6>Iٛ=>[ hB!ҢNf(mo3 qGpVyUw>dzf2Wl N&_h uHm#e7/M 7cy/.gvu?87e_DORfGcs}ackvz\Ƕϛ\x+E)M.LEzZΗ|] B=l?A?ڱmk"iG>h_ʢDBI黟.`z0=_t:l2DV^CtQA :t9SBƨQs>_v:5e]mk '<ǦjM}Nc\,DUc]xxpyI !}$]L? Ä \te^4&U{ø c߾}9!Ro|Ԍ09""kF٥W' Ct5Y&sɥ DC# C8 vE&M&RJt1(x4o 9對jvni8)]&4=tnB!tfӦMWa'9Ql*ϴICj_!V6\_޽{N!BHRbQ8/_tto/(tN{sXnT~Dk׮jlB!d͚5:_S3Y,v"OY08%mp8cmp k{܆G:%;pCu)O!BHSbQHfSo| ¢8/NG[%z쉪vc̝;ל-B!qNfXVp@ .5sկ$ <~Y7zhs !BilJ8]L? ģxghaV(纆!Ud\(iDP:Y˖s!cƌ~}Oyu:5Ú=!]urKNa,lDLÉnoG?Q.ujq'mN~M4\}B!BHI#G4#*NeKךm~҄ kgpR:\R9RJM~4xob@ö5'J'T68֭Zf9[BHqX~ѣߝv9NfĒjp,G f/$:I;u? $,\Pq1Db尔hTl;G5^D=WYdϯsc>x o9vvoǠRk^G#)c r-\f_7Z#@[ Peh 1pJTzQÙgٱ_}/藼o{1؟'Ͼ~rn>3I!qQ[#xI';I~%VYk^qeҥK"Bի;S~qөQb4%4/?2/ޛkzـ>|8yc Swcvb?Ppz pN3 ęu}f;/m#jJ཈#ΛMrTc]9О8ҞɹAaϣO3π8iwx^υ8see@ g/_1RN!qPS!xaI#۸ QHcy QvuQlէSL>ݜ-B!$̝;W0Q ;0pE N]o1"m8:q#h 8]Nx/nD7ǝ0a.y8,\vNv āe˲O-H[~Eۑů܏j}j9@ڵGsu <\^'rP8߃> 5q }V~1+`$]L?<ٿ=>d617Jڕڎ3ۻ]N\ծ:QmÒ-}ܸqlB!cĉ~λ[.]tlF1Tv9sc!Mw??7i;"s bppʛ}㤥?3{ls 70!ul'VWq!u f;H/~~Tc/8\%e>Ήgowy:6ķP _"H yA]SN!22?G"8('bPE6aD 3rM؆jkD8]e>ΐ!C̙"Bȑ#}l>_v:5k@Ւ]8p(k5Yql8uM'H*Rq\ڑhhۋvک.`C"UExKj} sz ^qm0<*݋vx~s]~r]\]۪yo~MlBHƓt1 %((N "\jӦM@!BNbGCqj`MaaCgqg^xi]vUV2gBk֬Qݺu_S3m߳Dגckaj3Nuo$uP"K"}m4\}B!BHJ:]L?<"GEqf6lFu52~R~Ɲ U}\BK.'"yөe?9 G_ HfԁS03ރˡ2}ۊ;R3\}B!BHXJ:]L?<*GFqƏalF;Q-l׈c"Fg;q8կ-D}vr'E!}i=Լ:q~Lj%s Jv?N;۞2eB!(u~ Q0 kbpHגuu_xal=?9r9SBH9Sn}mv:6Ú='Luց!B}]y(mރ8mCdhpنcmDުv{E'B!DTt}jÒ˜8 Ne;5vR#U't}B7C _tjF)* ,چ8#i;¦@[^n?:Cy0'B!AIk %)3;uNv:l%#ˮ:m: c;a&n!7oHuws:5Z)*슮59!Ydȗm;qgv3!BIN!c } }M2X?3{Q.8uG}T-[LtЖ9>~Gtls=H~~\~#:N;q [mq]`_I^!RW 5#8 cpR%^=a^-hl;:۶m>a H~_tcǎ5gB ĉ}eםwS\ kv cV ?&_ Ngoj;a 9Iwt۳g6WFp+1 q ͦCZa_U蟍v?>ʱ r }{x}Pn#d}Юg#q3\mB*V~SaFbpZPmG&bud{o6gB#Gɗ}өŐZ&054~pfIlqp,gigݠlErJs !:TSV?ġjG1CLhǹ72R{@c[^DamJ߼ f#eeqE~>x+'BJ龕.$"&L"d\< kpO=(pcU(i8۪9A-uDqܑCt}Q6m2gB DpS3!bڨц_t5҄I48~\yю8aqFOK7&$2vʈjTs ZuWwێ6ԄBL龕.$(*NiOn̻鰍m/s_l:aˑoI!$(롩.jtjF1; \8I]uk58r]-mqy'|LF9&EtzÎ:]MT^$/YʒOYPhFԳ6p r\"'ҷZg-ci'R4;!%Jt1 1GRqZa 6!¹Rղ lmWfBD[[֭gL; kִRqD{Ӯz~ur#z:u>붙* Yql8apꢞa*m~XPA-Ǖ~NhiSځ-oErM9L)Am9OB!YtOJ#޽3yaƼ' ǯqOXآm '>"bɒ%>\W4w:5rOYg7qF?G1ʄ qڄB&{w~#xTx:a vJ9ż!ːsM;477E!(5uj9bw=Լ:a rL#F3 9.tbRi:h8Gj;X愐bA5!?Jt1 GVqͯ8aNQ-:#F3E!A- i;Q YoF[~VLjl{Ĩ\yjmF0%Y}ɗ 8B!BAIIylyOwWnt؆1LvapXd.s{SSjoo7gBH#`:;9qrτ!zU/ٓ55R"Q֎? .B!dVORd⧮]Qa淌Uÿ5 >`7Btʈ*Bi0p=cs:50o.fӈNm}^ d!<#/S39a #G,p#:IC.&ծ}`v9w kNtfV2WB!eJ>]L?HHDvVo.t6]}^z6md)-#ЇOR7Lc6ohcx !߿i@ڍNfXf ,)-`INs3bȱ嵤A bbKLI!B%.$e$'gUm78h3y>/ݻw]_o|Cw//!eq Q : !>s.N(娶SZ?࠭ 8F&&Ϯ#5 ׎:>}?%!B!d+Wvpg8h8r^/_nV-e8 NjY:]LyFt\Ga JՎK4mmm:c9qv$팕Y;8ngG88DZ~uHsTKR}o;ds !B!ydD X\?GNm#ښy^Yfՠk+eq_q K ˱]k'v!fѢE'Tmtj&ep&'pc8]u2V28ř gsZiT))b>!B!$o4}~ |xDgܑCF4㳻2as|mmD%KıwAu۩in\^-6!$L)Ewqg5oNf= \jW$](¹lFl G hǵ51On>!B!$t}~ 2x`F>/Ç7gv8Qv9%V'7:9{ 9v% !g̘1'Կu9648"0^DZip u>ЈFd!g5.]j>!B!$}~2vXp6,mD}ׯ&c引^A l]G"ms3f;rRfcׁ14!cРA't>bS3יuWz@G_vNi,$a'cvMY\}B!BH)it1 fԩ৻:mD={vs!;-Ց9 kp"1DG1D#Gy *n;Dy⦦&qF B!䝒Oq,YvZuկF[~sbtZ[["R0o8cs:5+qE ˼i?nOXϾp}}\}B!BHQ(it1 9M?Rv'8hgOԎ{ E!$I/_]إs:548b18l8jsZڀ#U'.C3~rnf^G=ڪg/>ȑ#'B!Oҝ{0ö OvLqb!$={o? t:54D>ۑbAIo#ٛ>2q8'>t-P>ĉ'B!O3 0:xaۈI$2zhs!Ʉ 8 %.fXUkpV:qm'oy- ~g{_vՋj@s5WB!RDJ?]L?H_߻aۨ3E"1oF*N?7eFi/!FS3QQ&N[iK N`ۉtqS]Ivt W6v1ի'B!OSzsTö W^jӦMlP#~S@I͛7~q幜Qv9DWK08뙿9! ǴW΍_t5Gؼ~.q=zכO!B!Ȕ~1s?&mjmDc[7vZs2~Mb6X{:\#H]A9RxrP6_)1}l\&$V0AϞ=K_O8 kpJTsDZ"nl Ni;[ IE1 B!4bArʕ+w^2mDo/;~/[̜öWX3ŵ ~RA?'{$)N֎{'_tj5$ER? "]娆t%4 q;ij>!B!Q(HR֭[eNm#ښyOw/O4c sRcUDz+*ZX@;.Ǯvdrd틾#!$0-*}>lEGq:lѐsM;2~xsR@pr*Z?'2Z:8!$v&MT}Bj{8o@]D]V}Ʈdô v?SB!bA 췷a 눞5JG8hNj#::vkD}&<.F"e6aOѣK_rj D׺Id0D]WSicEhoѧIut<XB!T(.HR@Ǝx~_Ԇ%9EUWZ/v8zfϞm!J 8PGrja~nGG#lC$F!䄇liDx͚5B!Bt1 eG(:ͳ~?%=b&شiݻC:Nf \t^v`#tգT}l8ZU?hU'}v1!B!ؔ~+i6nܨTLrgnlQG5WX=ԤI%--Yb !$[̚5Kw;NMZ&mf̆sl;gvKW]wM\}B!BBB~brNˮ0Z}ixyժU9ӕqGyBH?~gwewt96i[ 60)ܟy| Su3ٮ vQm'/Ѱ`s !B!3 bA#Gyvjunl)H=i2CeENoBH6lskN&ߐخzԇQ(Ci v9n׮]ի'B!)vHҀL8Qx.;7Ou:[~s㳻t G48ˑ# 2һ^vkThiG: 5Hԯ_?=:hөI fk&cO!B!)~HҠ̙3GݶN(jaF$-`1b>zhSRGz$ҥѳf)5cRJMP^ON[M]O+r_OR^sK7RO@}8mA݆`vrlʋIowDpVb=3NMZfG@cَaqNX?}Ly!$'PB)*bAyœOs:k1>w0۷Z`@@}Nӷ8Kԩf/Tv"xE8mlw9U.sq j-'QGO~ù+xP#m :Qz߮.蠎 J`b~-v,. ͝;״+W61iڵkMiL*5xpYݷ#o^G2(Wہ›Aۤ:2FD*R}Bj{MZfaRDW v?g!=!X#~O! 2D=p:ҘDrݘpݺufxAѽl2S8ңgϲ6^Z^:eF`&)5 j]@i_]{i6:#Q金 QFB.&-Y5qAIyM}HJB!N!4 bAH'N9Wv]q1em=zϮhDLw튄ܦ`"I HHolv+M-GtjgvDVꄵ_n"OBIL,gSV4!Rm.lÇWmpI*ՄC6hPqAcQɤ?d⶛u{}oJHzz';:t )1N9!t" ׁ0,B!iq~iƎf RYv֭R'SSGHшJɚ5kt$-IDbؐo|__gDB/qk0B !OT#ڶZΔq~@"q;G.K_tjҊa{֣G6WBH=S1@BHN41 ~sNٱZXV}6}K k֘4q8I'/3f;|J]N&-v˥+Ԯ;羚T1 >~R;X}חK#[_B}N͛MEBO?HqXnNеkW wГ!.>J}Mqm[[['`Bv!20FErl &<ٳl֬r9rpwjo/7Q>μyt#R9s޽{rt~MM\];y,ړB j0B!E>T1 $:e>}bؔ)f8Ͷ:3ך/#kת#F? u۴NQZ6׫_~ "@ F!G*DH!4O暶߿lSa-u`AstJ]m$c &Uljj* me_\5B!YBHQ8UL?Dc%!F<<lXSCkK[Z̆hi8 0qD⠭M :4앝;N+t n},!T#RT#NBCQNQn =ztA" 9&$:uQC! `p}b3͛|N>{lsU!d j0B!E>T1 $>w^25r)a͛};Ǘl6>J%IիWaӮjq:Wi Xv٦>˗/7WBH#RT#NBAN\!:ٰJmdXHi8O?140qDɦ)z7NÕ3Yݻu֙3N!$PB)*!3eJa GGCGbv[֮57qDdʕj0vew]ta'קtßB5!q~R_z.; YuXS;9 v0>>M jss֭[iNUq:)K+ہנA̙$!$NB ~kG+f*Vq"Dsde˖rtu NmT۫ϗ3f9kB5!q~R_*9mC4u9Jm|vsif!?HhooWƍS]v- Pm:c6KW&q.!B!BHQN41 ,vرsP{ٴI}vOfRƙB 'g>뜜~Yσ׍O!$#Ae')E}&BFx!ږ,!GmYq: F?555bСqXsi۬"_*Ǐ\NK!> "ڷo/QۉZ{!Am]m%OprDDQQQ) su(KuUB HX֥KبZ !Nd-j-/=@?Sq-auu}qNw#~DWc_EmرjԄB}0ZCO>Bbx!M~ߗOZ  Zf[[V=$ >\ u<ѱcGoYY!B?+VHdҤIB#r5BQy]v7vDG!R̀~zqL̰rؿ|{"5V9\BHFȄ ORXXZ!$q"oQ 8БxFR-F$GՎ2ǒg2n4@Ax?:,//5%),d%QŇ!$wFưadZ(#TkEbaȑR|XM`N j3 ZZɑ߁<~x)cHo 9m"t4<L!ÈݻɁˆ*qB4tM.uhxc ?A}^;;q]&zCnؚV &Fp{gAxJQ,>N^Pݫ܇>/".^}qFG? a/yLy<LWVl0/~{}qF7@|x~<^ rM1Ŝ7g;'ϨwxC?Nv] ҦBrFP/)))~T'\WEԩt,lSZZ\)<M +p&Z`xn@k׫3&ɾ~jfks/"wH4 FD4O!/-me2*8gHuӶkı}ĕKW+!%XJkZQ?VBmAMbr.k&R$5BH|()-0xN7 6)ʚcpα6.Pl;Im>Fa܁h\{ؿ!vkbW"On(WL, BfCB! #=ZAQ?BF^AI!CH3Of!z´j~z?SQȦ lm>7y<@?|- 1=@ Ry>x-hZ9n``_](?JQ9m"tpDd#bOr2H\Bra$ 0@o^ԨBqfC8!)j|Qh:kS`y#w¹KR^?gqzDV1:CZ6A'ĵMY Z\B0=b[nk׮QBHK8!)\*!75rT 9>?ltnyy;HL2E^Bi~CO>B2Dr{vX@dFx F(:$C>u2(!C&^>\uH!\~4vKb UbQ _"JHf`䎿A6R|Wxt"n ;ʼn3j+y\BH[臑Ld9*6BR$5B aj.GK,DE犗ZH$aNpxع,j56LzO滶n2;QyBC?d &ȹ$BH6"qB\ұ1bj ("~FuW?H95Ӷˢ}&nFDK#j:\:iS{cĉ|T-s76^B!~Ci=29qB\fԨQRTX5WKqEh>M<Bmc Anm3B;k:4 }`sL89O0r'Q\N9YC 5+\ZD6Ѣu&T}w-B!$yիرS-]"s7oQ d K+ ƚmPr8;)\xMmm{h5&=95~ܙqz-+V0Y;)foZDќc3-m7+Kz_[/USNU-amx +))Q-BhC_3b)tۄoAomxs`m~=~ !#[׋Ν;=zx:_$\[8!X(U1S46AbEbtv5j-.;Elq-گ5rou*B3ql^!;uEeLAhfN| Bxj8Sh·z|݄B#TWWvډB\[8!D;)VVVZ_MsOu m6m>`y>)XΉ68 x~S1ta:R Z0 jufZy<h`c3z<1mՉyԞ°6?h|xms;rW;lWeE䣞F1X/$z͞#Q@ w l6-:j%@G;&@hX84>h@M!$]tӘ1cT !xK-j [:u$;N!SP8C5>S>-D:7MAcOD6cy.kC9:5)E6NMKIqMr#a5Ђi&Z6#u6ଣ|MvsQ&܄$O.}X#.y!$KzcǎU-$O*;QM)cZ`cB)Z &68kYIy5;35i JC" !lj*Wj !$R$5BH2dtLTH%rb")1Z"k,sLmhom 8F)Pks`}+**d!:$BR$/ڷoY]"BEJ!j,3~x)RS?t咸V\U&.\#&.Ylx}87{87qfEsl:q-rB7"9\A!#I2`ZnD׮]Eccj%!Eb/Q x%K`VXSG7ƭ ՓĹy3/P~[V7h:H; vF2i$yaCB!$}AMVtAWB?"qB3m!*# 7[ ":"Mr\Fn;|0CeذaR:ס.N^|,dH!$臑D(//ÇB/R$5B_,**R3#.n{]_ojd'&Ed) /-wf6 Ue2¸aI>}kr.X@^㼆5!tFWN:UBF)jѹ #sw}ϾzkF#&6rBC`H\q " F~.]d-!_\%ܯ_?@m;ǝwީƶQ&6iS6qqy.öهBH8`55#B]-u[8!>՝R0D>#b0Rm/,8oyMhj<8 CpQY!>[c@Ls¦ BM3;a1mm3zqNsB#I4 "z0u#!uD2ޢAFBGja 7bqܻ߰ ڙ)K#7&2I /#wv-bR:z6 3[ߪjGE>< c45ǎpow1bՒNX :":@my ؇mSshQ\?B_ Ԅ^AMlՋI3zq= @(`&Ϭ:$ 8ާs2a j;f83?ZKNO,j|z&i)Zk>"Em-' jp mƎ:Ǎ㽶L0k,y*E3A<8ρdjxo;[1ksF\~Sƹ(PBH8a51tϞ=eF\~Tv^?!Yp ǶcvSP_lhZq>;df"oQ b)z+rf0DaCFA^H+!)PCE3_h >N0lm>9DjG?iv ƌ#u!6B!jA*vډ&;pQ KG 0M9@ p^|-^:R$5BONeee73k_l tuy ~6[-j1Y1[<6]kgρac Np[ 9&gAksB!ف 0scǪv9)Jk#!X f$31a7±z2R$5BAΝ;K(??_\]$NFleu!R ~ h({uH!dFPl.T aDkpqgVx|I:(8+wBtZAcǎ2!!B #S"75V|5D)>\ mWj/\/XOtU (PKJ!j0tPEsBWkK;׈ ţenOKMzs{4'#:0r'w7p2dj-PxY̐B&Òiڿ ?l#F; )0З6*qBĄ HݣGVQXB~s%! N8Qm5CBKDAs]JCEB䷎Xiد(}"Eb/Q %KHgsF&M ZpFx'@<8}?XJJJT !0C?,>:B؏jhiDMWP3DhX8}JqZnLr|[8!d׮]r?2FÆ rbh±-m$jNw>9wY}J +l;F܏Id~-jR[[+׹Pȝܡw޾uSueZTϛZc%dk0=xׄBCMn}nkqZٜͶᴐv$|)NZƏ {~q1vCٙQmSu0hZ_,s$#B 6nZ0ׂ)@㋊T ]Y󤌒jwham!>;ADfEcSدi qk&PN-j0`H >\2t #Gڵ?(m"քBīɿZ6&zkQ&p2DaLN9}mV9K!*Io;j-e`DdjE}(PGG^A GI>}T #/;{SklkJ%/"*"maDjm)84n o~ m"qBBM7$.@>ANf͚%yyyB!~#,~)xkNl"[Ĭ a5 /Zg<^F+VU(++2=Pjg4)8}&s5h}t!X-B!ق~X0_jMAGfKv7b撸yQxḘE"(((Nǎe$  &%K1`Q^^Gˈ\냙b3p f_cl5CBHtQܱPs w"s)oQ ?)>%D8s̖pǮ]d `ȝ1l0}KE4TWU8 !0C?,X`uG#FP-p4!-̅+bbᖼ37?Nz!Wg^QgQ-?{Y+^FixF )w B@Dq%!8ÂC~~w5DGʹhn.qlx?* O<$N5+u*'+"JoQ 6\QǶ)l8ϭ> BZ 6]|=9tum>sqݻc&MZaN0@Ν;nݺ*;ƅ1Q&B~X03f3&R?qq}vG.PTD')R?^z!W@5\-Y :)jfEH'"PL\6=[15FP ,΍40r=zTkN_xDrkFB!$?~XeejtDk?"4h%AOy!W3؉MB4]k Dh$"P;#5hӯ9Folq2zhyl>}T +7;?j(=:" ! B?̿ѣԩW"YњQO\tJH\(>EDd-j|\5q6yLZs8Ea7&Z$:jstE ;E0VHB!.0ݳgO!X߾6ٛkgh}~M2lG/>߮;ŸMj+7aEƌ\~eqHS@#w^P\\Z !B܀~@*nA 2DFYC@eʈy{i1t^EB?"Gs,T@`kN\_I  l>feak~9.96]|`x9.>'9Ninh Ј=E"҉LV?Luuj,m@uEB!$rN!D;N1::{7_ϿWzˁ ?{nԳ-H9!n,±XdS)t>bIqcym slNu´)HD"j#GΝf͚Z` ܽ{w]:-&LP[BÔ)S\%Z}0&v:Me>9wY}Jҷ+w"tj[v:PM1©)֦#PhB-}σN7qE{^l?e#mL|61Z%qBB&{\:tzR-1l0k.E!LA? >\(//W-M2u.i|ML#)JÞ_{Dk&G6vT҇@|5QZT5k 0-NT !A?{#jjjT q4^0FW:%!J?8t=q0{{8wcѢ) Eb/Q $aAA\6i w0r[Px/i5 !HֵkWi$N`I[%w/E;vx'X"q{qEyVRRZ kc9xl;}10<6υcu5YpLb y~D, Fx" jo߾&Braހhۋ*H\T $\+]6n=Ԇkx?a> M"s\oQ DKa Z BZXvM؎`oTTB61>ދG2B!/}j #Ga8OA^߭?ڒW_J-$>F3DޢAlB6# NpNǶ(fuqhx 6=0LUM #wzrW!s!e|9S-$S$*Vˌn;j[J?AQBt~%cEW;GB$r5B>fM20 8~`&Pqq+]:gG1{7aN@*Ν;nݺe=!0@mB!cƌsbBI"b-y4"4!$sDޢA j8P>aT 4HѮ]ĕ2}SB!~Xv4hAx*R=}QFH+wT{!F^A ي6=zdFdl?FR[B#2^٩S'YhEHϯ=ҒWc24!$HK8!!«Ys#"ȝ2}tYl1eO~\"BHrѱcGѫW/B5EWzɶ-yTO]V{ !^S8!!KKWrGV6`gؖK> j!D!an1dB !>P0߭:+ӜW?5="qBzYc a5Ƒ-/`Nf@lg"!B҃~ʹU :!d?(=t^v)Ճ'"`oQ $'AԢkiK.fLQs^;R+9, P^x~&uW_(=8K|gckw>0S6f׌׾t|/:!ߛ[nYKO?EEEjB!n?lҤIrΰdBιƫbbᖼ37g^iB|N:-j|\Nu]\ZX6?7cG ĉe0ƈMJ !a KTyF>B#~(՜W{!AS^AESMDXv@M4Y:p Ddj<_mڢ ֶc͔t![5ħ_._g7zCDFVΩsgQAL!YCg_g /Z:ujLXԉBrpo{8âħoCѭY tVjI_Z#._mR{ϦΩܠGeT'{!ć@N$IڈrrwGit4ߌ87ȴ H@RBc? ٢FK,e}hRaa7AX>:: ZHϐKR9Oů'AE@}悿)PR$5BHT5rbJNGroH CD,cǎAEn^VKH^8)ϟP-B_0glxe1nEuK !PZd5W<6Etj-0\`gXƅ6}hcp5ǘr5Ј=E+< _mDؠsyO/0S8q;c?L7xںG?~^Qs^V6saY(acAѕ iHtD7㳄ϔ&ȝcgD@F!L.*?1{]婨rO|XLpM! baȏ˨pC?,:v7pC+(ba?Z>M_ 5헢swG Ԅd[85Z6b_~S؏69lu1<ִlRu\8I4qFkDrPGXH[ dVٰa.۫?~i񯏿r@lm{B a$b 3?^\AeqۖēKB~>>{I)3e"+Mm"ioQ Dhf}8t[ Ԝl %^CA.]ׁ4 -i cgǖ&&ȝ>}],C>E0bm 1A׋{^\!JvR=!$K~ ?2a'DP0~XK^>*_bZ!BHDޢA1eզd`;clu y ͂XBM r )F+0r52!>3g)!&Xn堎&E=7$G.ťwkڂ}J!mɄF`z G4GT|0|G(՞`+b:nDޢAqF?Lv\&B0L_m8x=H@ȝ\"^-zzrj6)%#u(kʆU-DX-fFB +Hv޽{  "n` S~}R_l Ԅd[8!XY1yQI"X6壙",ԚI&I' ⳁHl$_#w74o01µJ_Pք ?\êe34K?a^` %J#4rMNX Z~3q &اEav"@47S&6صq<&k#$@#5BH`閙1:fEPk***d*x9r\2d3(~MZ%JOD8؏\ B_FO.a>O5bԊ_Y2}:mX\_ 6@Mt`S D_y4:\Cyc #Ј=EEyZ&Bc~]v]]ر|ѪӫW/g!Sw!⬎2t5meV~Y$jNի}~ӥ?>ػUgsJ5ou!~Ddp uSES` N!Xkb-\cʰ:"Sŷ0Br{R}Dn0g4g Umj6QWr}!b;cu/x *kl³}Lu"N-7IgLd <(*ʝ&H!CCiz\ "dI&Ɉ D%ߺ]~.~LvV}B E?,l+..GV-v)1t^)J?8t2vnV{K#$4 A8c-d[ϧ}mp:3zljl%P]|n0nJ|NZ%#zLU1b uQ:H+dp2uةS:cO. R\'/*oP{!~Xf%?,L˓Uy: ~=9s-+KN^H ~pI@ Zւ)hfX&jnmbns8} ΑH=؆9jns\a-7@<+pPyJNU,d?zXbA%;CٳgFrbj-+jʘ#a`!A~Xv?,,5jKJJT$ee1Jҷ+l;!t^dj R$5OaA6SdhI[ цU5 }0YkLyoAbAGR5$h rw۷oR7"(L#8A"]yCaA'~XnM y_*>֒WGK`E.y擿0BAJ!j 3ZG3GtۚDMM?ø0^57_mXvBz)YrGdl`+wQ}8zړ>H#FH"q9m Q40QBdOS[[+"` R|ș"H;:!kdk׮2a@$B~ CBb-Dw+2{e}JĽ}XND޽U;$ehOP 0BD@#o`3VoS+w#b>D\D`)6zMYYPi(@P"Q -c7 ZhNC)L f$hyqJ1F? n=,>A vm;M&{}O{IF[O;y {F "!J&]mqΧ́9RQzxfSGe'eyM)t20:1,H%jdS.M޴j~$3ίi%}(4hK1(N"Q;n}>BDg,`Cxfy=ଔ $C?=#oT@Fp\x2,gmɦ1"Z!;,ͯbIpnbz%2!m+5-A *q50Zޤ~2qb0zI-O.C '-H)2l /+҈~z'̍\G)X®l8.³!1W{09M%l;ۜ&lg(!:{94$VZl..?bL`.^ےWzLAl5=0:yUbQ<W[B^D[ 0c&(|CyS2=NV owNCDСCe ~ůԈAԴ|zZEx\*lIgPPGK\ɋh@cː?9-F6dq 7-$)CG9y_|(P0BKJ!j)Pg ԉe?zrMQ7k(m*d KOåHWݏ;rR䆰_\\,#;c)6^(yߕc扚SOv $2GX0D//XT62!c:ի H7)>ZO|kSC?D.k?bSF-y wR{ :*qbaB&l[XmXyayAΩOT+XVs( >~aʔ){)@:uJU& *(pQ i=hD0bʙF =  #òGs'M"Hq:I'? 1D~؏E,? yσ͐M E̟k*_{%w>j^d`;#_HK8ZXl W3D]ϥg&ξ&hOTvok6hmB>u DQpזVM״,CEQAKO;=J$ =aB9 t_i<2ag?l9!nٕxM2%Dz_0O۵k' ZR#Q?!Ri>? ^މc߬^|FP 0BDz 7a-j!!p6XKG~>%"Pv9s}ѹKg#B1cH:HY8D e\_rbb(Y@DO34H?ÐsmӾ92.`\_n0MGZ'Q?, N8g,?-9r^ 铐J~!#Eb/Qhcdx/c7qK&.ƦbXax\ o,\o>!z'zm|HNN1Rh|~X>&Yx"wz)ߓTs" bij,0)B!@CST'$H PbM4ݒbت2t)-->'|9R~R5f"?  Qg~;׬?ӾNv?3rH0B#r_5+W!j3`38 b Q'ㆲ*⅐xt@3jj.: 1##DY\:ǎZb=ދT@:2˱ DE1BHv@y`{& Â[~oj]3&1xk0~X*`w7Yɿ؆@J4~Qc%%%%9\"&n+={sbs~"$S{FPgaxC-jE{ _`r{D腓5{`B/pS4dˉzW;:!R{$ "t0/ed D=H@.ÐN{vq4Nxʜ`oeL](#[bW~X߾}JD07|0/iZyHj ?ݾ?igAy}"DoQ $e&/*7_YZH(%Uq)a En=E) PD{1y"rG:Lad1{I d3FH,]/qO^ZCD):/64NaN >\)<}Qi Ko1m? ғtE46&_p3VN>B#~(*O\P{)>ZfuFH EyߩZH .kꩻܠdTGlM1rBNTq;rr)D:L6%K*0L~1M^7교'i%~Xn;XMMbSn~[ `@Rφz0 y-vƸB?z!InQ`Y)]2TDq6_!=R_d #w?I1[[7o߾"UtN֐X7^lEPτd燥!]v~,zdM%V(^T5"c <Ј=E 7 p /*uj pA ,YU<\R#YN}T/n?!yR0Faks?]!}wxlMY9V<߻oVriyaou &8%2R $W<3NĎ^<.~؊+Dǎ|V: %R@1Xq r=Qa`6(|^wڿ0YY:gԡI7&A?x! n1[|q[ Ȥ1r 9I>\k'jqL\ڱJ4nyM\x{hx}87nq[DsXtR1,wE4.S&L*^mxۈA?Y.ΝGC`R1M YԹk*{i,((aɀH] %sFDe-^LGPZ'ɼT}{N3JQEIw@iq2#~!#r5@n|4]$yTGpRDRA#Z9 ˟Ǥ ?@(ƒAe,/4r5#yᓛc*(o'xϑ㰢BNwB€A(2S-臅Df`EK'K,?-pl^ZD~(nșX3A\*'T|į7畾c>Yǿ R|ؾ?0jFP{ 0B24bOQp*6-"v +ZZGOjx|գ湁>۹.\- 5z(9Wm"t4kxc:#'U*62F}5*&j8: j#Rz$ \R)=*j; *Ĕ7!u[nbԩ̭AN0MB΅6? mÇWw1e;V,v5N:ݻ'T|2xxeG-y_{Dk O4j&>}GK.{qM@>S8Z$@c#0Ry_BoXEh)R r!i/)>whz&Mȋ#L0E\bm9yQj!]臅Muы=蟈UD.|YnE_jU?IHHN5i׮Lh~X2>XS2JK/=$PT$ɠB~!yGFѢfJvpEm =G2q >MW. W\_<C}6e+dB-8wӯ/b=Ҧ~Ea^::5۲2՚>nF ƈF`:w,Ew'c*ӌ[-kE Õ&!zgnI3HRwA .'/&FM!o}w_HPL0zhb'zq׼ROl;tNnٕ~!y zS6Ӧ نrZvs)PG˲:nfB.qKZt6~Iօ>Zyn12TW3C|:]M\rUkz:ua 'n^B2 $s6GMw$j/N"? U>gŰ&X^G: ~?y>jDf͚ZK%[Jl \^>">ix.#."E|?!Q2$w\ۼE3tT4BnABH\*g ;dqX :(G:v},}wUֆȩlI& (hd1G?AEsTʏ :x )" #] ?V )G80ؚ}JmbGň'^/.,/7ɿo* i`/][%4-t\}Zs>4+]tQ[/#$}"%oQh,\!/۠ZHixc/S-g(-mlOqP>_/- k$8P4ptH=v$ZOII _^ hע;c($S,YD> m^_/nu$:Vd@q\~{rT#uۦ)B⯉^F/!!by) Iag9{JDS__3oo%2D]s)VO{]k/LGP (FR$M~W?Id?,[m?A?üE+'EK}!EIDATrWkWŹ 8U9|(Iadbjժ#&HёY` B)'B*:!" JHׅIѨݳ!$fy_CYM `q)v&V9ΨQ/"y}X6Bo4CՃ7]H͌6-ZŚY(2Zq=;zxx遖+wT{M~EGe4o}Ju0`FHD_ޢAT"xHn@-jnb_q ~3 Na%=7Prnd*T cltvԈ5h3 Np# I׮+UOVB~XA1D5-9|tcϋ>_5\nk*eDSmjmȥmPްa;pf5^ϯ=ҒW1rPx}A~!Wy"/M|lRy1gNn@}qmiyN]m&0};VԔnCޟP:]P rx u"WeQXXZL5r9LcvFDy¡1MH,ZSKC~Xpz.n9:6 (NظC|ubb6tA{ǿ$a[LXjtE@s`+dۉc߬cʂLG}F6"E@?Ԉܯ<⍁S?X!8 KW[׉n#1d ?A(lE"7-ۼ@<VHTbPDV/.|{S}6ɝŀ*+?bEPk1yVv$_.haNlˁ9y=C}lʱ"5)W4bO%FHj@*>?X QjtaфUSnMF;laG[ZOӧV*m#LV=v=,S.yDRmAݻ\ɠ##G:2E &={":DŽ]{jABHl?h-f~7 " Ҧ!/|XTT  i[>_M|nX>'z x孽r[P>'_:(\ҜWz̽bKcUl96A5FH@.>oPCbm,8"Z}ng =^1_m]|.}>a9^-f&$le|N:{I~ecDH"4ny8|M/Vfܷ0ˆNI2Q-Ν;h1BN`9"uC"%%%rڎV$ßCaBVө (v*fFuEt ?]fb|dRT-Zſr5A#+8t?Z.&n+=sqq*?7~b@y5l&kS FA5'Cю]wN}QQq6 @޻QnmFGyp.ql1s1ytKX'6< \z|I=*v%NǦ)PkMM&۰ZLh!5ξ:6_?^i95@{[` ..27Q ѭi[q]*\2-CqnQ16s-р36G&ȅc| [?2R ӄdWI2<)`|$9up4q몕עWek[/k%s[3[5i}=)j! _/-S C&mVIDeO)B`5kmSx湵@hW?9>9[c9l @?1il^|:1:UB#ro2IHmb jU"P}x}@c'@Zjm!F}?i,ܣ>]H@5.۷G-oF>CiDv 4H枆0WF"d ju˞ê;ÂsSe`V@1{de23zܫ2 Ȩ3Z'cEdJ~(z96h R%P#$9"%xc`B)>bE;ɶ@wӉ_7u5s:_C2vooVC5׾FF.j7ؾ8Ϸu>H4^,Ӂ :*DmmJHi: M /!LC޳- !%mҝ$ &H6qk'.l%'c},Ӂ zlqYK;҈ElXXz1̌h-"BFJ[f460-oXF]@ [犮~ь3Ij3c@^m&h3tb)kNAm,~!8$Y$Q%+H nKE8_/Υvl9Vl^^ky"cSDb_mNyZ_uAc7s6CI}ƹq==gZI#=VlE[+RH^`ԩS\(ȕ[̚5KakݣG% ʃP^y\[Jb'~X.'m2zmț!UDſ ʎyEN4W~pr)N?6-UCZJ}J,f?4? p~׿;e 61~! }5tw6.ڸx" ja56'دEhg-fk@~&)@kynza6[e+´o[E}N2e'bri+"5={1ci\'x/|ACU<]֟OXZ6?,-GDt/t (&c:}E7M׾yAq?`KQEbG~;OnA#2u^FHr@*7-/PD;Sd_(/5bo#Z4Dj-@:5~9 >JϧjOטD_6oүޒi! ҁ߿Xt-S^8#RpȐ!r_[x?ӟTl;Y)JOg4!>T[q%$Ar`N$#Z@1C:{n}s.ȡw_?^*nKLݐ~Eoo]F>|{%O#$9 {qnztx_Z5)@c pj "mh9EX"3B*m>3/@}Dڛ㾻=v&a@t}oŨi79qNCcr5yoEyBbd?,W鱵`CZy-!ϖ-͙/~poď'-Q{S+ǥc,/꯶?[Ժ:'IȽ[8H 7$S4 ]mj#N'ކU6u}ۢvWx%Iւ郳[kwYG---[w7]cE2*I‹^`+ 8R$5pii 3:=6R]F8SwgHWʋhҁ oԪUw UB܁KKI 67NΒuw>ۯW|chqϋM}U q6ǥk,=Xw\~>DggTl=u0)dnFiRRR"ύp;SOm567J#5p.UǙ<;ԗݼA`vbS 1kܺm$;DoQ 9ǓDiXt†"~3D򖛌  jkJ_@=cʁi.%Ӏ (B KH,q[ V0opoo__4= J6wOZ /3k)6WXKX@;^?ڛ:Dtj-<&FM0S8>>oSH7ϝ Al5MQS9qX@s:m,&8)6;j<6tEq-qHvoE8ȋD DX r@د&w]ހ`XYV6#ߜF,Q{sӃ{Vmҁ Y1|G>B!d*T !v7?i+Z Ak-az7_>/[)noio+mXFUwTbj1ckx٧{L}&j0lk|N "!P-H_SN繓%h~X5qn0mK>ϡ%+X# <~x霏1Bv(T6uݤjo,~5"޾;nL x[d:B\bӋ录yI<"ۊWbH6Y:;ji7lV>,6}E7$3{Za[#YNfB4Ј=E Ox' DgSD@6kq Z8ODPI\PP @pFϿHX7}liv5<?D.CF ?T6#wCt 'u zӣsU !  Dޑzqh a7L76u?/o1MZ%~YuUd# (fcDPB?:ZuLhĞA]AXM-MFg[:>W&j8FӕKo]67}[/u  he/#yaߺ]~ #T,/%$2(>E'DFKg2b:X%co d~{殺Y@13t/m=Aw*әJ5ѻQrrj%es$~Xck[! ~>gKRM۶=ď* Ƶ:1`ioK; (~ooNӇ~!#Eb/Q Drϋ+䅼d!BHll#R_GTXEG9_n]ÏTANWDqGDW# 'Brm?_XV M/.lP?= (&ؿk FP0a(r6 ErHH 'uݤmDjDW_q/"EV c "8ɂt =6>$kwVB z㯩B~XpE^^uNfPL4b9[6>=wS3VHe}a089nB6a hm(pACs&T;abF_l m6f166@I#5BZx⨼1@8Li+RGaӪ;~BڦT#xfy)H';n"oQ XZ ;ACR~km=ťE;aFg<&E}6Q[$Q] &Jy\NGtl5 )vFm+ő/ (:mIWVoo{`_4P̯vSݛE(}J0|GQ &8}s853m@s}xDOޢAH+՞wTtEU q@ݚ#|W^rTk&PwQ>_zz?SyKdê'{g1F|P8涢חi5T'2Z@4䧾bA11৿}IXP[~L wOL` E]S kjÌ6#Q8/@m-R۶9NcxC-ja yl^R@+r}՞fІ>cDglnӶYt8۬Buľʑ{(:36ɱXI}4]<V>M_&(k.arm02:2탙!ڄ^??4U~6La봯wzbh)=d?jLH%jX=%\@6cNAl8-+cP܏)PS67׸VRyVָi.Y)|e~=e-B7lHM&(v\}!O VB!~X)!h][1 T'l`~.贻] {?~!+߰q}ϼ"_ 7 իNXB|w"jA?[(P){!V^&₏AFLj$*P>iq8jgr8?"5 E:ϵMbü=]i,wIv2*T6!o~5ysIX0z!#mB)Tk H{E =5G>}o:pg>+_CNĊ-V5,KM ?#]{!1qQx< DK 9SvɥeDP ;=wTz-tq ,CE$ $Se޸aGj!$3 Am`,T#|iHGy9~bȐ!F?li{j؃ǐ#Uc:v(7fR{H*:48`S8}pՒ{Ӧ9 -:(.ӵkWtESޭir)fT5 6L}"#B/CEaq9=qݪB?,@ h\W djǏ/ z)}Qcرela3>.Lxg o"@=zZs %ء(Pu[8Ikޗ7 # ڷopQkg?fԦϿ_\٧J Dz:w:}ŃeKˇ?' Hv^b ?ߝ\ DO'_/>#D}}ikA]QQ!x bРAg& :]als;-sxA:NVT{B{,XAB'~S ƶ>CDx\RR"ϩŹ>mm?$y<Ơc9>1yEѓR-\yI0`@MW^);M5Sĩ="uE7>V\=uD52_sL. ߑ'VԔɪLBAqx pK;MbSH~W eż7Z|Z58sI1{С am{ҏ6&- ՈEAee9x„ RDj3.,,yyy-l0a fE^m1hAhQX xb eOmm$;DwoQ $)7.3%B4 ,m4irK;׈3So(lFQFoxIkkweU+!@Ľ!!^B?,9.E7E޲E|lPRCQ&fK0JFztCF}5BRbGOT+ #N-JO@qfO*TILUp\N$78('uObbuQ3U2b:((!#n i >/[ 5kDΝ)\2z,vV]fo5A*$=l~"CJXB8pEnv(4)H(88>H(^aR$5BRԹ rbFCܠ7i8Ab"?C\L ]SVW)_,s'Q^y\=8KԜDaǡF!oy-Vk,|Z@q/vcy,CD Ϙ1Cu̵ϲB󌏄̷n~vM⍏f~pZBЍ=DqD㻢? ;R$5BKKryyaJvɛp .duEQ}Cʌ=2}=rDjwIe!0} (P_~ICDwz D9}DCMcƶQ[z$EY(-? idad){!jFr" ,BDH :(93Ѱibj* |oTaM"b5&YM胵V@uC p4 r~ WY&;nHb_ð B?DK#mi7V& }`?ܦ 8P"Qi/^,z7ȥ)gl=A^:EAYu,nHH|ּEW/M[%o0V`ra],TݿaEw2: D^:+Mf:"yB&?z!DA!/ 2J B,qi Q3l~8vUF@[ G3ː#1:sRFkQ&@^AHFX`˯ "AQ8??_.[.;7(9Wɵ;$_ie„Ru9^|sxV'B 6feM8Ybܹ8q+u! &fd0FPf`nFܯh"1pz!9u)DQ-P"y}^ o/_ 78s<~8-j+@\Or L?E.C-<]L|$#aY!n՜b&¾j`$*HO{P&A$6k,1tPE҅~Xk6)HG;F8?Q,Uh#"Y5B2H霈kUV-b4S6nmx-PC1Lіk0!e[eG/T$9,E'1!@P0 H uCCHl"i@F{bԨQjIavurb13Xq`|xLG-jd T '3 տjg4hDlbt,`!vGKf-;S~DCG[CA-jdS.!O/7',rS`͉3B)XCFNgFLDTc j0H pDMԜW{M䇑BdDQ|b.2%f5Ġ d'qMCO@]w*D`iBRgu;ePO_[.1XB0F2 YXX(ƍ'u&`HpX4臵~Xx0H5 .J&5B)SHF1f̘69w Ka J&5B|5˛nfppظSrr\kCOX1'D%$9@ʌ;iӦ#F>GuX#%{!73NK^9)"#4]C,Cgj 6 }0W+{9ѩSM2ԱFRi6PԐLdbP ėy BϋAB7䤈"?X9(T`$Ԉ+Vm۶ ('҉0(I&Q2wqkf&oz0Z5lbtJd0/g#$L}C.CEDDwsBDHu?,Ȅ{}'U][ikvR=cױVc%} +Ŧ3joԜcߌ㐳0?oktxoqxe>w<Ŭ zm׋޽{{WSNm^Vu<&'N3rCvA.Ppa8oW? SLF$~ 'V9`-BM:hDƍݺujO5j,%‹M,X eSHNT}nFiqHsߴU-.ZSI 1l8۝۹&PcR4I 2TD7qe龖wv B~q`=!sB֘Qˉ>v2ئ@c 'ޘMiwZ@߿_t1p3eS`6gk-6'#Pl;Aρqx P{p I]b9䴈MZ@6i"8hM@}j,5#/pE=!z|Dac ^%'F#>)LA9i4LLڹ/?Lc9B MaXaIFEEIzѣYA a&Z5!BޡAHhM* 8̠+S&~Sxb{eu[a!|00!"Ix[S\UPLMMbF\;Oâa% )M^37j8G4IjѹsgOj'wa5%{!7Z]'Ue0)a"(%F+waTybyƤB!~RMCJXb9l ~0g+Lh晆<>f(mS(zn ,?Yd^GyD[ >\YtR<BbdbP $\rUlFfSHTBpI<6H-|SۻBB f¯Y\fWXB!9f?'Δ!s)ƣaq"{נ Zh׋ArQhsEP۠FC˕yq aiwĉDgEMY*Bk5k.O{ /G6{ԪUYJO>Ò>Xb2`Nɘ-YcW7&&h}"Pk==dMS][[FP#BAޡAHN K9IsLBR9µDA h!~Xt%G,:ټ3簡â4cnOa@B5UԨ=jadQ2wqptjb O!d()Ƿʉ 'BHX }똂)T@u0QS δ 61 SM֘}a@@_~YtI=hl? !dbP $sqg.#%$̙F1yQIҭP,p+.C%$|F- a>`l!"a\X818fh}1g4O!fԩ2r50afC8!&ɥE+j/yW4T,4f~Qê[ZM$u BL١FP2wqB ka).vC>0ҡ\B.SkZ~J;G*EGZM`6>$BA0`@?,5J&5BǠ=&E(MVlNB3'E~Z [ Hj_ic&-V$DL,Q?pF܅~XfFHvQ2wqB|cvt`F~Iф-BHAdr[Uҁ{Ov\$ 6`S2j.[ad%{!$ g 17#*jD# !iD⊖  KF J3 '68?|ZI"(lP!aômaa~!dbP ]7fD = Kw0!Ew_vIΞC'E%⻣8c08ghd&7$^XUo̗vPiQǜ$ T-n`~!ك~I%{!ć)k4ST;)ז6 9װD>9V{V. PX 9 g&UISzzV$&Bgdt&4u;&T\JHɖ:H2#$:J&5Bp7 A5jD 3wӣs36ȼ, DN] PwA3WH4'I6[fu!$i~iC0)*8U.E; ;X ٻg(ܤrb2 rEw}ˎANDs"d_T !n$ #a~Hgpdra]3TKz#5!$4ƕ~ UQQ>N'm,+ddE)K;n-?s(R<"!>(|!&T|<8P"\o<[ԪU&@_F͗HI`~H:_L+櫖FH3J&5BiiA.CD8UQ4'TFmBL9BQ)Lz_I~flQ7h*9")#u涖nIήe!6伝ux(X F-uzn%'FW*BR'}0@?0  CE0)Elh>yN_ۦi%s ,i:~Z,O,Somspq%7W $`"'E0B }Ġ#~EU!!}Lj}K_e! JN"uِ:KHTebTjYtU",E&={iA۲N?C/?pI=!ޠ#w09 !ח_tji r/~X5VMy0Ft  { V!!=Lj䟊6c'ylue>񃥬ȏ-pmc(ZL pNepaXIΪXbY=Ƿ# !BH:#BJ&5Br%X'@B!daB!CޡAHNPzz_QB!l@?B!ğ(B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B!B /*? IENDB`././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.8236792 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/0000755000077000000000000000000015060352601022537 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXactivity.nxdl.xml0000644000077000000000000000532714777236751026363 0ustar00rosborn A planned or unplanned action that has a temporal extension and for some time depends on some entity. This class is a super class for all other activities. Start time of this activity. It is recommended to include local time zone information. End time of this activity. It is recommended to include local time zone information. In some cases, the end time of an activity can only be estimated. In this case, this attribute shall be True. Short description of the activity. This can be any data or other descriptor acquired during the activity (NXnote allows to add pictures, audio, movies). Alternatively, a reference to the location or a unique identifier or other metadata file. In the case these are not available, free-text description. Any number of instances of :ref:`NXnote` are allowed for describing extra details of this activity. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXactuator.nxdl.xml0000644000077000000000000000730015046415443026325 0ustar00rosborn An actuator used to control an external condition. The condition itself is described in :ref:`NXenvironment`. Name of the actuator Short name of actuator used e.g. on monitor display program The physical component on which this actuator acts. This should be a path in the NeXus tree structure. For example, this could be an instance of NXsample or a device on NXinstrument. Name for the physical quantity effected by the actuation Examples: temperature | pH | magnetic_field | electric_field | current | conductivity | resistance | voltage | pressure | flow | stress | strain | shear | surface_pressure The type of hardware used for the actuation. Examples (suggestions, but not restrictions): :Temperature: laser | gas lamp | filament | resistive :Pressure: anvil cell :Voltage: potentiostat Any output that the actuator produces. For example, a heater can have the field output_power(NX_NUMBER). If the actuator is PID-controlled, the settings of the PID controller can be stored here. Refers to the last transformation specifying the position of the actuator in the NXtransformations chain. This is the group recommended for holding the chain of translation and rotation operations necessary to position the actuator within the instrument. The dependency chain may however traverse similar groups in other component groups. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXaperture.nxdl.xml0000644000077000000000000001032214777236751026345 0ustar00rosborn A beamline aperture. Note, the group was incorrectly documented as deprecated, but it is not and it is in common use. You can specify the geometry of the aperture using either NXoff_geometry or for simpler geometry shape and size. The reference point of the aperture is its center in the x and y axis. The reference point on the z axis is the surface of the aperture pointing towards the source. In complex (asymmetric) geometries an NXoff_geometry group can be used to provide an unambiguous reference. .. image:: aperture/aperture.png :width: 40% Use this group to describe the shape of the aperture. Stores the raw positions of aperture motors. Location and shape of aperture .. TODO: documentation needs improvement, contributions welcome * description of terms is poor and leaves much to interpretation * Describe what is meant by translation _here_ and ... * Similar throughout base classes * Some base classes do this much better * Such as where is the gap written? location and shape of each blade Absorbing material of the aperture Description of aperture Shape of the aperture. The relevant dimension for the aperture, i.e. slit width, pinhole and iris diameter Describe any additional information in a note. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXapm_charge_state_analysis.nxdl.xml0000644000077000000000000001560115046415443031677 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The number of ion candidates. Maximum number of allowed atoms per ion. Number of entries Base class to document the parameters, configuration, and results of a processing for recovering the charge state and nuclide composition of an ion from ranging definitions as used in the research field of atom probe microscopy. A ranging definition classically reports only the mass-to-charge-state-ratio interval plus the elemental composition, but not necessarily the nuclide that compose the ion. As the mass-resolving-power in an atom probe instrument is finite and typically lower than for cutting edge tandem mass spectrometry it is possible that different combinations of nuclides are indistinguishable and thus multiple ions in eventually even different charge states can be valid labels for a given mass-to-charge-state-ratio peak. Enumerating the possible combinations is a programmatic approach that can help with peak identification. Parameters for the algorithm used to recover which combinations of nuclides have a mass and charge that matches a set of constraints. Each parameter in this group is defines one constraint. Parameter that defines the elements considered in the combinatorial search. The array contains nuclides as many times as their multiplicity and must not be empty. Nuclides are encoded using the hashing rule that is defined in by nuclide_hash of :ref:`NXatom`. Constraining the elements or nuclides instead of providing all nuclides reduces the time to perform an exhaustive combinatorial search. Parameter that defines the interval :math:`[{\frac{m}{q}}_{min}, {\frac{m}{q}}_{max}]` within which ions with given mass-to-charge-state-ratio qualify as candidates. Parameter that defines the minimum half life for how long each nuclide of each ion needs to be stable such that the ion qualifies as a candidate. Parameter that defines the minimum natural abundance of each nuclide of each ion such that the ion qualifies as a candidate. If the value is false, it means that non-unique solutions are accepted. These are solutions where multiple candidates have been built from different nuclide instances but the charge_state of all the ions is the same. Signed charge, i.e. integer multiple of the elementary charge of each candidate. Table of nuclide instances of which each candidate is composed. Each row vector is sorted in descending order. Unused entries in the matrix should be set to 0. Use the hashing rule that is defined in nuclide_hash of :ref:`NXatom`. Accumulated mass of the nuclides in each candidate. Not corrected for quantum effects. The product of the natural abundances of the nuclides for each candidate. For each candidate the half life of the nuclide that has the shortest half life. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXapm_measurement.nxdl.xml0000644000077000000000000000712615046415443027673 0ustar00rosborn Base class for collecting a run with a real or a simulated atom probe or field-ion microscope. The term run is understood as an exact synonym for session, i.e. the usage of a real or simulated tomograph or microscope for a certain amount of time during which one characterizes a single specimen. Research workflows for experiments and simulations of atom probe and related field-evaporation evolve continuously and become increasingly connected with other methods used for material characterization specifically electron microscopy. A few examples in this direction are: * `T. Kelly et al. <https://doi.org/10.1017/S1431927620022205>`_ * `C. Fleischmann et al. <https://doi.org/10.1016/j.ultramic.2018.08.010>`_ * `W. Windl et al. <https://doi.org/10.1093/micmic/ozad067.294>`_ * `C. Freysoldt et al. <https://doi.org/10.1103/PhysRevLett.124.176801>`_ * `G. da Costa et al. <https://doi.org/10.1038/s41467-024-54169-2>`_ The majority of atom probe research is performed using the so-called Local Electrode Atom Probe (LEAP) instruments from AMETEK/Cameca. In addition, several research groups have built their own instruments and shared different aspects of the technical specifications and approaches including how these groups apply data processing e.g.: * `M. Monajem et al. <https://doi.org/10.1017/S1431927622003397>`_ * `P. Stender et al. <https://doi.org/10.1017/S1431927621013982>`_ * `I. Dimkou et al. <https://doi.org/10.1093/micmic/ozac051>`_ to name but a few. A statement whether the measurement completed successfully, or was aborted. Statement about the quality of the measurement. The value can be extracted from the CAnalysis.CResults.fQuality field of a CamecaRoot ROOT file. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXapm_ranging.nxdl.xml0000644000077000000000000001256415046415443026775 0ustar00rosborn Base class for the configuration and results of ranging definitions. Ranging is a data post-processing step used in the research field of atom probe during which elemental, isotopic, and/or molecular identities are assigned to mass-to-charge-state ratios within certain intervals. The documentation of these steps is based on ideas that have been described in the literature: * `M. K. Miller <https://doi.org/10.1002/sia.1719>`_ * `D. Haley et al. <https://doi.org/10.1017/S1431927620024290>`_ * `M. Kühbach et al. <https://doi.org/10.1017/S1431927621012241>`_ Specifies the mass-to-charge-state ratio histogram. Smallest :math:`{\frac{m}{q}}_{min}` mass-to-charge-state ratio value. The lower (left-hand side) inclusive bound of the interval :math:`[{\frac{m}{q}}_{min}`, {\frac{m}{q}}_{max}]`. Largest :math:`{\frac{m}{q}}_{max}` mass-to-charge-state ratio value. The upper (right-hand side) inclusive bound of the interval :math:`[{\frac{m}{q}}_{min}`, {\frac{m}{q}}_{max}]`. The number of bins on the interval :math:`[{\frac{m}{q}}_{min}`, {\frac{m}{q}}_{max}]`. A default histogram aka mass spectrum of the mass-to-charge-state ratio values. Details of the background model that was used to correct the total counts per bin into counts. Free-text field to describe how atom probers define a background model. Thereby, community feedback can be collected to inform an improved version of this base class in the future. How were peaks in the mass-to-charge-state ratio histogram identified. Details about how peaks, with taking into account error models, were interpreted as ion types or not. How many ion types are distinguished. If no ranging was performed, each ion is of the special unknown type. The iontype ID of this unknown type is 0 representing a reserved value. Consequently, start counting iontypes from 1. Assumed maximum value that suffices to store all relevant molecular ions, even the most complicated ones that one can typically observe and distinguish typically. Currently, a value of 32 is used (see M. Kühbach et al. <https://doi.org/10.1017/S1431927621012241>`_). ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXapm_reconstruction.nxdl.xml0000644000077000000000000002775015046415443030434 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Number of ions spatially filtered from results of the hit_finding algorithm from which an instance of a reconstructed volume has been generated. These ions get new identifier assigned in the process - the so-called evaporation_id, which must not be confused with the pulse_id! Base class for the configuration and results of a reconstruction algorithm. Generating a tomographic reconstruction of the specimen uses selected and calibrated ion hit positions, the evaporation sequence, and voltage curve data. Very often scientists use own software scripts according to published procedures, so-called reconstruction protocols. Parameters that configure a reconstruction algorithm which takes hit data and mass-to-charge-state ratio values to construct a model of the evaporated specimen. This model is called the reconstructed volume. Researchers in the field of atom probe call these algorithms reconstruction protocols. Different such protocols exist. Although these are qualitatively similar, each protocol uses and interprets the parameters slightly differently. The majority of reconstructions is performed with the proprietary software APSuite / IVAS, the source code for the reconstruction protocols that this software implements in detail is not open but the parameters and their qualitative effect on the reconstructed volume follows the protocols that are discussed in the atom probe literature. This group allows to document these parameters in a standardized manner. Lowest voltage at which an ion that is considered in the reconstructed volume has been extracted from the specimen. Highest voltage at which an ion that is considered in the reconstructed volume has been extracted from the specimen. Qualitative statement about which reconstruction protocol was used. For reconstructions performed with APSuite / IVAS the value "cameca" should be used. Assumed primary element based on which the reconstruction is calibrated. The value can be extracted from the CAnalysis.CSpatial.fPrimaryElement field of a CamecaRoot ROOT file. Assumed detection efficiency The value can be extracted from the CAnalysis.CSpatial.fEfficiency field of a CamecaRoot ROOT file. Nominal flight path The value can be extracted from the CAnalysis.CSpatial.fFlightPath field of a CamecaRoot ROOT file. Assumed evaporation electric field The value can be extracted from the CAnalysis.CSpatial.fEvaporationField field of a CamecaRoot ROOT file. Image compression factor (ICF) The value can be extracted from the CAnalysis.CSpatial.fImageCompression field of a CamecaRoot ROOT file. Sum of ion volumes The value can be extracted from the CAnalysis.CSpatial.fKfactor field of a CamecaRoot ROOT file. Shank angle The value can be extracted from the CAnalysis.CSpatial.fShankAngle field of a CamecaRoot ROOT file. Assumed atomic volume The value can be extracted from the CAnalysis.CSpatial.fTipRadius field of a CamecaRoot ROOT file. The value can be extracted from the CAnalysis.CSpatial.fTipRadius0 field of a CamecaRoot ROOT file. The value can be extracted from the CAnalysis.CSpatial.fVoltage0 field of a CamecaRoot ROOT file. Different strategies for crystallographic calibration of the reconstruction are possible. Therefore, we collect first such feedback before parametrizing this further. If no crystallographic calibration was performed, the field should be filled with the n/a, meaning not applied. Possibility of a free text field that allows to report additional details related to the reconstruction protocol. For LEAP systems and reconstructions that are performed with APSuite / IVAS see also `B. Gault et al. <https://doi.org/10.1093/mam/ozae081>_` and `T. Blum et al. <https://doi.org/10.1002/9781119227250.ch18>`_ (page 371). for best practices on the reporting of metadata in atom probe tomography. Three-dimensional positions of the ions in the reconstructed volume. The instance of :ref:`NXcoordinate_system` in which the positions are defined. Visual overview of the reconstructed dataset via a three-dimensional histogram of ion counts. Ion counts are characterized using one nanometer cubic bins without applying any smoothening of reconstructed positions during the histogram computation. Such preview is useful to get an impression of the macroscopic shape of the reconstructed volume. Visualizing by ion counts highlights density variations the reconstructed volume that are signatures of features such as poles, interfaces or irregularities of the specimen shape. Sum of ion volumes The value can be extracted from the CAnalysis.CSpatial.fRecoVolume field of a CamecaRoot ROOT file. The nominal diameter of the specimen ROI which is measured in the experiment. The physical specimen cannot be measured completely because ions may launch but hit in locations other than the detector. Tight, axis-aligned bounding box about the point cloud of the reconstruction. Minimum coordinate value along the x-direction Maximum coordinate value along the x-direction Minimum coordinate value along the y-direction Maximum coordinate value along the y-direction Minimum coordinate value along the z-direction Maximum coordinate value along the z-direction ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXapm_simulation.nxdl.xml0000644000077000000000000000300015046415443027515 0ustar00rosborn Base class for simulation of ion extraction from matter via laser and/or voltage pulsing. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXatom.nxdl.xml0000644000077000000000000002365715046415443025460 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Number of atom positions. Dimensionality Maximum number of atoms/isotopes allowed per ion. Number of mass-to-charge-state-ratio range intervals for ion type. Base class for documenting a set of atoms. Atoms in the set may be bonded. The set may have a net charge to represent an ion. An ion can be a molecular ion. Given name for the set. This field could for example be used in the research field of atom probe tomography to store a standardized human-readable name of the element or ion like such as Al +++ or 12C +. Given numerical identifier for the set. The identifier zero is reserved for the special unknown ion type. Identifier used to refer to if the set of atoms represents a substance. Signed net (partial) charge of the (molecular) ion. Different methods for computing charge are in use. Care needs to be exercised with respect to the integration. `T. A. Manz <10.1039/c6ra04656h>`_ and `N. G. Limas <10.1039/C6RA05507A>`_ discuss computational details. Charge reported in multiples of the charge of an electron. For research using atom probe tomography the value should be set to zero if the charge_state is unknown and irrecoverable. This can happen when classical ranging definition files in formats like RNG, RRNG are used. These file formats do not document the charge state explicitly but only the number of atoms of each element per molecular ion surplus the respective mass-to-charge-state-ratio interval. Details on ranging definition files in the literature are `M. K. Miller <https://doi.org/10.1002/sia.1719>`_. Assumed volume affected by the set of atoms. Neither individual atoms nor a set of cluster of these have a volume that is unique as a some cut-off criterion is required. Index for each atom at locations as detailed by position. Indices can be used as identifier and thus names for individual atoms. Nuclide information for each atom at locations as detailed by position. One `approach <https://doi.org/10.1017/S1431927621012241>`_ for storing nuclide information efficiently is via individual hash values. Consult the docstring of ``nuclide_hash`` for further details. Position of each atom. Path to a reference frame in which positions are defined to resolve ambiguity when the reference frame is different to the NeXus default reference frame (McStas). Relative occupancy of the atom position. This field is useful for specifying the atomic motif in instances of :ref:`NXunit_cell`. Vector of nuclide hash values. The vector is sorted in decreasing order. Individual hash values :math:`H` `encode <https://doi.org/10.1017/S1431927621012241>`_ for each nuclide or element the number of protons :math:`Z` and a constant :math:`c` via the following hashing rule :math:`H = Z + c \cdot 256` . :math:`Z and c` must be 8-bit unsigned integers. The constant :math:`c` is either set to number of neutrons :math:`N` or to the special value 255. The special value 255 is used to refer to all isotopes of an element from the IUPAC periodic table. Exemplified for hydrogen (meaning irrespective which isotope), its hash value is :math:`H = 1 + 255 \cdot 256 = 65281`. Exemplified for the :math:`^{1}H` hydrogen isotope (:math:`Z = 1, N = 0`), its hash value is :math:`H = 1 + 0 \cdot 256 = 1`. Exemplified for the :math:`^{2}H` deuterium isotope (:math:`Z = 1, N = 1`), its hash value is :math:`H = 1 + 1 \cdot 256 = 257`. Exemplified for the :math:`^{3}H` tritium isotope (:math:`Z = 1, N = 2`), its hash value is :math:`H = 1 + 2 \cdot 256 = 513`. Exemplified for the :math:`^{99}Tc` technetium isotope (:math:`Z = 43, N = 56`), its hash value is :math:`H = 43 + 56 \cdot 256 = 14379`. The special hash value :math:`0` is a placeholder. This hashing rule implements a bitshift operation. The benefit is that this enables encoding of all currently known nuclides and elements efficiently into an 16-bit unsigned integer. Sufficient unused indices remain to case situations when new elements will be discovered. Table which decodes the entries in nuclide_hash into a human-readable matrix instances for either nuclids or elements. Specifically, the first row specifies the nuclide mass number. When the nuclide_hash values are used this means the row should report the sum :math:`Z + N` or 0. The value 0 documents that an element from the IUPAC periodic table is meant. The second row specifies the number of protons :math:`Z`. The value 0 in this case documents a placeholder or that no element-specific information is relevant. Taking a carbon-14 nuclide as an example the mass number is 14. That is encoded as a column vector (14, 6). The array is stored matching the order of nuclide_hash. Associated lower :math:`{\frac{m}{q}}_{min}` and upper :math:`{\frac{m}{q}}_{max}` bounds of the mass-to-charge-state ratio interval(s) :math:`[{\frac{m}{q}}_{min}, {\frac{m}{q}}_{max}]`. (boundaries inclusive). This field is primarily of interest for documenting :ref:`NXprocess` steps of indexing a ToF/mass-to-charge-state ratio histogram. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXattenuator.nxdl.xml0000644000077000000000000000720514777236751026712 0ustar00rosborn A device that reduces the intensity of a beam by attenuation. If uncertain whether to use :ref:`NXfilter` (band-pass filter) or :ref:`NXattenuator` (reduces beam intensity), then choose :ref:`NXattenuator`. Distance from sample. Note, it is recommended to use NXtransformations instead. Type or composition of attenuator, e.g. polythene Thickness of attenuator along beam direction Scattering cross section (coherent+incoherent) Absorption cross section The nominal amount of the beam that gets through (transmitted intensity)/(incident intensity) In or out or moving of the beam time stamp for this observation The reference point of the attenuator is its center in the x and y axis. The reference point on the z axis is the surface of the attenuator pointing towards the source. In complex (asymmetic) geometries an NXoff_geometry group can be used to provide an unambiguous reference. .. image:: attenuator/attenuator.png :width: 40% Shape of this component. Particulary useful to define the origin for position and orientation in non-standard cases. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXbeam.nxdl.xml0000644000077000000000000004526215046415443025420 0ustar00rosborn These symbols coordinate datasets with the same shape. Number of scan points. Number of channels in the incident beam spectrum, if known Number of moments representing beam divergence (x, y, xy, etc.) Properties of the neutron or X-ray beam at a given location. This group is intended to be referenced by beamline component groups within the :ref:`NXinstrument` group or by the :ref:`NXsample` group. This group is especially valuable in storing the results of instrument simulations in which it is useful to specify the beam profile, time distribution etc. at each beamline component. Otherwise, its most likely use is in the :ref:`NXsample` group in which it defines the results of the neutron scattering by the sample, e.g., energy transfer, polarizations. Finally, There are cases where the beam is considered as a beamline component and this group may be defined as a subgroup directly inside :ref:`NXinstrument`, in which case it is recommended that the position of the beam is specified by an :ref:`NXtransformations` group, unless the beam is at the origin (which is the sample). Note that ``incident_wavelength``, ``incident_energy``, and related fields can be a scalar values or arrays, depending on the use case. To support these use cases, the explicit dimensionality of these fields is not specified, but it can be inferred by the presense of and shape of accompanying fields, such as incident_wavelength_weights for a polychromatic beam. Distance from sample. Note, it is recommended to use NXtransformations instead. Energy carried by each particle of the beam on entering the given location. Several use cases are permitted, depending on the presence or absence of other ``incident_energy_X`` fields. The usage should follow that of :ref:`incident_wavelength </NXbeam/incident_wavelength-field>`. The energy spread FWHM for the corresponding energy(ies) in incident_energy. The usage of this field should follow that of :ref:`incident_wavelength </NXbeam/incident_wavelength-field>`. Relative weights of the corresponding energies in ``incident_energy``. The usage of this field should follow that of :ref:`incident_wavelength </NXbeam/incident_wavelength-field>`. Energy carried by each particle of the beam on leaving the given location Change in particle energy caused by the beamline component In the case of a monochromatic beam this is the scalar wavelength. Several other use cases are permitted, depending on the presence or absence of other incident_wavelength_X fields. In the case of a polychromatic beam this is an array of length **m** of wavelengths, with the relative weights in ``incident_wavelength_weights``. In the case of a monochromatic beam that varies shot- to-shot, this is an array of wavelengths, one for each recorded shot. Here, ``incident_wavelength_weights`` and incident_wavelength_spread are not set. In the case of a polychromatic beam that varies shot-to- shot, this is an array of length **m** with the relative weights in ``incident_wavelength_weights`` as a 2D array. In the case of a polychromatic beam that varies shot-to- shot and where the channels also vary, this is a 2D array of dimensions **nP** by **m** (slow to fast) with the relative weights in ``incident_wavelength_weights`` as a 2D array. Note, :ref:`variants <Design-Variants>` are a good way to represent several of these use cases in a single dataset, e.g. if a calibrated, single-value wavelength value is available along with the original spectrum from which it was calibrated. Wavelength on entering beamline component In the case of a polychromatic beam this is an array of length **m** of the relative weights of the corresponding wavelengths in ``incident_wavelength``. In the case of a polychromatic beam that varies shot-to- shot, this is a 2D array of dimensions **nP** by **m** (slow to fast) of the relative weights of the corresponding wavelengths in ``incident_wavelength``. The wavelength spread FWHM for the corresponding wavelength(s) in incident_wavelength. In the case of shot-to-shot variation in the wavelength spread, this is a 2D array of dimension **nP** by **m** (slow to fast) of the spreads of the corresponding wavelengths in incident_wavelength. Beam crossfire in degrees parallel to the laboratory X axis The dimension **c** is a series of moments of that represent the standard uncertainty (e.s.d.) of the directions of of the beam. The first and second moments are in the XZ and YZ planes around the mean source beam direction, respectively. Further moments in **c** characterize co-variance terms, so the next moment is the product of the first two, and so on. Size of the beam entering this component. Note this represents a rectangular beam aperture, and values represent FWHM. If applicable, the first dimension shall represent the extent in the direction parallel to the azimuthal reference plane (by default it is [1,0,0]), and the second dimension shall be the normal to the reference plane (by default it is [0,1,0]). Wavelength on leaving beamline component Polarization vector on entering beamline component Polarization vector on leaving beamline component Polarization vector on entering beamline component using Stokes notation The Stokes parameters are four components labelled I,Q,U,V or S_0,S_1,S_2,S_3. These are defined with the standard Nexus coordinate frame unless it is overridden by an NXtransformations field pointed to by a depends_on attribute. The last component, describing the circular polarization state, is positive for a right-hand circular state - that is the electric field vector rotates clockwise at the sample and over time when observed from the source. I (S_0) is the beam intensity (often normalized to 1). Q, U, and V scale linearly with the total degree of polarization, and indicate the relative magnitudes of the pure linear and circular orientation contributions. Q (S_1) is linearly polarized along the x axis (Q > 0) or y axis (Q < 0). U (S_2) is linearly polarized along the x==y axis (U > 0) or the -x==y axis (U < 0). V (S_3) is circularly polarized. V > 0 when the electric field vector rotates clockwise at the sample with respect to time when observed from the source; V < 0 indicates the opposite rotation. Polarization vector on leaving beamline component using Stokes notation (see incident_polarization_stokes). Wavelength spread FWHM of beam leaving this component Divergence FWHM of beam leaving this component flux incident on beam plane area Energy of a single pulse at the given location. Average power at the at the given location. Incident energy fluence at the given location. FWHM duration of the pulses at the given location. Delay time between two pulses of a pulsed beam. A reference to the beam in relation to which the delay is. This should be the path to another instance of ``NXbeam``. The use of this attribute should be similar to that of the :ref:`depends_on attribute </NXtransformations/AXISNAME@depends_on-attribute>`. in NXtransformations. FROG (frequency-resolved optical gating) trace of the pulse. This is to be used for ultrashort laser pulses in a FROG (frequency-resolved optical gating) setup. Horizontal axis of a FROG trace, i.e. delay. This is to be used for ultrashort laser pulses in a FROG (frequency-resolved optical gating) setup. Vertical axis of a FROG trace, i.e. frequency. This is to be used for ultrashort laser pulses in a FROG (frequency-resolved optical gating) setup. The type of chirp implemented Group delay dispersion of the pulse for linear chirp Distribution of beam with respect to relevant variable e.g. wavelength. This is mainly useful for simulations which need to store plottable information at each beamline component. The NeXus coordinate system defines the Z axis to be along the nominal beam direction. This is the same as the McStas coordinate system (see :ref:`Design-CoordinateSystem`). However, the additional transformations needed to represent an altered beam direction can be provided using this depends_on field that contains the path to a NXtransformations group. This could represent redirection of the beam, or a refined beam direction. Direction (and location) for the beam. The location of the beam can be given by any point which it passes through as its offset attribute. Direction of beam vector, its value is ignored. If missing, then the beam direction is defined as [0,0,1] and passes through the origin. Note, this field should be referenced by the parent group's ``depends_on`` field; also, as this field is a direction, its ``transformation_type`` attribute should be omitted. Three values that define the direction of beam vector Three values that define the location of a point through which the beam passes Points to the path to a field defining the location on which this depends or the string "." for origin. Direction of normal to reference plane used to measure azimuth relative to the beam, its value is ignored. This also defines the parallel and perpendicular components of the beam's polarization. If missing, then the reference plane normal is defined as [0,1,0]. Note, as this field is a direction, its ``transformation_type`` attribute should be omitted. Three values that define the direction of reference plane normal Points to the path to a field defining the location on which this depends or the string "." for origin. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXbeam_stop.nxdl.xml0000644000077000000000000000710514777236751026474 0ustar00rosborn A device that blocks the beam completely, usually to protect a detector. Beamstops and their positions are important for SANS and SAXS experiments. engineering shape, orientation and position of the beam stop. description of beamstop This group describes the shape of the beam line component This group is an alternative to NXoff_geometry for describing the shape of the beam stop. Size of beamstop. If this is not sufficient to describe the beam stop use NXoff_geometry instead. x position of the beamstop in relation to the detector. Note, it is recommended to use NXtransformations instead. y position of the beamstop in relation to the detector. Note, it is recommended to use NXtransformations instead. distance of the beamstop to the detector. Note, it is recommended to use NXtransformations instead. The reference point of the beam stop is its center in the x and y axis. The reference point on the z axis is the surface of the beam stop pointing towards the source. .. image:: beam_stop/beam_stop.png :width: 40% ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXbeam_transfer_matrix_table.nxdl.xml0000644000077000000000000001233715046415443032054 0ustar00rosborn Variables used throughout the document, e.g. dimensions or parameters. Length of the array associated to the data type. Contains data structures of an experimental optical setup (i.e., multiple transfer matrix tables). These data structures are used to relate physical properties of two beams (NXbeam) which have one common optical component (NXcomponent) (one specific transfer matrix). One of these beams is an input beam and the other one is an output beam. The data describes the change of beam properties, e.g. the intensity of a beam is reduced because the transmission coefficient of the beam device is lower than 1. Select which type of data was recorded, for example aperture and focal length. It is possible to have multiple selections. This selection defines how many columns (N_variables) are stored in the data array. N in the name, is the index number in which order the given property is listed. Please list in this array the column and row names used in your actual data. That is in the case of aperture ['diameter'] or focal length ['focal_length_value'] and for orientation matrix ['OM1', 'OM2', 'OM3'] or for jones matrix ['JM1','JM2'] Contains the datastructure which relates beam properties of an input and output beam as result of the input beam interaction with the beam device. Transfer matrix relationship between N input beams and M output beams. It contains a table with the relevant matrices to be used for different transmitted properties (such as polarization, intensity, phase). Data structure for all transfermatrices of a beam device in a setup. For each combination of N input and M output beams and for L physical concept (i.e. beam intensity), one matrix can be defined. In this way, the transfer matrix table has the dimension NxM. For each entry, in this transfer matrix, there are L formalisms. Each formalism has the dimension math:`dim(L_i)xdim(L_i)`, whereby math:`L_i` is the specific physical concept (Intensity, polarization, direction). A beamsplitter with two input laser beams can have a total of four transfermatrices (2 Input x 2 Output). The dimension of the transfer matrix depends on the parameters. Examples are: 1x1 for intensity/power 2x2 for jones formalism 3x3 for direction Specific name of input beam which the transfer matrix table is related to. Specific name of output beam which the transfer matrix table is related to. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXbending_magnet.nxdl.xml0000644000077000000000000000770114777236751027466 0ustar00rosborn A bending magnet strength of magnetic field of dipole magnets An array of four numbers giving X+, X-, Y+ and Y- half divergence Distance of source point from particle beam waist in X (horizontal) direction. Note, it is recommended to use NXtransformations instead to place component. Distance of source point from particle beam waist in Y (vertical) direction. Note, it is recommended to use NXtransformations instead to place component. Accepted photon beam divergence in X+ (horizontal outboard) direction. Note that divergence_x_plus+divergence_x_minus is the total horizontal beam divergence. Accepted photon beam divergence in X- (horizontal inboard) direction. Note that divergence_x_plus+divergence_x_minus is the total horizontal beam divergence. Accepted photon beam divergence in Y+ (vertical upward) direction. Note that divergence_y_plus+divergence_y_minus is the total vertical beam divergence. Accepted photon beam divergence in Y- (vertical downward) direction. Note that divergence_y_plus+divergence_y_minus is the total vertical beam divergence. bending magnet spectrum "Engineering" position of bending magnet This group describes the shape of the beam line component .. todo:: Add a definition for the reference point of a bending magnet. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXcalibration.nxdl.xml0000644000077000000000000002305615046415443027000 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays Number of points of the calibrated and uncalibrated axes Subclass of NXprocess to describe post-processing calibrations. A description of the procedures employed. The physical quantity of the calibration, e.g., energy, momentum, time, etc. A digital persistent identifier (e.g., DOI, ISO standard) referring to a detailed description of a calibration method but no actual calibration data. A digital persistent identifier (e.g., a DOI) referring to a publicly available calibration measurement used for this instrument, e.g., a measurement of a known standard containing calibration information. The axis values may be copied or linked in the appropriate NXcalibration fields for reference. A file serialization of a calibration which may not be publicly available (externally from the NeXus file). This metadata can be a documentation of the source (file) or database (entry) from which pieces of information have been extracted for consumption (e.g. in a research data management system (RDMS)). It is also possible to include the actual file by using the `file` field. The axis values may be copied or linked in the appropriate NXcalibration fields for reference. Indicates the name of the last operation applied in the NXprocess sequence. Has the calibration been applied? Array containing the data coordinates in the original uncalibrated axis The symbol of the axis to be used in the fit_function, e.g., `energy`, `E`. This should comply to the following naming rules (similar to python's naming rules): * A variable name must start with a letter or the underscore character * A variable name cannot start with a number * A variable name can only contain alpha-numeric characters and underscores (A-z, 0-9, and _ ) * Variable names are case-sensitive (age, Age and AGE are three different variables) The path from which this data is derived, e.g., raw detector axis. Should be a valid NeXus path name, e.g., /entry/instrument/detector/raw. Additional input axis to be used in the formula. The name of each ``PARAMETER`` is used as the symbol to be used in the ``fit_formula_description``, i.e., if the field name is `my_field` you should refer to this axis by `my_field` in the ``fit_formula_description``. The path from which this data is derived, e.g., raw detector axis. Should be a valid NeXus path name, e.g., /entry/instrument/detector/raw. Fit coefficients to be used in ``fit_formula_description``. As an example, for non-linear energy calibrations, e.g. in a time-of-flight (TOF) detector, a polynomial function is fitted to a set of features (peaks) at well defined energy positions to determine E(TOF). Here we can store the fit coefficients for that procedure. Use a0, a1, ..., an for the coefficients of a polynomial fit, corresponding to the values in the ``fit_formula_description``. For linear calibration. Scaling parameter. This should yield the relation `calibrated_axis` = (`original_axis` + `offset`) * `scaling_factor`. For a more detailed description of scaling factors, see :ref:`/NXdata/FIELDNAME_scaling_factor </NXdata/FIELDNAME_scaling_factor-field>`. For linear calibration. Offset parameter. This should yield the relation `calibrated_axis` = (`original_axis` + `offset`) * `scaling_factor`. For a more detailed description of offset, see :ref:`/NXdata/FIELDNAME_offset </NXdata/FIELDNAME_offset-field>`. Here we can store a description of the formula used for the fit function. For polynomial fits, use a0, a1, ..., an for the coefficients, corresponding to the values in the coefficients group. Use x0, x1, ..., xm for the mth position in the `original_axis` field. If there is the symbol attribute specified for the `original_axis` this may be used instead of x. If you want to use the whole axis use `x`. Alternate axis can also be available as specified by the `fit_formula_inputs` group. The data should then be referred here by the `SYMBOL` name, e.g., for a field name ``my_field`` in ``fit_formula_inputs``, it should be referred here by ``my_field`` or ``my_field0`` if you want to read the zeroth element of the array. Mapping data for calibration. This can be used to map data points from uncalibrated to calibrated values, i.e., by multiplying each point in the input axis by the corresponding point in the mapping data. An array representing the axis after calibration, matching the data length Any data acquired/used during the calibration that does not fit the `NX_FLOAT` fields above. NXdata groups can be used for multidimensional data which are relevant to the calibration .. index:: plotting Declares which child group contains a path leading to a :ref:`NXdata` group. It is recommended (as of NIAC2014) to use this attribute to help define the path to the default dataset to be plotted. See https://www.nexusformat.org/2014_How_to_find_default_data.html for a summary of the discussion. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXcapillary.nxdl.xml0000644000077000000000000000531014777236751026477 0ustar00rosborn A capillary lens to focus the X-ray beam. Based on information provided by Gerd Wellenreuther (DESY). Type of the capillary The manufacturer of the capillary. This is actually important as it may have an impact on performance. The gain of the capillary as a function of energy The transmission of the capillary as a function of energy The focal size in FWHM .. todo:: Add a definition for the reference point of a capillary lens. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXchemical_composition.nxdl.xml0000644000077000000000000001017115046415443030673 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The number of samples or things. Chemical composition of a sample or a set of things. Reporting compositions as atom and weight percent yields both dimensionless quantities but their conceptual interpretation differs. A normalization based on atom_percent counts relative to the total number of atoms which are of a particular type. By contrast, weight_percent normalization factorizes in the respective mass of the elements. Software libraries that work with units, like pint in Python, are challenged by these differences as at.-% and wt.-% are both fractional quantities. Total formula mass or number of atoms, depending on the normalization stated in the normalization field. If this group is used to report the composition of elements from the periodic table, the group should use the chemical symbol of that element. For other case the group name is unconstrained. Count or weight which, when divided by total yields the composition of this element, isotope, molecule, or ion. Composition value for the element/ion referred to under name. Composition is reported either normalized for atomic or weight percent. The field normalization should be used to communicate this explicitly. Composition should be reported consistently for all instances ELEMENT. Magnitude of the standard deviation of the composition. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXcircuit.nxdl.xml0000644000077000000000000001362115046415443026150 0ustar00rosborn Base class for documenting circuit devices. Electronic circuits are hardware components that connect several electronic components to achieve specific functionality, e.g. amplifying a voltage or convert a voltage to binary numbers, etc. Hardware where the circuit is implanted; includes information about the hardware manufacturers and type (e.g. part number) All the elements below may be single numbers of an array of values with length N_channel describing multiple input and output channels. List of components used in the circuit, e.g., resistors, capacitors, transistors or any other complex components. Description of how components are interconnected, including connection points and wiring. Details of the power source for the circuit, including voltage and current ratings. Type of signal (input signal) the circuit is designed to handle, e.g., analog, digital, mixed-signal. The operating frequency of the circuit, see also bandwidth, which is possibly but not necessarily centered around this frequency (e.g. running a 100 kHz bandwidth amplifier at low, audio frequencies 1 - 20,000 Hz). The bandwidth of the frequency response of the circuit. Input impedance of the circuit. Output impedance of the circuit. Gain of the circuit, if applicable, usually all instruments have a gain which might be important or not. Root-mean-square (RMS) noise level (in current or voltage) in the circuit in voltage or current. Operating temperature range of the circuit. Calibration data for the circuit. Offset value for current or voltage. Number of output channels connected to this circuit. Most probably N_channel. Type of output signal, e.g., voltage, current, digital. Power consumption of the circuit per unit time. Status indicators for the circuit, e.g., LEDs, display readouts. Protection features built into the circuit, e.g., overvoltage protection, thermal shutdown. Updated rate for several processes using the input signal, e.g., History Graph, the circuit uses for any such process. The rate at which the signal changes when ramping from the starting value. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXcite.nxdl.xml0000644000077000000000000000441214777236751025445 0ustar00rosborn A literature reference Definition to include references for example for detectors, manuals, instruments, acquisition or analysis software used. The idea would be to include this in the relevant NeXus object: :ref:`NXdetector` for detectors, :ref:`NXinstrument` for instruments, etc. This should describe the reason for including this reference. For example: The dataset in this group was normalised using the method which is described in detail in this reference. URL referencing the document or data. DOI referencing the document or data. Bibliographic reference data in EndNote format. Bibliographic reference data in BibTeX format. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXcollection.nxdl.xml0000644000077000000000000000533414777236751026660 0ustar00rosborn An unvalidated set of terms, such as the description of a beam line. Use :ref:`NXcollection` to gather together any set of terms. The original suggestion is to use this as a container class for the description of a beamline. For NeXus validation, :ref:`NXcollection` will always generate a warning since it is always an optional group. Anything (groups, fields, or attributes) placed in an :ref:`NXcollection` group will not be validated. .. admonition:: NXcollection content is not validated. :ref:`NXcollection` is and will always be for unvalidated content. Any and all content within a :ref:`NXcollection` group specified by an application definition cannot be validated. It is suggested to use a :ref:`NXparameters` group for similar content which should be validated. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXcollectioncolumn.nxdl.xml0000644000077000000000000000740615046415443030063 0ustar00rosborn Electron collection column of an electron analyzer. Scheme of the electron collection lens, i.e. angular dispersive, spatial dispersive, momentum dispersive, non-dispersive, etc. Voltage applied to the extractor lens Current necessary to keep the extractor lens at a set voltage. Variations indicate leakage, field emission or arc currents to the extractor lens. Distance between sample and detector entrance Labelling of the lens setting in use. The space projected in the angularly dispersive directions, real or reciprocal Acceptance angle of the collection column. This concept is related to term `7.4`_ of the ISO 18115-1:2023 standard. .. _7.4: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:7.4 Acceptance length or area of the collection column. The magnification of the electron lens assembly. The size and position of an aperture inserted in the column, e.g. field aperture or contrast aperture Deflectors in the collection column section Individual lenses in the collection column section ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXcollimator.nxdl.xml0000644000077000000000000000707414777236751026675 0ustar00rosborn A beamline collimator. position, shape and size Angular divergence of Soller collimator divergence of collimator in local x direction divergence of collimator in local y direction Frequency of oscillating collimator Log of frequency blade thickness blade spacing name of absorbing material name of transmitting material This group describes the shape of the beam line component Assuming a collimator with a "flat" entry surface, the reference plane is the plane which contains this surface. The reference point of the collimator in the x and y axis is the centre of the collimator entry surface on that plane. The reference plane is orthogonal to the z axis and the location of this plane is the reference point on the z axis. The collimator faces negative z values. .. image:: collimator/collimator.png :width: 40% ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXcomponent.nxdl.xml0000644000077000000000000001015115046415443026503 0ustar00rosborn Base class for components of an instrument - real ones or simulated ones. Was the component used? Name of the component. Ideally, use instances of ``identifierNAME`` to point to a resource that provides further details. If such a resource does not exist or should not be used, use this free text, although it is not recommended. Instance or list of instances of ``NXcomponent`` (or base classes extending ``NXcomponent``) or ``NXbeam`` that act as input(s) to this component. Each input should point to the path of the group acting as input. An example usage would be to chain components and/or beams together to describe the beam path in an experiment. Instance or list of instances of ``NXcomponent`` (or base classes extending ``NXcomponent``) or ``NXbeam`` that act as output(s) of this component. For more information, see :ref:`inputs </NXcomponent/inputs-field>`. Specifies the position of the component by pointing to the last transformation in the transformation chain that is defined via the NXtransformations group. NeXus positions components by applying a set of translations and rotations to the component starting from 0, 0, 0. The order of these operations is critical and forms what NeXus calls a dependency chain. The depends_on field defines the path to the top most operation of the dependency chain or the string "." if located in the origin. The depends_on can also point to an instance of ``NX_coordinate_system`` if the transformations of the component depend on that coordinate system. Usually these operations are stored in a NXtransformations group. But NeXus allows them to be stored anywhere. Collection of axis-based translations and rotations to describe the location and geometry of the component in the instrument. The dependency chain may however traverse similar groups in other component groups. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXcoordinate_system.nxdl.xml0000644000077000000000000002665715046415443030256 0ustar00rosborn Base class to detail a coordinate system (CS). Instances of ``NXcoordinate_system`` can be used to describe coordinate systems other than the default `NeXus coordinate system <https://manual.nexusformat.org/design.html#the-nexus-coordinate-system>`_. Whenever possible, all instances of :ref:`NXcoordinate_system` should be used at the top-level (i.e, directly below ``NXentry``) within an application definition or within a NeXus file. ``NXcoordinate_system`` can be part of the transformations chain using :ref:`NXtransformations`, where it acts as a linear change-of-basis transformation (using a 3x3 matrix with the basis vectors ``x``, `y``, and ``z`` as columns). Any group that has an optional ``depends_on`` field or any field that has an optional ``depends_on`` attribute has a fallback when ``depends_on`` is not provided. The fallback behavior involves traversing up the hierarchy until the first ancestor that contains one and only one ``NXcoordinate_system`` group is found. If such an ancestor exists, its coordinate system applies. If none is found or more than one instance of ``NXcoordinate_system`` is found at the same level, then the current coordinate system is not defined with respect to anything else. As an example, if there is only one ``NXcoordinate_system`` called "my_coordinate_system" defined directly under ``NXentry``, each optional ``depends_on`` field/attribute that is not defined automatically defaults to ``depends_on=my_coordinate_system``. How many groups of type ``NXcoordinate_system`` should be used in an application definition? * 0; if there is no instance of ``NXcoordinate_system`` across the entire tree, you can use ``depends_on="."`` to state that this transformation depends on the default `NeXus coordinate system <https://manual.nexusformat.org/design.html#the-nexus-coordinate-system>`_ (which is the same as the one used by `McStas <https://mcstas.org/>`_). For the sake of clarity, even in this case it is better to be explicit and consistent for every other coordinate system definition to support users with interpreting the content and logic behind every instance of the tree. The default NeXus coordinate system (i.e., the McStas coordinate system) can be expressed as follows: .. code-block:: mcstas@NXcoordinate_system x = [1, 0, 0] y = [0, 1, 0] z = [0, 0, 1] @y_direction = "opposite to gravity" @z_direction = "direction of the primary beam" Note that this assumes that the direction of the beam is not defined in the ``NXbeam`` instance. * 1; if only one :ref:`NXcoordinate_system` is defined, it should be placed as high up in the tree hierarchy (ideally right below an instance of NXentry) of the application definition tree as possible. This coordinate system shall be named such that it is clear how this coordinate system is typically referred to in a community. For the NeXus McStas coordinate system, it is advised to call it ``mcstas`` for the sake of improved clarity. If this is the case, it is assumed that this ``NXcoordinate_system`` overwrites the NeXus default McStas coordinate system, i.e. users can thereby conveniently and explicitly specify the coordinate system that they wish to use. This case has the advantage that it is explicit and offers no ambiguities. However, in reality typically multiple coordinate systems have to be mastered especially for complex multi-signal modality experiments. If this case is realized, the best practice is that in every case where this coordinate system should be referred to the respective group has a ``depends_on`` field, to clearly indicate which specific coordinate systems is referred to. * 2 and more; as soon as more than one :ref:`NXcoordinate_system` is specified somewhere in the tree, different interpretations are possible as to which of these coordinate systems apply or take preference. While these ambiguities should be avoided if possible, the opportunity for multiples instances enables to have coordinate system conventions that are specific for some part of the NeXus tree. This is especially useful for deep groups where multiple scientific methods are combined or cases where having a definition of global conversion tables how to convert between representations in different coordinate systems is not desired or available for now. To resolve the possible ambiguities which specific coordinate systems in an :ref:`NXtransformations` train is referred to, it is even more important to use the ``depends_on`` field in groups and the ``depends_on`` attribute in NXtransformations to refer to one of the ``NXcoordinate_system`` instances. In the case of two or more instances of ``NXcoordinate_system`` it is advised to specify the relationship between the two coordinate systems by using the :ref:`NXtransformations` group within ``NXcoordinate_system``. In any case, users are encouraged to write explicit and clean ``depends_on`` fields in all groups that encode information for which the interpretation of coordinate systems and transformations is relevant. If these ``depends_on`` instances are not provided or no instance of ``NX_coordinate_system`` exists in the upper part of the hierarchy, the application definition is considered underconstrained. Note that this is the case for all files that were created before ``NXcoordinate_system`` was added. Human-readable field describing where the origin of this CS is. Exemplar values could be *left corner of the lab bench*, *door handle* *pinhole through which the electron beam exits the pole piece*, *barycenter of the triangle*, *center of mass of the stone*. Coordinate system type. Opportunity to define an alias for the name of the x-axis. Human-readable field telling in which direction the x-axis points if that instance of :ref:`NXcoordinate_system` has no reference to any parent and as such is the world reference frame. Exemplar values could be direction of gravity. Basis unit vector along the first axis which spans the coordinate system. This axis is frequently referred to as the x-axis in Euclidean space and the i-axis in reciprocal space. Note that `x``, ``y``, and ``z`` must constitute a basis, i.e., a set of linearly independent vectors that span the vector space. Opportunity to define an alias for the name of the y-axis. Human-readable field telling in which direction the y-axis points if that instance of :ref:`NXcoordinate_system` has no reference to any parent and as such is the mighty world reference frame. See docstring of ``x_direction`` for further details. Basis unit vector along the second axis which spans the coordinate system. This axis is frequently referred to as the y-axis in Euclidean space and the j-axis in reciprocal space. Opportunity to define an alias for the name of the z-axis. Human-readable field telling in which direction the z-axis points if that instance of :ref:`NXcoordinate_system` has no reference to any parent and as such is the mighty world reference frame. See docstring of x_alias for further details. Basis unit vector along the third axis which spans the coordinate system. This axis is frequently referred to as the z-axis in Euclidean space and the k-axis in reciprocal space. This specifies the relation to another coordinate system by pointing to the last transformation in the transformation chain in the NXtransformations group. Collection of axis-based translations and rotations to describe this coordinate system with respect to another coordinate system. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXcrystal.nxdl.xml0000644000077000000000000003346314777236751026212 0ustar00rosborn These symbols will be used below to coordinate dimensions with the same lengths. number of different unit cells to be described number of wavelengths A crystal monochromator or analyzer. Permits double bent monochromator comprised of multiple segments with anisotropic Gaussian mosaic. If curvatures are set to zero or are absent, array is considered to be flat. Scattering vector is perpendicular to surface. Crystal is oriented parallel to beam incident on crystal before rotation, and lies in vertical plane. Position of crystal How this crystal is used. Choices are in the list. reflection geometry The chemical formula specified using CIF conventions. Abbreviated version of CIF standard: * Only recognized element symbols may be used. * Each element symbol is followed by a 'count' number. A count of '1' may be omitted. * A space or parenthesis must separate each cluster of (element symbol + count). * Where a group of elements is enclosed in parentheses, the multiplier for the group must follow the closing parentheses. That is, all element and group multipliers are assumed to be printed as subscripted numbers. * Unless the elements are ordered in a manner that corresponds to their chemical structure, the order of the elements within any group or moiety depends on whether or not carbon is present. * If carbon is present, the order should be: C, then H, then the other elements in alphabetical order of their symbol. If carbon is not present, the elements are listed purely in alphabetic order of their symbol. This is the *Hill* system used by Chemical Abstracts. See, for example: http://www.iucr.org/__data/iucr/cif/standard/cifstd15.html or http://www.cas.org/training/stneasytips/subinforformula1.html. Type or material of monochromating substance. Chemical formula can be specified separately. Use the "reflection" field to indicate the (hkl) orientation. Use the "d_spacing" field to record the lattice plane spacing. This field was changed (2010-11-17) from an enumeration to a string since common usage showed a wider variety of use than a simple list. These are the items in the list at the time of the change: PG (Highly Oriented Pyrolytic Graphite) | Ge | Si | Cu | Fe3Si | CoFe | Cu2MnAl (Heusler) | Multilayer | Diamond. The chemical formula specified using CIF conventions. Abbreviated version of CIF standard: * Only recognized element symbols may be used. * Each element symbol is followed by a 'count' number. A count of '1' may be omitted. * A space or parenthesis must separate each cluster of (element symbol + count). * Where a group of elements is enclosed in parentheses, the multiplier for the group must follow the closing parentheses. That is, all element and group multipliers are assumed to be printed as subscripted numbers. * Unless the elements are ordered in a manner that corresponds to their chemical structure, the order of the elements within any group or moiety depends on whether or not carbon is present. * If carbon is present, the order should be: C, then H, then the other elements in alphabetical order of their symbol. If carbon is not present, the elements are listed purely in alphabetic order of their symbol. * This is the *Hill* system used by Chemical Abstracts. A number which describes if this is the first, second,.. :math:`n^{th}` crystal in a multi crystal monochromator Cut angle of reflecting Bragg plane and plane of crystal surface Space group of crystal structure Unit cell parameters (lengths and angles) Unit cell lattice parameter: length of side a Unit cell lattice parameter: length of side b Unit cell lattice parameter: length of side c Unit cell lattice parameter: angle alpha Unit cell lattice parameter: angle beta Unit cell lattice parameter: angle gamma Volume of the unit cell Orientation matrix of single crystal sample using Busing-Levy convention: W. R. Busing and H. A. Levy (1967). Acta Cryst. 22, 457-464 Optimum diffracted wavelength spacing between crystal planes of the reflection Scattering vector, Q, of nominal reflection Miller indices (hkl) values of nominal reflection Thickness of the crystal. (Required for Laue orientations - see "usage" field) mass density of the crystal Horizontal width of individual segment Vertical height of individual segment Thickness of individual segment Typical gap between adjacent segments number of segment columns in horizontal direction number of segment rows in vertical direction horizontal mosaic Full Width Half Maximum vertical mosaic Full Width Half Maximum Horizontal curvature of focusing crystal Vertical curvature of focusing crystal Is this crystal bent cylindrically? If cylindrical: cylinder orientation angle Polar (scattering) angle at which crystal assembly is positioned. Note: some instrument geometries call this term 2theta. Note: it is recommended to use NXtransformations instead. Azimuthal angle at which crystal assembly is positioned. Note: it is recommended to use NXtransformations instead. Bragg angle of nominal reflection average/nominal crystal temperature how lattice parameter changes with temperature log file of crystal temperature crystal reflectivity versus wavelength crystal transmission versus wavelength A NXshape group describing the shape of the crystal arrangement This group describes the shape of the beam line component .. todo:: Add a definition for the reference point of a crystal. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXcs_computer.nxdl.xml0000644000077000000000000000571615046415443027037 0ustar00rosborn Base class for reporting the description of a computer Given name/alias to the computing system, e.g. MyDesktop. Name of the operating system, e.g. Windows, Linux, Mac, Android. Version plus build number, commit hash, or description of an ever persistent resource where the source code of the program and build instructions can be found so that the program can be configured in such a manner that the result file is ideally recreatable yielding the same results. A globally unique persistent identifier of the computer, i.e. the Universally Unique Identifier (UUID) of the computing node. Multiple instances should be named processor1, processor2, etc. Multiple instances should be named memory1, memory2, etc. Multiple instances should be named storage1, storage2, etc. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXcs_filter_boolean_mask.nxdl.xml0000644000077000000000000000717215046415443031176 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Number of entries (e.g. number of points or objects). Number of bits assumed for the container datatype used. Length of mask considering the eventual need for padding. Base class for packing and unpacking booleans. The field mask should be constructed from packing a vector of booleans (a bitfield) into unsigned integers with bytesize bitdepth. Padding to an integer number of such integers is assumed. Thereby, this base class can be used to inform software about necessary modulo operations to decode the mask to recover e.g. set membership of objects in sets whose membership has been encoded as a vector of booleans. This is useful e.g. when processing object sets such as point cloud data. If e.g. a spatial filter has been applied to a set of points, we may wish to document memory-space efficiently which points were analyzed. An array of boolean values is one option to achieve this. A value is true if the point is included and false otherwise. Possibility to refer to which set this mask applies. If depends_on is not provided, it is assumed that the mask applies to its direct parent. Number of objects represented by the mask. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The content of the mask. If padding is used, padding bits have to be set to 0. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXcs_memory.nxdl.xml0000644000077000000000000000375315046415443026510 0ustar00rosborn Base class for reporting the description of the memory system of a computer. Typically, computers have multiple instances of memory. Qualifier for the type of random access memory. Total amount of data which the medium can hold. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXcs_prng.nxdl.xml0000644000077000000000000000771215046415443026145 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Computer science description of pseudo-random number generator. The purpose of this base class is to identify if exactly the same sequence can be reproduced, like for a PRNG or not, like for a true physically random source. Physical approach or algorithm whereby random numbers are generated. Different approaches for generating random numbers with a computer exists. Some use a dedicated physical device whose the state is unpredictable physically. Some use a strategy of mangling information from the system clock. Also in this case the sequence is not reproducible without having additional pieces of information. In most cases though so-called pseudo-random number generator (PRNG) algorithms are used. These yield a deterministic sequence of practically randomly appearing numbers. These algorithms differ in their quality in how random the resulting sequences actually are, i.e. sequentially uncorrelated. Nowadays one of the most commonly used algorithm is the MersenneTwister (mt19937). Name of the PRNG implementation and version. If such information is not available or if the PRNG type was set to other the DOI to the publication or the source code should be given. Parameter of the PRNG controlling its initialization and thus controlling the specific sequence generated. Number of initial draws from the PRNG after its initialized with the seed. These initial draws are typically discarded in an effort to equilibrate the sequence. If no warmup was performed or if warmup procedures are unclear, users should set the value to zero. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXcs_processor.nxdl.xml0000644000077000000000000000546215046415443027216 0ustar00rosborn Base class for reporting the description of processing units of a computer. Examples are e.g. classical so-called central processing units (CPUs), coprocessors, graphic cards, accelerator processing units or a system of these. Typical examples for the granularization of processing units are: * A desktop computer with a single CPU; describe using one instance of NXcircuit. * A dual-socket server; describe using two instances of NXcircuit. * A server with two dual-socket server nodes; describe with four instances of NXcircuit surplus a field that defines their level in the hierarchy. General type of the processing unit e.g. * pu, processing core or hyper-threading core * cpu, (multi-)core central processing unit * gpu, (multi-)core general purpose processing unit * fpga, field programmable gate array Clock speed of the circuit ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXcs_profiling.nxdl.xml0000644000077000000000000001674715046415443027200 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Computer science description for performance and profiling data of an application. Performance monitoring and benchmarking of software is a task where questions can be asked at various levels of detail. In general, there are three main contributions to performance: * Hardware capabilities and configuration * Software configuration and capabilities * Dynamic effects of the system in operation and the system working together with eventually multiple computers, especially when these have to exchange information across a network and these are used usually by multiple users. At the most basic level users may wish to document how long e.g. a data analysis with a scientific software i.e. an app took. A frequent idea is here to answer practical questions like how critical is the effect on the workflow of the scientists, i.e. is the analysis possible in a few seconds or would it take days if I were to run this analysis on a comparable machine? For this more qualitative performance monitoring, mainly the order of magnitude is relevant, as well as how this was achieved using parallelization (i.e. reporting the number of CPU and GPU resources used, the number of processes and threads configured, and providing basic details about the computer). At more advanced levels benchmarks may go as deep as detailed temporal tracking of individual processor instructions, their relation to other instructions, the state of call stacks; in short eventually the entire app execution history and hardware state history. Such analyses are mainly used for performance optimization, i.e. by software and hardware developers as well as for tracking bugs. Specialized software exists which documents such performance data in specifically-formatted event log files or databases. This base class cannot and should not replace these specific solutions for now. Instead, the intention of the base class is to serve scientists at the basic level to enable simple monitoring of performance data and log profiling data of key algorithmic steps or parts of computational workflows, so that these pieces of information can guide users which order of magnitude differences should be expected or not. Developers of application definitions should add additional fields and references to e.g. more detailed performance data to which they wish to link the metadata in this base class. Path to the directory from which the tool was called. Command line call with arguments if applicable. ISO 8601 time code with local time zone offset to UTC information included when the app was started. ISO 8601 time code with local time zone offset to UTC information included when the app terminated or crashed. Wall-clock time how long the app execution took. This may be in principle end_time minus start_time; however usage of eventually more precise timers may warrant to use a finer temporal discretization, and thus demands a more precise record of the wall-clock time. The number of nominal processes that the app invoked at runtime. The main idea behind this field e.g. for apps which use e.g. MPI (Message Passing Interface) parallelization is to communicate how many processes were used. For sequentially running apps number_of_processes and number_of_threads is one. If the app exclusively uses GPU parallelization, number_of_gpus can be larger than one. If no GPU is used, number_of_gpus is zero, even though the hardware may have GPUs installed. The number of nominal threads that the app invoked at runtime. Specifically here the maximum number of threads used for the high-level threading library used (e.g. OMP_NUM_THREADS), posix. The number of nominal GPUs that the app invoked at runtime. A collection with one or more computing nodes each with own resources. This can be as simple as a laptop or the nodes of a cluster computer. A collection of individual profiling event data which detail e.g. how much time the app took for certain computational steps and/or how much memory was consumed during these operations. ID is an increasing unsigned integer starting at 1. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXcs_profiling_event.nxdl.xml0000644000077000000000000001115015046415443030360 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Number of processes. Computer science description of a profiling event. ISO 8601 time code with local time zone offset to UTC information included when the event tracking started. ISO 8601 time code with local time zone offset to UTC information included when the event tracking ended. Free-text description what was monitored/executed during the event. Wall-clock time how long the event took. This may be in principle end_time minus start_time; however usage of eventually more precise timers may warrant to use a finer temporal discretization, and thus demand for a more precise record of the wall-clock time. Elapsed time may contain time portions where resources were idling. The number of nominal processes that the app invoked during the execution of this event. The main idea behind this field e.g. for apps which use e.g. MPI (Message Passing Interface) parallelization is to communicate how many processes were used. For sequentially running apps number_of_processes and number_of_threads is one. If the app exclusively uses GPU parallelization, number_of_gpus can be larger than one. If no GPU is used, number_of_gpus is zero, even though the hardware may have GPUs installed. The number of nominal threads that the app invoked at during the execution of this event. Specifically here the maximum number of threads used for the high-level threading library used (e.g. OMP_NUM_THREADS), posix. The number of nominal GPUs that the app invoked during the execution of this event. Maximum amount of virtual memory allocated per process during the event. Maximum amount of resident memory allocated per process during the event. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXcs_storage.nxdl.xml0000644000077000000000000000447415046415443026645 0ustar00rosborn Base class for reporting the description of the I/O of a computer. Qualifier for the type of storage medium used. Total amount of data which the medium can hold. Maximum read rate of the storage medium. Maximum write rate of the storage medium. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXcylindrical_geometry.nxdl.xml0000644000077000000000000000663314777236751030740 0ustar00rosborn These symbols will be used below. number of vertices required to define all cylinders in the shape number of cylinders in the shape number cylinders which are detectors Geometry description for cylindrical shapes. This class can be used in place of ``NXoff_geometry`` when an exact representation for cylinders is preferred. For example, for Helium-tube, neutron detectors. It can be used to describe the shape of any component, including detectors. In the case of detectors it can be used to define the shape of a single pixel, or, if the pixel shapes are non-uniform, to describe the shape of the whole detector. List of x,y,z coordinates for vertices. The origin of the coordinates is the position of the parent component, for example the NXdetector which the geometry describes. If the shape describes a single pixel for a detector with uniform pixel shape then the origin is the position of each pixel as described by the ``x/y/z_pixel_offset`` datasets in ``NXdetector``. List of indices of vertices in the ``vertices`` dataset to form each cylinder. Each cylinder is described by three vertices A, B, C. First vertex A lies on the cylinder axis and circular face, second point B on edge of the same face as A, and third point C at the other face and on axis. Maps cylinders in ``cylinder``, by index, with a detector id. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXdata.nxdl.xml0000644000077000000000000005376114777236751025445 0ustar00rosborn These symbols will be used below to coordinate fields with the same shape. rank of the ``DATA`` field(s) length of the ``x`` field length of the ``y`` field length of the ``z`` field The :ref:`NXdata` class is designed to encapsulate all the information required for a set of data to be plotted. NXdata groups contain plottable data (also referred to as *signals* or *dependent variables*) and their associated axis coordinates (also referred to as *axes* or *independent variables*). The actual names of the :ref:`DATA </NXdata/DATA-field>` and :ref:`AXISNAME </NXdata/AXISNAME-field>` fields can be chosen :ref:`freely <validItemName>`, as indicated by the upper case (this is a common convention in all NeXus classes). .. note:: ``NXdata`` provides data and coordinates to be plotted but does not describe how the data is to be plotted or even the dimensionality of the plot. https://www.nexusformat.org/NIAC2018Minutes.html#nxdata-plottype--attribute .. include:: data/index.rst :start-line: 1 .. admonition:: Example of a simple curve plot .. code-block:: data:NXdata @signal = "data" @axes = ["x"] data: float[100] x: float[100] More complex cases are supported * histogram data: ``x`` has one more value than ``data``. * alternative axes: instead of a single ``x`` axis you can have several axes, one of which being the default. * signals with more than one dimension: ``data`` could be 2D with axes ``x`` and ``y`` along each dimension. * axes with more than one dimension: ``data`` could be 2D with axes ``x`` and ``y`` also being 2D, providing a unique ``(x, y)`` coordinate for each ``data`` point. **Signals:** .. index:: plotting .. admonition:: Defined by * :ref:`DATA </NXdata/DATA-field>` fields * the :ref:`signal </NXdata@signal-attribute>` attribute * the :ref:`auxiliary_signals</NXdata@auxiliary_signals-attribute>` attribute The :ref:`DATA </NXdata/DATA-field>` fields contain the signal values to be plotted. The name of the field to be used as the *default plot signal* is provided by the :ref:`signal </NXdata@signal-attribute>` attribute. The names of the fields to be used as *secondary plot signals* are provided by the :ref:`auxiliary_signals</NXdata@auxiliary_signals-attribute>` attribute. .. admonition:: An example with three signals, one of which being the default .. code-block:: data:NXdata @signal = "data1" @auxiliary_signals = ["data2", "data3"] data1: float[10,20,30] # the default signal data2: float[10,20,30] data3: float[10,20,30] **Axes:** .. index:: axes (attribute) .. index:: coordinates .. admonition:: Defined by * :ref:`AXISNAME </NXdata/AXISNAME-field>` fields * the :ref:`axes </NXdata@axes-attribute>` attribute * :ref:`AXISNAME_indices </NXdata@AXISNAME_indices-attribute>` attributes The fields and attributes are defined as follows 1. The :ref:`AXISNAME </NXdata/AXISNAME-field>` fields contain the axis coordinates associated with the signal values. 2. The :ref:`axes </NXdata@axes-attribute>` attribute provides the names of the :ref:`AXISNAME </NXdata/AXISNAME-field>` fields to be used as the `default axis` for each dimension of the :ref:`DATA </NXdata/DATA-field>` fields. 3. The :ref:`AXISNAME_indices </NXdata@AXISNAME_indices-attribute>` attributes describe the :ref:`DATA </NXdata/DATA-field>` dimensions spanned by the corresponding :ref:`AXISNAME </NXdata/AXISNAME-field>` fields. The fields and attributes have the following constraints 1. The length of the :ref:`axes </NXdata@axes-attribute>` attribute must be equal to the rank of the :ref:`DATA </NXdata/DATA-field>` fields. When a particular dimension has no default axis, the string “.” is used in that position. 2. The number of values in :ref:`AXISNAME_indices </NXdata@AXISNAME_indices-attribute>` must be equal to the rank of the corresponding :ref:`AXISNAME </NXdata/AXISNAME-field>` field. 3. When :ref:`AXISNAME_indices </NXdata@AXISNAME_indices-attribute>` is missing for a given :ref:`AXISNAME </NXdata/AXISNAME-field>` field, the positions of the :ref:`AXISNAME </NXdata/AXISNAME-field>` field name in the :ref:`axes </NXdata@axes-attribute>` attribute are used. 4. When :ref:`AXISNAME_indices </NXdata@AXISNAME_indices-attribute>` is the same as the indices of "AXISNAME" in the :ref:`axes </NXdata@axes-attribute>` attribute, there is no need to provide :ref:`AXISNAME_indices </NXdata@AXISNAME_indices-attribute>`. 5. The indices of "AXISNAME" in the :ref:`axes </NXdata@axes-attribute>` attribute must be a subset of :ref:`AXISNAME_indices </NXdata@AXISNAME_indices-attribute>`. 6. The shape of an :ref:`AXISNAME </NXdata/AXISNAME-field>` field must correspond to the shape of the :ref:`DATA </NXdata/DATA-field>` dimensions it spans. This means that for each dimension ``i`` in ``[0, AXISNAME.ndim)`` spanned by axis field :ref:`AXISNAME </NXdata/AXISNAME-field>`, the number of axis values ``AXISNAME.shape[i]`` along dimension ``i`` must be equal to the number of data points ``DATA.shape[AXISNAME_indices[i]]`` along dimension ``i`` or one more than the number of data points ``DATA.shape[AXISNAME_indices[i]]+1`` in case the :ref:`AXISNAME </NXdata/AXISNAME-field>` field contains histogram bin edges along dimension ``i``. Highlight consequences of these constraints 1. An :ref:`AXISNAME </NXdata/AXISNAME-field>` field can have more than one dimension and can therefore span more than one :ref:`DATA </NXdata/DATA-field>` dimension. Conversely, one :ref:`DATA </NXdata/DATA-field>` dimension can be spanned by more than one :ref:`AXISNAME </NXdata/AXISNAME-field>` field. The default axis name (if any) of each dimension can be found in the :ref:`axes </NXdata@axes-attribute>` attribute. 2. A list of all available axes is not provided directly. All strings in the :ref:`axes </NXdata@axes-attribute>` attribute (excluding the “.” string) are axis field names. In addition the prefix of an attribute ending with the string "_indices" is also an axis field name. .. admonition:: The following example covers all axes features supported (see :ref:`sphx_glr_classes_base_classes_data_plot_fscan2d.py`) .. code-block:: data:NXdata @signal = "data" @axes = ["x_set", "y_set", "."] # default axes for all three dimensions @x_encoder_indices = [0, 1] @y_encoder_indices = 1 # or [1] data: float[10,7,1024] x_encoder: float[11,7] # coordinates along the first and second dimensions y_encoder: float[7] # coordinates along the second dimension x_set: float[10] # default coordinates along the first dimension y_set: float[7] # default coordinates along the second dimension **Uncertainties:** .. admonition:: Defined by * :ref:`FIELDNAME_errors </NXdata/FIELDNAME_errors-field>` fields Standard deviations on data values as well as coordinates can be provided by :ref:`FIELDNAME_errors </NXdata/FIELDNAME_errors-field>` fields where ``FIELDNAME`` is the name of a :ref:`DATA </NXdata/DATA-field>` field or an :ref:`AXISNAME </NXdata/AXISNAME-field>` field. .. admonition:: An example of uncertainties on the signal, auxiliary signals and axis coordinates .. code-block:: data:NXdata @signal = "data1" @auxiliary_signals = ["data2", "data3"] @axes = ["x", ".", "z"] data1: float[10,20,30] data2: float[10,20,30] data3: float[10,20,30] x: float[10] z: float[30] data1_errors: float[10,20,30] data2_errors: float[10,20,30] data3_errors: float[10,20,30] x_errors: float[10] z_errors: float[30] .. index:: find the default plottable data .. index:: plotting .. index:: signal attribute value The value is the :ref:`name <validItemName>` of the signal that contains the default plottable data. This field or link *must* exist and be a direct child of this NXdata group. It is recommended (as of NIAC2014) to use this attribute rather than adding a signal attribute to the field. See https://www.nexusformat.org/2014_How_to_find_default_data.html for a summary of the discussion. .. index:: plotting Array of strings holding the :ref:`names <validItemName>` of additional signals to be plotted with the :ref:`default signal </NXdata@signal-attribute>`. These fields or links *must* exist and be direct children of this NXdata group. Each auxiliary signal needs to be of the same shape as the default signal. .. NIAC2018: https://www.nexusformat.org/NIAC2018Minutes.html Which slice of data to show in a plot by default. This is useful especially for datasets with more than 2 dimensions. Should be an array of length equal to the number of dimensions in the data, with the following possible values: * ".": All the data in this dimension should be included * Integer: Only this slice should be used. * String: Only this slice should be used. Use if ``AXISNAME`` is a string array. Example:: data:NXdata @signal = "data" @axes = ["image_id", "channel", ".", "."] @image_id_indices = 0 @channel_indices = 1 @default_slice = [".", "difference", ".", "."] image_id = [1, ..., nP] channel = ["threshold_1", "threshold_2", "difference"] data = uint[nP, nC, i, j] Here, a data array with four dimensions, including the number of images (nP) and number of channels (nC), specifies more dimensions than can be visualized with a 2D image viewer for a given image. Therefore the default_slice attribute specifies that the "difference" channel should be shown by default. Alternate version using an integer would look like this (note 2 is a string):: data:NXdata @signal = "data" @axes = ["image_id", "channel", ".", "."] @image_id_indices = 0 @channel_indices = 1 @default_slice = [".", "2", ".", "."] image_id = [1, ..., nP] channel = ["threshold_1", "threshold_2", "difference"] data = uint[nP, nC, i, j] The ``AXISNAME_indices`` attribute is a single integer or an array of integers that defines which :ref:`DATA </NXdata/DATA-field>` dimensions are spanned by the corresponding axis. The first dimension index is ``0`` (zero). The number of indices must be equal to the rank of the :ref:`AXISNAME </NXdata/AXISNAME-field>` field. When the ``AXISNAME_indices`` attribute is missing for a given :ref:`AXISNAME </NXdata/AXISNAME-field>` field, its value becomes the index (or indices) of the :ref:`AXISNAME </NXdata/AXISNAME-field>` name in the :ref:`axes </NXdata@axes-attribute>` attribute. .. note:: When ``AXISNAME_indices`` contains multiple integers, it must be saved as an actual array of integers and not a comma separated string. .. index:: plotting The ``axes`` attribute is a list of strings which are the names of the :ref:`AXISNAME </NXdata/AXISNAME-field>` fields to be used as the default axis along every :ref:`DATA </NXdata/DATA-field>` dimension. As a result the length must be equal to the rank of the :ref:`DATA </NXdata/DATA-field>` fields. The string "." can be used for dimensions without a default axis. .. note:: When ``axes`` contains multiple strings, it must be saved as an actual array of strings and not a single comma separated string. Coordinate values along one or more :ref:`DATA </NXdata/DATA-field>` dimensions. The shape of an ``AXISNAME`` field must correspond to the shape of the :ref:`DATA </NXdata/DATA-field>` dimensions it spans. This means that for each ``i`` in ``[0, AXISNAME.ndim)`` the number of data points ``DATA.shape[AXISNAME_indices[i]]`` must be equal to the number of coordinates ``AXISNAME.shape[i]`` or the number of bin edges ``AXISNAME.shape[i]+1`` in case of histogram data. As the upper case ``AXISNAME`` indicates, the names of the ``AXISNAME`` fields can be chosen :ref:`freely <validItemName>`. Most ``AXISNAME`` fields will be sequences of numbers but if an axis is better represented using names, such as channel names, an array of NX_CHAR can be provided. Axis label Unit in which the coordinate values are expressed. See the section :ref:`Design-Units` for more information. ``0|false``: single value, ``1|true``: multiple values Index of first good value Index of last good value Index (positive integer) identifying this specific set of numbers. N.B. The ``axis`` attribute is the old way of designating a link. Do not use the :ref:`axes </NXdata@axes-attribute>` attribute with the ``axis`` attribute. The :ref:`axes </NXdata@axes-attribute>` attribute is now preferred. .. index:: plotting Data values to be used as the NeXus *plottable data*. As the upper case ``DATA`` indicates, the names of the ``DATA`` fields can be chosen :ref:`freely <validItemName>`. The :ref:`signal attribute </NXdata@signal-attribute>` and :ref:`auxiliary_signals attribute</NXdata@auxiliary_signals-attribute>` can be used to find all datasets in the ``NXdata`` that contain data values. The maximum rank is ``32`` for compatibility with backend file formats. The rank (``dataRank``) of the ``data`` must satisfy ``1 <= dataRank <= NX_MAXRANK=32``. .. index:: plotting Plottable (independent) axis, indicate index number. Only one field in a :ref:`NXdata` group may have the ``signal=1`` attribute. Do not use the ``signal`` attribute with the ``axis`` attribute. Defines the names of the coordinates (independent axes) for this data set as a colon-delimited array. NOTE: The :ref:`axes </NXdata@axes-attribute>` attribute is the preferred method of designating a link. Do not use the :ref:`axes </NXdata@axes-attribute>` attribute with the ``axis`` attribute. data label "Errors" (meaning *uncertainties* or *standard deviations*) associated with any field named ``FIELDNAME`` in this ``NXdata`` group. This can be a :ref:`DATA </NXdata/DATA-field>` field (signal or auxiliary signal) or a :ref:`AXISNAME </NXdata/AXISNAME-field>` field (axis). The dimensions of the ``FIELDNAME_errors`` field must match the dimensions of the corresponding ``FIELDNAME`` field. Standard deviations of data values - the data array is identified by the group attribute ``signal``. The ``errors`` array must have the same dimensions as ``DATA``. Client is responsible for defining the dimensions of the data. The ``errors`` must have the same rank (``dataRank``) as the ``data``. An optional scaling factor to apply to the values in any field named ``FIELDNAME`` in this ``NXdata`` group. This can be a :ref:`DATA </NXdata/DATA-field>` field (signal or auxiliary signal) or a :ref:`AXISNAME </NXdata/AXISNAME-field>` field (axis). The elements stored in NXdata datasets are often stored as integers for efficiency reasons and need further correction or conversion, generating floats. For example, raw values could be stored from a device that need to be converted to values that represent the physical values. The two fields FIELDNAME_scaling_factor and FIELDNAME_offset allow linear corrections using the following convention: .. code-block:: corrected values = (FIELDNAME + offset) * scaling_factor This formula will derive the values to use in downstream applications, when necessary. When omitted, the scaling factor is assumed to be 1. An optional offset to apply to the values in FIELDNAME (usually the signal). When omitted, the offset is assumed to be 0. See :ref:`FIELDNAME_scaling_factor </NXdata/FIELDNAME_scaling_factor-field>` for more information. The scaling_factor and FIELDNAME_scaling_factor fields have similar semantics. However, scaling_factor is ambiguous in the case of multiple signals. Therefore scaling_factor is deprecated. Use FIELDNAME_scaling_factor instead, even when only a single signal is present. The offset and FIELDNAME_offset fields have similar semantics. However, offset is ambiguous in the case of multiple signals. Therefore offset is deprecated. Use FIELDNAME_offset instead, even when only a single signal is present. Title for the plot. This is an array holding the values to use for the x-axis of data. The units must be appropriate for the measurement. This is a special case of a :ref:`AXISNAME field </NXdata/AXISNAME-field>` kept for backward compatiblity. This is an array holding the values to use for the y-axis of data. The units must be appropriate for the measurement. This is a special case of a :ref:`AXISNAME field </NXdata/AXISNAME-field>` kept for backward compatiblity. This is an array holding the values to use for the z-axis of data. The units must be appropriate for the measurement. This is a special case of a :ref:`AXISNAME field </NXdata/AXISNAME-field>` kept for backward compatiblity. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXdeflector.nxdl.xml0000644000077000000000000000560215046415443026455 0ustar00rosborn Component of an electron analyzer that deflects the paths of electrons. This includes electrostatic and electromagnetic deflectors. Qualitative type of deflector with respect to the number of pole pieces. Colloquial or short name for the deflector. For manufacturer names and identifiers use ``NXfabrication`` and ``identifierNAME``. Excitation voltage of the deflector. For dipoles it is a single number. For higher order multipoles, it is an array. Excitation current of the deflector. For dipoles it is a single number. For higher orders, it is an array. Spatial offset of the deflector in x direction (perpendicular to ```offset_y```). Spatial offset of the deflector in y direction (perpendicular to ```offset_x```). ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1748710342.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXdetector.nxdl.xml0000644000077000000000000010023415016631706026313 0ustar00rosborn These symbols will be used below to illustrate the coordination of the rank and sizes of datasets and the preferred ordering of the dimensions. Each of these are optional (so the rank of the datasets will vary according to the situation) and the general ordering principle is slowest to fastest. The type of each dimension should follow the order of scan points, detector output (e.g. pixels), then time-of-flight (i.e. spectroscopy, spectrometry). Note that the output of a detector is not limited to single values (0D), lists (1D) and images (2), but three or higher dimensional arrays can be produced by a detector at each trigger. number of scan points (only present in scanning measurements) number of detector pixels in the first (slowest) direction number of detector pixels in the second (faster) direction number of detector pixels in the third (if necessary, fastest) direction number of bins in the time-of-flight histogram A detector, detector bank, or multidetector. Total time of flight Total time of flight In DAQ clock pulses Clock frequency in Hz Identifier for detector (pixels) Can be multidimensional, if needed Data values from the detector. The rank and dimension ordering should follow a principle of slowest to fastest measurement axes and may be explicitly specified in application definitions. Mechanical scanning of objects (e.g. sample position/angle, incident beam energy, etc) tends to be the slowest part of an experiment and so any such scan axes should be allocated to the first dimensions of the array. Note that in some cases it may be useful to represent a 2D set of scan points as a single scan-axis in the data array, especially if the scan pattern doesn't fit a rectangular array nicely. Repetition of an experiment in a time series tends to be used similar to a slow scan axis and so will often be in the first dimension of the data array. The next fastest axes are typically the readout of the detector. A point detector will not add any dimensions (as it is just a single value per scan point) to the data array, a strip detector will add one dimension, an imaging detector will add two dimensions (e.g. X, Y axes) and detectors outputting higher dimensional data will add the corresponding number of dimensions. Note that the detector dimensions don't necessarily have to be written in order of the actual readout speeds - the slowest to fastest rule principle is only a guide. Finally, detectors that operate in a time-of-flight mode, such as a neutron spectrometer or a silicon drift detector (used for X-ray fluorescence) tend to have their dimension(s) added to the last dimensions in the data array. The type of each dimension should should follow the order of scan points, detector pixels, then time-of-flight (i.e. spectroscopy, spectrometry). The rank and dimension sizes (see symbol list) shown here are merely illustrative of coordination between related datasets. Title of measurement Integral of data as check of data integrity The best estimate of the uncertainty in the data value (array size should match the data field). Where possible, this should be the standard deviation, which has the same units as the data. The form data_error is deprecated. Offset from the detector center in x-direction. Can be multidimensional when needed. x-axis offset from detector center Offset from the detector center in the y-direction. Can be multidimensional when different values are required for each pixel. y-axis offset from detector center Offset from the detector center in the z-direction. Can be multidimensional when different values are required for each pixel. y-axis offset from detector center This is the distance to the previous component in the instrument; most often the sample. The usage depends on the nature of the detector: Most often it is the distance of the detector assembly. But there are irregular detectors. In this case the distance must be specified for each detector pixel. Note, it is recommended to use NXtransformations instead. This is the polar angle of the detector towards the previous component in the instrument; most often the sample. The usage depends on the nature of the detector. Most often it is the polar_angle of the detector assembly. But there are irregular detectors. In this case, the polar_angle must be specified for each detector pixel. Note, it is recommended to use NXtransformations instead. This is the azimuthal angle angle of the detector towards the previous component in the instrument; most often the sample. The usage depends on the nature of the detector. Most often it is the azimuthal_angle of the detector assembly. But there are irregular detectors. In this case, the azimuthal_angle must be specified for each detector pixel. Note, it is recommended to use NXtransformations instead. name/manufacturer/model/etc. information Serial number for the detector Local name for the detector Position and orientation of detector Solid angle subtended by the detector at the sample Size of each detector pixel. If it is scalar all pixels are the same size. Size of each detector pixel. If it is scalar all pixels are the same size Detector dead time Detector gas pressure maximum drift space dimension Crate number of detector Equivalent local term Slot number of detector Equivalent local term Input number of detector Equivalent local term Description of type such as He3 gas cylinder, He3 PSD, scintillator, fission chamber, proportion counter, ion chamber, ccd, pixel, image plate, CMOS, ... Group containing the description and metadata for a single channel from a multi-channel detector. Given an :ref:`NXdata` group linked as part of an NXdetector group that has an axis with named channels (see the example in :ref:`NXdata </NXdata@default_slice-attribute>`), the NXdetector will have a series of NXdetector_channel groups, one for each channel, named CHANNELNAME_channel. Spectral efficiency of detector with respect to e.g. wavelength efficiency of the detector This field can be two things: #. For a pixel detector it provides the nominal wavelength for which the detector has been calibrated. #. For other detectors this field has to be seen together with the efficiency field above. For some detectors, the efficiency is wavelength dependent. Thus this field provides the wavelength axis for the efficiency field. In this use case, the efficiency and wavelength arrays must have the same dimensionality. Real-time of the exposure (use this if exposure time varies for each array element, otherwise use ``count_time`` field). Most often there is a single real time value that is constant across an entire image frame. In such cases, only a 1-D array is needed. But there are detectors in which the real time changes per pixel. In that case, more than one dimension is needed. Therefore the rank of this field should be less than or equal to (detector rank + 1). start time for each frame, with the ``start`` attribute as absolute reference stop time for each frame, with the ``start`` attribute as absolute reference date of last calibration (geometry and/or efficiency) measurements summary of conversion of array data to pixels (e.g. polynomial approximations) and location of details of the calibrations How the detector is represented Elapsed actual counting time Use this group to provide other data related to this NXdetector group. In order to properly sort the order of the images taken in (for example) a tomography experiment, a sequence number is stored with each image. This is the x position where the direct beam would hit the detector. This is a length and can be outside of the actual detector. The length can be in physical units or pixels as documented by the units attribute. This is the y position where the direct beam would hit the detector. This is a length and can be outside of the actual detector. The length can be in physical units or pixels as documented by the units attribute. This is the start number of the first frame of a scan. In protein crystallography measurements one often scans a couple of frames on a give sample, then does something else, then returns to the same sample and scans some more frames. Each time with a new data file. This number helps concatenating such measurements. The diameter of a cylindrical detector The acquisition mode of the detector. True when the angular calibration has been applied in the electronics, false otherwise. Angular calibration data. True when the flat field correction has been applied in the electronics, false otherwise. Flat field correction data. Errors of the flat field correction data. The form flatfield_error is deprecated. True when the pixel mask correction has been applied in the electronics, false otherwise. The 32-bit pixel mask for the detector. Can be either one mask for the whole dataset (i.e. an array with indices i, j) or each frame can have its own mask (in which case it would be an array with indices np, i, j). Contains a bit field for each pixel to signal dead, blind or high or otherwise unwanted or undesirable pixels. They have the following meaning: .. can't make a table here, a bullet list will have to do for now * bit 0: gap (pixel with no sensor) * bit 1: dead * bit 2: under responding * bit 3: over responding * bit 4: noisy * bit 5: -undefined- * bit 6: pixel is part of a cluster of problematic pixels (bit set in addition to others) * bit 7: -undefined- * bit 8: user defined mask (e.g. around beamstop) * bits 9-30: -undefined- * bit 31: virtual pixel (corner pixel with interpolated value) Normal data analysis software would not take pixels into account when a bit in (mask & 0x0000FFFF) is set. Tag bit in the upper two bytes would indicate special pixel properties that normally would not be a sole reason to reject the intensity value (unless lower bits are set. If the full bit depths is not required, providing a mask with fewer bits is permissible. If needed, additional pixel masks can be specified by including additional entries named pixel_mask_N, where N is an integer. For example, a general bad pixel mask could be specified in pixel_mask that indicates noisy and dead pixels, and an additional pixel mask from experiment-specific shadowing could be specified in pixel_mask_2. The cumulative mask is the bitwise OR of pixel_mask and any pixel_mask_N entries. This field allow to distinguish different types of exposure to the same detector "data" field. Some techniques require frequent (re-)calibration inbetween measuremnts and this way of recording the different measurements preserves the chronological order with is important for correct processing. This is used for example in tomography (:ref:`NXtomo`) sample projections, dark and flat images, a magic number is recorded per frame. The key is as follows: * projection (sample) = 0 * flat field = 1 * dark field = 2 * invalid = 3 * background (no sample, but buffer where applicable) = 4 In cases where the data is of type :ref:`NXlog` this can also be an NXlog. Counting detectors usually are not able to measure all incoming particles, especially at higher count-rates. Count-rate correction is applied to account for these errors. True when count-rate correction has been applied, false otherwise. The countrate_correction_lookup_table defines the LUT used for count-rate correction. It maps a measured count :math:`c` to its corrected value :math:`countrate\_correction\_lookup\_table[c]`. :math:`m` denotes the length of the table. True when virtual pixel interpolation has been applied, false otherwise. When virtual pixel interpolation is applied, values of some pixels may contain interpolated values. For example, to account for space between readout chips on a module, physical pixels on edges and corners between chips may have larger sensor areas and counts may be distributed between their logical pixels. How many bits the electronics reads per pixel. With CCD's and single photon counting detectors, this must not align with traditional integer sizes. This can be 4, 8, 12, 14, 16, ... Time it takes to read the detector (typically milliseconds). This is important to know for time resolved experiments. Time it takes to start exposure after a trigger signal has been received. This is the reaction time of the detector firmware after receiving the trigger signal to when the detector starts to acquire the exposure, including any user set delay.. This is important to know for time resolved experiments. User-specified trigger delay. Time it takes to start exposure after a trigger signal has been received. This is the reaction time of the detector hardware after receiving the trigger signal to when the detector starts to acquire the exposure. It forms the lower boundary of the trigger_delay_time when the user does not request an additional delay. Time during which no new trigger signal can be accepted. Typically this is the trigger_delay_time + exposure_time + readout_time. This is important to know for time resolved experiments. This is time for each frame. This is exposure_time + readout time. The gain setting of the detector. This is a detector-specific value meant to document the gain setting of the detector during data collection, for detectors with multiple available gain settings. Examples of gain settings include: * ``standard`` * ``fast`` * ``auto`` * ``high`` * ``medium`` * ``low`` * ``mixed high to medium`` * ``mixed medium to low`` Developers are encouraged to use one of these terms, or to submit additional terms to add to the list. The value at which the detector goes into saturation. Especially common to CCD detectors, the data is known to be invalid above this value. For example, given a saturation_value and an underload_value, the valid pixels are those less than or equal to the saturation_value and greater than or equal to the underload_value. The precise type should match the type of the data. The lowest value at which pixels for this detector would be reasonably measured. The data is known to be invalid below this value. For example, given a saturation_value and an underload_value, the valid pixels are those less than or equal to the saturation_value and greater than or equal to the underload_value. The precise type should match the type of the data. CCD images are sometimes constructed by summing together multiple short exposures in the electronics. This reduces background etc. This is the number of short exposures used to sum images for an image. At times, radiation is not directly sensed by the detector. Rather, the detector might sense the output from some converter like a scintillator. This is the name of this converter material. At times, radiation is not directly sensed by the detector. Rather, the detector might sense the output from some converter like a scintillator. This is the thickness of this converter material. Single photon counter detectors can be adjusted for a certain energy range in which they work optimally. This is the energy setting for this. For use in special cases where the data in NXdetector is represented in several parts, each with a separate geometry. Shape description of each pixel. Use only if all pixels in the detector are of uniform shape. Shape description of each pixel. Use only if all pixels in the detector are of uniform shape and require being described by cylinders. Shape description of the whole detector. Use only if pixels in the detector are not of uniform shape. Shape description of the whole detector. Use only if pixels in the detector are not of uniform shape and require being described by cylinders. The reference point of the detector is the center of the first pixel. In complex geometries the NXoff_geometry groups can be used to provide an unambiguous reference. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXdetector_channel.nxdl.xml0000644000077000000000000001444114777236751030025 0ustar00rosborn These symbols will be used below to illustrate the coordination of the rank and sizes of datasets and the preferred ordering of the dimensions. Each of these are optional (so the rank of the datasets will vary according to the situation) and the general ordering principle is slowest to fastest. The type of each dimension should follow the order of scan points, detector output (e.g. pixels), then time-of-flight (i.e. spectroscopy, spectrometry). Note that the output of a detector is not limited to single values (0D), lists (1D) and images (2D), but three or higher dimensional arrays can be produced by a detector at each trigger. Rank of the ``data`` field associated with this detector number of scan points number of detector pixels in the slowest direction number of detector pixels in the second slowest direction number of detector pixels in the third slowest direction Description and metadata for a single channel from a multi-channel detector. Given an :ref:`NXdata` group linked as part of an NXdetector group that has an axis with named channels (see the example in :ref:`NXdata </NXdata@default_slice-attribute>`), the NXdetector will have a series of NXdetector_channel groups, one for each channel, named CHANNELNAME_channel. Example, given these axes in the NXdata group:: @axes = ["image_id", "channel", ".", "."] And this list of channels in the NXdata group:: channel = ["threshold_1", "threshold_2", "difference"] The NXdetector group would have three NXdetector_channel groups:: detector:NXdetector ... threshold_1_channel:NXdetector_channel threshold_energy = float flatfield = float[i, j] pixel_mask = uint[i, j] flatfield_applied = bool pixel_mask_applied = bool threshold_2_channel:NXdetector_channel threshold_energy = float flatfield = float[i, j] pixel_mask = uint[i, j] flatfield_applied = bool pixel_mask_applied = bool difference_channel:NXdetector_channel threshold_energy = float[2] Energy at which a photon will be recorded True when the flat field correction has been applied in the electronics, false otherwise. Response of each pixel given a constant input Errors of the flat field correction data. The form flatfield_error is deprecated. True when the pixel mask correction has been applied in the electronics, false otherwise. Custom pixel mask for this channel. May include nP as the first dimension for masks that vary for each scan point. The value at which the detector goes into saturation. Especially common to CCD detectors, the data is known to be invalid above this value. For example, given a saturation_value and an underload_value, the valid pixels are those less than or equal to the saturation_value and greater than or equal to the underload_value. The precise type should match the type of the data. The lowest value at which pixels for this detector would be reasonably measured. The data is known to be invalid below this value. For example, given a saturation_value and an underload_value, the valid pixels are those less than or equal to the saturation_value and greater than or equal to the underload_value. The precise type should match the type of the data. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXdetector_group.nxdl.xml0000644000077000000000000000675414777236751027561 0ustar00rosborn Logical grouping of detectors. When used, describes a group of detectors. Each detector is represented as an NXdetector with its own detector data array. Each detector data array may be further decomposed into array sections by use of NXdetector_module groups. Detectors can be grouped logically together using NXdetector_group. Groups can be further grouped hierarchically in a single NXdetector_group (for example, if there are multiple detectors at an endstation or multiple endstations at a facility). Alternatively, multiple NXdetector_groups can be provided. The groups are defined hierarchically, with names given in the group_names field, unique identifying indices given in the field group_index, and the level in the hierarchy given in the group_parent field. For example if an x-ray detector group, DET, consists of four detectors in a rectangular array:: DTL DTR DLL DLR We could have:: group_names: ["DET", "DTL", "DTR", "DLL", "DLR"] group_index: [1, 2, 3, 4, 5] group_parent: [-1, 1, 1, 1, 1] An array of the names of the detectors given in NXdetector groups or the names of hierarchical groupings of detectors given as names of NXdetector_group groups or in NXdetector_group group_names and group_parent fields as having children. An array of unique identifiers for detectors or groupings of detectors. Each ID is a unique ID for the corresponding detector or group named in the field group_names. The IDs are positive integers starting with 1. An array of the hierarchical levels of the parents of detectors or groupings of detectors. A top-level grouping has parent level -1. Code number for group type, e.g. bank=1, tube=2 etc. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXdetector_module.nxdl.xml0000644000077000000000000001363214777236751027703 0ustar00rosborn Geometry and logical description of a detector module. When used, child group to NXdetector. Many detectors consist of multiple smaller modules. Sometimes it is important to know the exact position of such modules. This is the purpose of this group. It is a child group to NXdetector. Note, the pixel size is given as values in the array fast_pixel_direction and slow_pixel_direction. A dimension-2 or dimension-3 field which gives the indices of the origin of the hyperslab of data for this module in the main area detector image in the parent NXdetector module. The data_origin is 0-based. The frame number dimension (np) is omitted. Thus the data_origin field for a dimension-2 dataset with indices (np, i, j) will be an array with indices (i, j), and for a dimension-3 dataset with indices (np, i, j, k) will be an array with indices (i, j, k). The :ref:`order <Design-ArrayStorageOrder>` of indices (i, j or i, j, k) is slow to fast. Two or three values for the size of the module in pixels in each direction. Dimensionality and order of indices is the same as for data_origin. Offset of the module in regards to the origin of the detector in an arbitrary direction. Three values that define the axis for this transformation A fixed offset applied before the transformation (three vector components). Units of the offset. Points to the path of the next element in the geometry chain. Values along the direction of :ref:`fastest varying <Design-ArrayStorageOrder>` :index:`pixel direction<dimension; fastest varying>`. Each value in this array is the size of a pixel in the units specified. Alternatively, if only one value is given, all pixels in this direction have the same value. The direction itself is given through the vector attribute. Three values that define the axis for this transformation A fixed offset applied before the transformation (three vector components). Units of the offset. Points to the path of the next element in the geometry chain. Values along the direction of :ref:`slowest varying<Design-ArrayStorageOrder>` :index:`pixel direction<dimension; slowest varying>`. Each value in this array is the size of a pixel in the units specified. Alternatively, if only one value is given, all pixels in this direction have the same value. The direction itself is given through the vector attribute. Three values that define the axis for this transformation A fixed offset applied before the transformation (three vector components). Units of the offset. Points to the path of the next element in the geometry chain. Points to the start of the dependency chain for this module. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXdisk_chopper.nxdl.xml0000644000077000000000000001366114777236751027201 0ustar00rosborn This symbol will be used below to coordinate datasets with the same shape. Number of slits in the disk A device blocking the beam in a temporal periodic pattern. A disk which blocks the beam but has one or more slits to periodically let neutrons through as the disk rotates. Often used in pairs, one NXdisk_chopper should be defined for each disk. The rotation of the disk is commonly monitored by recording a timestamp for each full rotation of disk, by having a sensor in the stationary disk housing sensing when it is aligned with a feature (such as a magnet) on the disk. We refer to this below as the "top-dead-center signal". Angles and positive rotation speeds are measured in an anticlockwise direction when facing away from the source. Type of the disk-chopper: only one from the enumerated list (match text exactly) Chopper rotation speed. Positive for anticlockwise rotation when facing away from the source, negative otherwise. Number of slits Angular opening Disk spacing in direction of beam Angle of each edge of every slit from the position of the top-dead-center timestamp sensor, anticlockwise when facing away from the source. The first edge must be the opening edge of a slit, thus the last edge may have an angle greater than 360 degrees. Timestamps of the top-dead-center signal. The times are relative to the "start" attribute and in the units specified in the "units" attribute. Please note that absolute timestamps under unix are relative to ``1970-01-01T00:00:00.0Z``. Angular separation of the center of the beam and the top-dead-center timestamp sensor, anticlockwise when facing away from the source. Radius of the disk Total slit height Chopper phase angle Time difference between timing system t0 and chopper driving clock signal Pulse reduction factor of this chopper in relation to other choppers/fastest pulse in the instrument Effective distance to the origin. Note, it is recommended to use NXtransformations instead. Low and high values of wavelength range transmitted This group describes the shape of the beam line component The reference plane of the disk chopper includes the surface of the spinning disk which faces the source. The reference point in the x and y axis is the point on this surface which is the centre of the axle which the disk is spinning around. The reference plane is orthogonal to the z axis and its position is the reference point on that axis. Note: This reference point in almost all practical cases is not where the beam passes though. .. image:: disk_chopper/disk_chopper.png :width: 40% ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXdistortion.nxdl.xml0000644000077000000000000001041414777236751026716 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays Number of symmetry points used for distortion correction Number of points of the matrix distortion field (x direction) Number of points of the matrix distortion field (y direction) Subclass of NXprocess to describe post-processing distortion correction. Has the distortion correction been applied? For `symmetry-guided distortion correction`_, where a pattern of features is mapped to the regular geometric structure expected from the symmetry. Here we record the number of elementary symmetry operations. .. _symmetry-guided distortion correction: https://www.sciencedirect.com/science/article/abs/pii/S0304399118303474?via%3Dihub For symmetry-guided distortion correction. Here we record the coordinates of the symmetry centre point. For symmetry-guided distortion correction. Here we record the coordinates of the relevant symmetry points. Column deformation field for general non-rigid distortion corrections. 2D matrix holding the column information of the mapping of each original coordinate. Row deformation field for general non-rigid distortion corrections. 2D matrix holding the row information of the mapping of each original coordinate. Description of the procedures employed. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXelectron_detector.nxdl.xml0000644000077000000000000000441114777236751030224 0ustar00rosborn A subclass of NXdetector for detectors that detect electrons. Type of electron amplifier, MCP, channeltron, etc. Description of the electron detector type, DLD, Phosphor+CCD, CMOS. Voltage applied to the electron detector. Voltage applied to the amplifier. The low voltage of the amplifier might not be the ground. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXelectronanalyzer.nxdl.xml0000644000077000000000000003075515046415443030076 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays Number of fast axes (axes acquired simultaneously, without scanning a physical quantity) Number of slow axes (axes acquired while scanning a physical quantity) Number of data points in the transmission function. Basic class for describing an electron analyzer. This concept is related to term `12.59`_ of the ISO 18115-1:2023 standard. .. _12.59: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:12.59 Free text description of the type of the detector Name or model of the equipment Acronym or other shorthand name Work function of the electron analyzer. The work function of a uniform surface of a conductor is the minimum energy required to remove an electron from the interior of the solid to a vacuum level immediately outside the solid surface. The kinetic energy :math:E_K of a photoelectron emitted from an energy level with binding energy :math:`E_B` below the Fermi level is given by :math:`E_K = h\nu - E_B - W = h\nu - E_B - e \phi_{\mathrm{sample}}`. Here, :math:`W = e \phi_{\mathrm{sample}}` is the work function of the sample surface, which is directly proportional to the potential difference :math:`\phi_{\mathrm{sample}}` between the electrochemical potential of electrons in the bulk and the electrostatic potential of an electron in the vacuum just outside the surface. In PES measurements, the sample and the spectrometer (with work function :math:`W_{\mathrm{spectr.}} = e \phi_{\mathrm{spectr.}}`) are electrically connected and therefore their Fermi levels are aligned. Due to the difference in local vacuum level between the sample and spectrometer, there however exists an electric potential difference (contact potential) :math:`\Delta\phi = \phi_{\mathrm{sample}} - \phi_{\mathrm{spectr.}}`. The measured kinetic energy of a photoelectron in PES is therefore given by :math:`E_K^{\mathrm{meas.}} = E_K + e\Delta\phi = h\nu - E_B - e\phi_{\mathrm{spectr.}}`. Hence, the measured kinetic energy :math:`E_K^{\mathrm{meas.}}` of a photoelectron is independent of the sample work function. Nonetheless, the work function :math:`\phi_{\mathrm{spectr.}}` needs to be known to accurately determine the binding energy scale. Voltage range of the power supply. This influences the noise of the supply and thereby the energy resolution. Energy resolution of the analyzer with the current setting. May be linked from an NXcalibration. Minimum distinguishable energy separation in the energy spectra. This concept is related to term `10.24`_ of the ISO 18115-1:2023 standard. .. _10.24: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:10.24 Ratio of the energy resolution of the electron analyzer at a specified energy value to that energy value. This concept is related to term `10.7`_ of the ISO 18115-1:2023 standard. .. _10.7: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:10.7 Momentum resolution of the electron analyzer (FWHM) Angular resolution of the electron analyzer (FWHM) Spatial resolution of the electron analyzer (Airy disk radius) This concept is related to term `10.14`_ of the ISO 18115-1:2023 standard. .. _10.14: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:10.15 List of the axes that are acquired simultaneously by the detector. These refer only to the experimental variables recorded by the electron analyzer. Other variables such as temperature, manipulator angles etc. can be labeled as fast or slow in the data. The fast axes should be listed in order of decreasing speed if they describe the same physical quantity or different components of the same quantity (e.g., ['kx', 'ky'] or ['detector_x', 'detector_y']). However, axes representing different physical quantities (e.g., ['energy', 'kx']) do not need to be ordered by speed. .. csv-table:: Examples :header: "Mode", "fast_axes", "slow_axes" "Hemispherical in ARPES mode", "['energy', 'kx']","" "Hemispherical with channeltron, sweeping energy mode", "", [\"energy\"] "Tof", "['energy', 'kx', 'ky']","" "Momentum microscope, spin-resolved", "['energy', 'kx', 'ky']", "['spin up-down', 'spin left-right']" Axes may be less abstract than this, i.e. ['detector_x', 'detector_y']. If energy_scan_mode=sweep, fast_axes: ['energy', 'kx']; slow_axes: ['energy'] is allowed. List of the axes that are acquired by scanning a physical parameter, listed in order of decreasing speed. See fast_axes for examples. Transmission function of the electron analyzer. The transmission function (TF) specifies the detection efficiency per solid angle for electrons of different kinetic energy passing through the electron analyzer. It depends on the spectrometer geometry as well as operation settings such as lens mode and pass energy. The transmission function is usually given as relative intensity vs. kinetic energy. The TF is used for calibration of the intensity scale in quantitative XPS. Without proper transmission correction, a comparison of results measured from the same sample using different operating modes for an instrument would show significant variations in signal intensity for the same kinetic energies. This concept is related to term `7.15`_ of the ISO 18115-1:2023 standard. .. _7.15: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:7.15 Kinetic energy values Relative transmission efficiency for the given kinetic energies Describes the electron collection (spatial and momentum imaging) column Describes the energy dispersion section Describes the spin dispersion section Describes the electron detector Deflectors outside the main optics ensembles described by the subclasses Individual lenses outside the main optics ensembles described by the subclasses Any other resolution not explicitly named in this base class. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXenergydispersion.nxdl.xml0000644000077000000000000002141515046415443030077 0ustar00rosborn Energy dispersion section of an electron analyzer. Energy dispersion scheme employed, for example: tof, hemispherical, cylindrical, mirror, retarding grid, etc. Mean kinetic energy of the electrons in this energy-dispersive section of the analyzer. This term should be used for hemispherical analyzers. This concept is related to term `12.63`_ of the ISO 18115-1:2023 standard. .. _12.63: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:12.63 Kinetic energy set for this dispersive section. Can be either the set kinetic energy, or the whole calibrated energy axis of a scan. Drift energy for time-of-flight energy dispersive elements. Center of the energy window The interval of transmitted energies. It can be two different things depending on whether the scan is fixed or swept. With a fixed scan it is a 2 vector containing the extrema of the transmitted energy window (smaller number first). With a swept scan of m steps it is a 2xm array of windows, one for each measurement point. Diameter of the dispersive orbit Radius of the dispersive orbit Way of scanning the energy axis constant :math:`\Delta E` mode, where the electron retardation (i.e., the fraction of pass energy to kinetic energy, :math:`R = (E_K - W)/E_p`, is scanned, but the pass energy :math:`E_p` is kept constant. Here, :math:`W = e \phi` is the spectrometer work function (with the potential difference :math:`\phi` between the electrochemical potential of electrons in the bulk and the electrostatic potential of an electron in the vacuum just outside the surface). This mode is often used in X-ray/ultraviolet photoemission spectroscopy (XPS/UPS) because the energy resolution does not change with changing energy (due to the constant pass energy). Synonyms: constant :math:`\Delta E` mode, constant analyzer energy mode, CAE mode, FAT mode This concept is related to term `12.64`_ of the ISO 18115-1:2023 standard. .. _12.64: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:12.64 constant :math:`\Delta E/E` mode, where the pass energy is scanned such that the electron retardation ratio is constant. In this mode, electrons of all energies are decelerated with this same fixed factor. Thus, the pass energy is proportional to the kinetic energy. This mode is often used in Auger electron spectroscopy (AES) to improve S/N for high-KE electrons, but this leads to a changing energy resolution (:math:`\Delta E \sim E_p`) at different kinetic energies. It can however also be used in XPS. Synonyms: constant :math:`\Delta E/E` mode, constant retardation ratio mode, CRR mode, FRR mode This concept is related to term `12.66`_ of the ISO 18115-1:2023 standard. .. _12.66: https://www.iso.org/obp/ui/en/#iso:std:iso:18115:-1:ed-3:v1:en:term:12.66 In the fixed energy (FE) mode, the intensity for one single kinetic energy is measured for a specified time. This mode is particularly useful during setup or alignment of the electron analyzer, for analysis of stability of the excitation source or for sample alignment. Since the mode measures intensity as a function of time, the difference in channel signals is not of interest. Therefore, the signals from all channels are summed. Synonym: FE mode Snapshot mode does not involve an energy scan and instead collects data from all channels of the detector without averaging. The resulting spectrum reflects the energy distribution of particles passing through the analyzer using the current settings. This mode is commonly used to position the detection energy at the maximum of a peak and record the signal, enabling faster data acquisition within a limited energy range compared to FAT. Snapshot measurements are particularly suitable for CCD and DLD detectors, which have multiple channels and can accurately display the peak shape. While five or nine-channel detectors can also be used for snapshot measurements, their energy resolution is relatively lower. In dither acquisition mode, the kinetic energy of the analyzer is randomly varied by a small value around a central value and at fixed pass energy. This reduces or removes inhomogeneities of the detector efficiency, such as e.g. imposed by a mesh in front of the detector. Mostly relevant for CCD/DLD type of detectors. Length of the time-of-flight drift electrode Size, position and shape of a slit in dispersive analyzer, e.g. entrance and exit slits. Deflectors in the energy dispersive section Individual lenses in the energy dispersive section ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXentry.nxdl.xml0000755000077000000000000002027314777236751025670 0ustar00rosborn .. index:: find the default plottable data .. index:: plotting .. index:: default attribute value Declares which :ref:`NXdata` group contains the data to be shown by default. It is used to resolve ambiguity when one :ref:`NXdata` group exists. The value :ref:`names <validItemName>` a child group. If that group itself has a ``default`` attribute, continue this chain until an :ref:`NXdata` group is reached. For more information about how NeXus identifies the default plottable data, see the :ref:`Find Plottable Data, v3 <Find-Plottable-Data-v3>` section. (**required**) :ref:`NXentry` describes the measurement. The top-level NeXus group which contains all the data and associated information that comprise a single measurement. It is mandatory that there is at least one group of this type in the NeXus file. The data group .. note:: Before the NIAC2016 meeting [#]_, at least one :ref:`NXdata` group was required in each :ref:`NXentry` group. At the NIAC2016 meeting, it was decided to make :ref:`NXdata` an optional group in :ref:`NXentry` groups for data files that do not use an application definition. It is recommended strongly that all NeXus data files provide a NXdata group. It is permissable to omit the NXdata group only when defining the default plot is not practical or possible from the available data. For example, neutron event data may not have anything that makes a useful plot without extensive processing. Certain application definitions override this decision and require an :ref:`NXdata` group in the :ref:`NXentry` group. The ``minOccurs=0`` attribute in the application definition will indicate the :ref:`NXdata` group is optional, otherwise, it is required. .. [#] NIAC2016: https://www.nexusformat.org/NIAC2016.html, https://github.com/nexusformat/NIAC/issues/16 ISIS Muon IDF_Version Extended title for entry Unique identifier for the experiment, defined by the facility, possibly linked to the proposals Brief summary of the experiment, including key objectives. Description of the full experiment (document in pdf, latex, ...) User or Data Acquisition defined group of NeXus files or NXentry Brief summary of the collection, including grouping criteria. unique identifier for the measurement, defined by the facility. UUID identifier for the measurement. Version of UUID used Reserved for future use by NIAC. See https://github.com/nexusformat/definitions/issues/382 (alternate use: see same field in :ref:`NXsubentry` for preferred) Official NeXus NXDL schema to which this entry conforms which must be the name of the NXDL file (case sensitive without the file extension) that the NXDL schema is defined in. For example the ``definition`` field for a file that conformed to the *NXarpes.nxdl.xml* definition must contain the string **NXarpes**. This field is provided so that :ref:`NXentry` can be the overlay position in a NeXus data file for an application definition and its set of groups, fields, and attributes. *It is advised* to use :ref:`NXsubentry`, instead, as the overlay position. NXDL version number URL of NXDL file Local NXDL schema extended from the entry specified in the ``definition`` field. This contains any locally-defined, additional fields in the entry. NXDL version number URL of NXDL file Starting time of measurement Ending time of measurement Duration of measurement Time transpired actually collecting data i.e. taking out time when collection was suspended due to e.g. temperature out of range Such as "2007-3". Some user facilities organize their beam time into run cycles. Name of program used to generate this file Program version number configuration of the program Revision id of the file due to re-calibration, reprocessing, new analysis, new instrument definition format, ... This is the flightpath before the sample position. This can be determined by a chopper, by the moderator or the source itself. In other words: it the distance to the component which gives the T0 signal to the detector electronics. If another component in the NXinstrument hierarchy provides this information, this should be a link. Notes describing entry A small image that is representative of the entry. An example of this is a 640x480 jpeg image automatically produced by a low resolution plot of the NXdata. The mime type should be an ``image/*`` ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXenvironment.nxdl.xml0000644000077000000000000001042114777236751027062 0ustar00rosborn Parameters for controlling external conditions Apparatus identification code/model number; e.g. OC100 011 Alternative short name, perhaps for dashboard display like a present Seblock name Type of apparatus. This could be the SE codes in scheduling database; e.g. OC/100 Description of the apparatus; e.g. 100mm bore orange cryostat with Roots pump Program controlling the apparatus; e.g. LabView VI name The position and orientation of the apparatus. Note, it is recommended to use NXtransformations instead. This is to be used if there is no actuator/sensor that controls/measures the environment parameters, but the user would still like to give a value for it. An example would be a room temperature experiment where the temperature is not actively measured, but rather estimated. Note that this method for recording the environment parameters is not advised, but using NXsensor and NXactuator is strongly recommended instead. NeXus positions components by applying a set of translations and rotations to apply to the component starting from 0, 0, 0. The order of these operations is critical and forms what NeXus calls a dependency chain. The depends_on field defines the path to the top most operation of the dependency chain or the string "." if located in the origin. Usually these operations are stored in a NXtransformations group. But NeXus allows them to be stored anywhere. This is the group recommended for holding the chain of translation and rotation operations necessary to position the component within the instrument. The dependency chain may however traverse similar groups in other component groups. Additional information, LabView logs, digital photographs, etc Any actuator used to control the environment. This can be linked to an actuator defined in an NXinstrument instance. Any sensor used to monitor the environment. This can be linked to a sensor defined in an NXinstrument instance. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXevent_data.nxdl.xml0000644000077000000000000001064714777236751026642 0ustar00rosborn NXevent_data is a special group for storing data from neutron detectors in event mode. In this mode, the detector electronics emits a stream of detectorID, timestamp pairs. With detectorID describing the detector element in which the neutron was detected and timestamp the timestamp at which the neutron event was detected. In NeXus detectorID maps to event_id, event_time_offset to the timestamp. As this kind of data is common at pulsed neutron sources, the timestamp is almost always relative to the start of a neutron pulse. Thus the pulse timestamp is recorded too together with an index in the event_id, event_time_offset pair at which data for that pulse starts. At reactor source the same pulsed data effect may be achieved through the use of choppers or in stroboscopic measurement setups. In order to make random access to timestamped data faster there is an optional array pair of cue_timestamp_zero and cue_index. The cue_timestamp_zero will contain courser timestamps then in the time array, say every five minutes. The cue_index will then contain the index into the event_id,event_time_offset pair of arrays for that courser cue_timestamp_zero. A list of timestamps for each event as it comes in. There will be extra information in the NXdetector to convert event_id to detector_number. The time that each pulse started with respect to the offset ISO8601 The index into the event_time_offset, event_id pair for the pulse occurring at the matching entry in event_time_zero. If voltages from the ends of the detector are read out this is where they go. This list is for all events with information to attach to a particular pulse height. The information to attach to a particular pulse is located in events_per_pulse. Timestamps matching the corresponding cue_index into the event_id, event_time_offset pair. Index into the event_id, event_time_offset pair matching the corresponding cue_timestamp. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXevent_data_apm.nxdl.xml0000644000077000000000000001355515046415443027463 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Number of pulses collected in between start_time and end_time. Base class to store state and (meta)data of events over the course of an atom probe experiment. Having at least one instance for an instance of NXapm is recommended. This base class applies the concept of the :ref:`NXevent_data_em` base class to the specific needs of atom probe research. Again static and dynamic quantities are split to avoid a duplication of information. Specifically, the time interval considered is the entire time starting at start_time until end_time during which we assume the pulser triggered pulses. These pulses are identified via the pulse_id field. The point in time when each pulse was fired can be recovered from analyzing start_time and delta_time. Which temporal granularity is adequate depends on the situation and research question. Using a model which enables a collection of events offers the most flexible way to cater for both atom probe experiments or simulation. To monitor the course of an ion extraction experiment (or simulation) it makes sense to track time explicitly via time stamps or implicitly via e.g. a clock inside the instrument, such as the clock of the pulser and respective pulse_id. ISO 8601 time code with local time zone offset to UTC information included when the snapshot time interval started. If users wish to specify an interval of time that the snapshot should represent during which the instrument was stable and configured using specific settings and calibrations, the start_time is the start, the left bound of the time interval, while the end_time specifies the end, the right bound of the time interval. ISO 8601 time code with local time zone offset to UTC information included when the snapshot time interval ended. Delta time array which resolves for each pulse_id the time difference between when that pulse was fired and start_time. In summary, using start_time, end_time, delta_time, pulse_id_offset, and pulse_id provides temporal context information when a pulse was fired relative to start_time and when it is relevant to translate this into coordinated world time UTC. Note that pulses in reality have a shape and thus additional documentation is required to assure that the entries in delta_time are always taken at at points in time that, relative to the triggering of the pulse, represent an as close as possible state of the pulse. Integer which defines the first pulse_id. Typically, this is either zero or one. An integer to identify a specific pulse in a sequence. There are two possibilities to report pulse_id values: If pulse_id_offset is provided, the pulse_id values are defined by the sequence :math:`[pulse\_id\_offset, pulse\_id\_offset + p]` with :math:`p` the number of pulses collected in between start_time and end_time. Alternatively, pulse_id_offset is not provided but instead a sequence of :math:`p` values is defined. These integer values do not need to be sorted. Place to store dynamic metadata of the instrument to document as close as possible the state of the instrument during the event, i.e. in between start_time and end_time. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXfabrication.nxdl.xml0000644000077000000000000000521015046415443026762 0ustar00rosborn Details about a component as it is defined by its manufacturer. Company name of the manufacturer. Version or model of the component named by the manufacturer. If it is possible that different versions exist, the value in this field should be made specific enough to resolve the version. Serial number of the component. Datetime of component's initial construction. This refers to the date of first measurement after new construction or to the relocation date, if it describes a multicomponent/custom-build setup. Just the year is often sufficient, but if a full date/time is used, it is recommended to add an explicit time zone. Free-text list of functionalities which the component offers. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXfermi_chopper.nxdl.xml0000644000077000000000000000634714777236751027354 0ustar00rosborn A Fermi chopper, possibly with curved slits. Fermi chopper type chopper rotation speed radius of chopper width of an individual slit radius of curvature of slits number of slits input beam height input beam width distance. Note, it is recommended to use NXtransformations instead. Wavelength transmitted by chopper energy selected geometry of the fermi chopper absorbing material transmitting material This group describes the shape of the beam line component .. todo:: Add a definition for the reference point of a fermi chopper. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXfilter.nxdl.xml0000644000077000000000000001523114777236751026007 0ustar00rosborn For band pass beam filters. If uncertain whether to use :ref:`NXfilter` (band-pass filter) or :ref:`NXattenuator` (reduces beam intensity), then use :ref:`NXattenuator`. Geometry of the filter Composition of the filter. Chemical formula can be specified separately. This field was changed (2010-11-17) from an enumeration to a string since common usage showed a wider variety of use than a simple list. These are the items in the list at the time of the change: Beryllium | Pyrolytic Graphite | Graphite | Sapphire | Silicon | Supermirror. position with respect to in or out of the beam (choice of only "in" or "out") in the beam out of the beam Wavelength transmission profile of filter average/nominal filter temperature Linked temperature_log for the filter Thickness of the filter mass density of the filter The chemical formula specified using CIF conventions. Abbreviated version of CIF standard: * Only recognized element symbols may be used. * Each element symbol is followed by a 'count' number. A count of '1' may be omitted. * A space or parenthesis must separate each cluster of (element symbol + count). * Where a group of elements is enclosed in parentheses, the multiplier for the group must follow the closing parentheses. That is, all element and group multipliers are assumed to be printed as subscripted numbers. * Unless the elements are ordered in a manner that corresponds to their chemical structure, the order of the elements within any group or moiety depends on whether or not carbon is present. * If carbon is present, the order should be: * C, then H, then the other elements in alphabetical order of their symbol. * If carbon is not present, the elements are listed purely in alphabetic order of their symbol. * This is the *Hill* system used by Chemical Abstracts. Sensor(s)used to monitor the filter temperature Unit cell lattice parameter: length of side a Unit cell lattice parameter: length of side b Unit cell lattice parameter: length of side c Unit cell lattice parameter: angle alpha Unit cell lattice parameter: angle beta Unit cell lattice parameter: angle gamma Unit cell Orientation matrix of single crystal filter using Busing-Levy convention: W. R. Busing and H. A. Levy (1967). Acta Cryst. 22, 457-464 m value of supermirror filter substrate material of supermirror filter substrate thickness of supermirror filter coating material of supermirror filter substrate roughness (RMS) of supermirror filter coating roughness (RMS) of supermirror filter This group describes the shape of the beam line component .. todo:: Add a definition for the reference point of a filter. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXfit.nxdl.xml0000644000077000000000000002362015046415443025270 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Rank of the dependent and independent data arrays (for multivariate scalar-valued fit.) Description of a fit procedure using a scalar valued global function Human-readable label for this fit procedure. Data and results of the fit. Independent variable(s) for this fit procedure, representing the values to be fitted by the ``global_fit_function``. The ``input_dependent`` field must have the same rank (``dimRank``) as the ``input_independent`` field. Each individual dimension of ``input_dependent`` must have the same number of points as the corresponding dimension in the ``input_independent`` field. Dependent variable(s) for this fit procedure (i.e., the observed data). The ``input_independent`` field must have the same rank (``dimRank``) as the ``input_dependent`` field. Each individual dimension of ``input_independent`` must have the same number of points as the corresponding dimension in the ``input_dependent`` field. Resulting fit obtained by evaluating the ``global_fit_function`` at the points specified in ``input_independent`` using the optimized fit parameters. This represents the best-fit curve or surface approximating the input_dependent data. The ``fit_sum`` field must have the same rank (``dimRank``) as the ``input_independent`` field. Each individual dimension of ``fit_sum`` must have the same number of points as the corresponding dimension in the ``input_independent`` field. The difference between the observed data (``input_dependent``) and the predicted fit values (``fit_sum``). A lower magnitude of residuals indicates a better fit. The ``residual`` field must have the same rank (``dimRank``) as the ``input_independent`` field. Each individual dimension of ``residual`` must have the same number of points as the corresponding dimension in the ``input_independent`` field. An instance of the peak model. If there is no characteristic name for each peak component, the peaks could be labeled as peak_0, peak_1, and so on. Total area under the curve (can also be used for the total area minus any background values). Relative sensitivity for this peak, to be used for quantification in an NXprocess. As an example, in X-ray spectroscopy could depend on the energy scale (see position), the ionization cross section, and the element probed. Relative area of this peak compared to other peaks. The relative area can simply be derived by dividing the total_area by the total area of all peaks or by a more complicated method (e.g., by additionally dividing by the relative sensitivity factors). Details shall be given in `global_fit_function`. One fitted background (functional form, position (see :ref:`data/input_independent </NXfit/data/input_independent-field>`), and intensities) of the peak fit. If there is no characteristic name for each background component, it is envisioned that backgrounds are labeled as background_0, background_1, and so on. Function used to describe the overall fit to the data, taking into account the parameters of the individual :ref:`NXpeak` components. Often, if the peaks and fit backgrounds are defined independently (i.e, with their own parameter sets), the resulting global fit is a function of the form :math:`model = peak_1(p_1) + peak2(p_2) + backgr(p_3).`, where each :math:`p_x` describes the set of parameters for one peak/background. Function used to optimize the parameters during peak fitting. Description of the method used to optimize the parameters during peak fitting. Examples: - least squares - non-linear least squares - Levenberg-Marquardt algorithm (damped least-squares) - linear regression - Bayesian linear regression For the optimization, the formula is any optimization process on the ``global_fit_function`` given above. As an example, for a least squares algorithm on independent components, the formula of the ``error_function`` would be :math:`LLS(peak_1(p_1) + peak_2(p_2) + backgr(p_3))`, where each :math:`p_i` describes the set of parameters for one peak/background. In this case, the ``formula_description`` can be expressed as :math:`min(\chi^2)`, where :math:`\chi^2` is the sum of squared residuals between the model and the observed data: :math:`min(\chi^2) = \sum_{i=1}^{N} \left( y_i - \left( \text{peak}_1(p_1, x_i) + \text{peak}_2(p_2, x_i) + \text{backgr}(p_3, x_i) \right) \right)^2` It is however also possible to supply more involved formulas (e.g., in the case of constrained fits). Figure-of-merit to determine the goodness of fit, i.e., how well the fit model (i.e., the set of peaks and backgrounds) fits the measured observations. This value (which is a single number) is often used to guide adjustments to the fitting parameters in the peak fitting process. Metric used to determine the goodness of fit. Examples include: - :math:`\chi^2`, the squared sum of the sigma-weighted residuals - reduced :math:`\chi^2`:, :math:`\chi^2`: per degree of freedom - :math:`R^2`, the coefficient of determination ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXfit_function.nxdl.xml0000644000077000000000000001026115046415443027172 0ustar00rosborn This describes a fit function that is used to fit data to any functional form. A fit function is used to describe a set of data :math:`y_k, k = 1 ... M`, which are collected as a function of one or more independent variables :math:`x` at the points :math:`x_k`. The fit function :math:`f` describes these data in an approximate way as :math:`y_k \approx f(a_0, . . . a_n, x_k)`, where :math:`a_i, i = 0 . . . n` are the *fit parameters* (which are stored the instances of ``NXfit_parameter``). Type of function used. Examples include "Gaussian" and "Lorentzian". In case a complicated functions, the the functional form of the function should be given by the ``formula_description`` field . The user is also encouraged to use the ``description`` field for describing the fit function in a human-readable way. Application definitions may limit the allowed fit functions by using an enumeration for the ``function_type`` field. Human-readable short description of this fit function. Software tools may use this field to write their local description of the fit function. Description of the mathematical formula of the function, taking into account the instances of ``TERM`` in ``fit_parameters``. A parameter for a fit function. This would typically be a variable that is optimized in a fit. A description of what this parameter represents. If the parameter is held constant, then this attribute should be True. The minimal value of the parameter, to be used as a constraint during fitting. The maximal value of the parameter, to be used as a constraint during fitting. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXflipper.nxdl.xml0000644000077000000000000000532614777236751026167 0ustar00rosborn A spin flipper. Linear density of turns (such as number of turns/cm) in flipping field coils Linear density of turns (such as number of turns/cm) in compensating field coils Linear density of turns (such as number of turns/cm) in guide field coils Flipping field coil current in "on" state" Compensating field coil current in "on" state" Guide field coil current in "on" state thickness along path of neutron travel .. todo:: Add a definition for the reference point of a spin flipper. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXfresnel_zone_plate.nxdl.xml0000644000077000000000000000600714777236751030401 0ustar00rosborn A fresnel zone plate list of polynomial coefficients describing the focal length of the zone plate, in increasing powers of photon energy, that describes the focal length of the zone plate (in microns) at an X-ray photon energy (in electron volts). how the zone plate was manufactured Material of the zones themselves Material present between the zones. This is usually only present for the "zone doubled" fabrication process If no mask is present, set mask_thickness to 0 and omit the mask_material field .. todo:: Add a definition for the reference point of a fresnel zone plate. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXgeometry.nxdl.xml0000644000077000000000000000535314777236751026361 0ustar00rosborn legacy class - recommend to use :ref:`NXtransformations` now It is recommended that instances of :ref:`NXgeometry` be converted to use :ref:`NXtransformations`. This is the description for a general position of a component. It is recommended to name an instance of :ref:`NXgeometry` as "geometry" to aid in the use of the definition in simulation codes such as McStas. Also, in HDF, linked items must share the same name. However, it might not be possible or practical in all situations. shape/size information of component translation of component orientation of component Optional description/label. Probably only present if we are an additional reference point for components rather than the location of a real component. Position of the component along the beam path. The sample is at 0, components upstream have negative component_index, components downstream have positive component_index. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1748719305.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXgoniometer.nxdl.xml0000755000077000000000000000513015016653311026650 0ustar00rosborn Goniometer rotation angles and sample translations used during a measurement. The goniometers used at neutron and x-ray facilities are typically four-circle or six-circle goniometers, or variants of either one. There is no universally recognized naming convention for angles and translations, so the group should contain a :ref:`NXcite` group, which describes how the angles are defined. A reference to a publication or online documentation that describe the convention used in this group to define the names of angles and sample translations. The common name for the type of goniometer used in these measurements. One of the goniometer rotation angles defined by the specified convention. The translation of the sample from the centre of rotation of the goniometer angles along one of the coordinate axes. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXgrating.nxdl.xml0000644000077000000000000000764514777236751026167 0ustar00rosborn A diffraction grating, as could be used in a soft X-ray monochromator Blaze or trapezoidal angles, with the angle of the upstream facing edge listed first. Blazed gratings can be identified by the low value of the first-listed angle. List of polynomial coefficients describing the spatial separation of lines/grooves as a function of position along the grating, in increasing powers of position. Gratings which do not have variable line spacing will only have a single coefficient (constant). Angle between the incident beam and the utilised outgoing beam. An array describing the thickness of each layer A NXshape group describing the shape of the mirror Numerical description of the surface figure of the mirror. This group describes the shape of the beam line component .. todo:: Add a definition for the reference point of a bending grating. "Engineering" position of the grating Transformations used by this component to define its position and orientation. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXguide.nxdl.xml0000644000077000000000000001757014777236751025627 0ustar00rosborn number of reflecting surfaces number of wavelengths A neutron optical element to direct the path of the beam. :ref:`NXguide` is used by neutron instruments to describe a guide consists of several mirrors building a shape through which neutrons can be guided or directed. The simplest such form is box shaped although elliptical guides are gaining in popularity. The individual parts of a guide usually have common characteristics but there are cases where they are different. For example, a neutron guide might consist of 2 or 4 coated walls or a supermirror bender with multiple, coated vanes. To describe polarizing supermirrors such as used in neutron reflection, it may be necessary to revise this definition of :ref:`NXguide` to include :ref:`NXpolarizer` and/or :ref:`NXmirror`. When even greater complexity exists in the definition of what constitutes a *guide*, it has been suggested that :ref:`NXguide` be redefined as a :ref:`NXcollection` of :ref:`NXmirror` each having their own :ref:`NXgeometry` describing their location(s). For the more general case when describing mirrors, consider using :ref:`NXmirror`. NOTE: The NeXus International Advisory Committee welcomes comments for revision and improvement of this definition of :ref:`NXguide`. TODO: Explain what this NXgeometry group means. What is intended here? A description of this particular instance of ``NXguide``. TODO: documentation needed Reflectivity as function of reflecting surface and wavelength reflectivity of each surface as a function of wavelength List of surfaces. Probably best to use index numbers but the specification is very loose. wavelengths at which reflectivity was measured TODO: documentation needed TODO: documentation needed external material outside substrate The ``m`` value for a supermirror, which defines the supermirror regime in multiples of the critical angle of Nickel. TODO: documentation needed TODO: documentation needed TODO: documentation needed TODO: documentation needed TODO: documentation needed number of substrate sections (also called ``nsurf`` as an index in the ``NXguide`` specification) This group describes the shape of the beam line component The entry opening of the guide lies on the reference plane. The center of the opening on that plane is the reference point on the x and y axis. The reference plane is orthogonal to the z axis and is the reference point along the z axis. Given no bend in the guide, it is parallel with z axis and extends in the positive direction of the z axis. .. image:: guide/guide.png :width: 40% ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXhistory.nxdl.xml0000644000077000000000000000546715046415443026220 0ustar00rosborn A set of activities that occurred to a physical entity prior/during experiment. Ideally, a full report of the previous operations (or links to a chain of operations). Alternatively, notes allow for additional descriptors in any format. Any activity that was performed on the physical entity prior or during the experiment. An ID or reference to the location or a unique (globally persistent) identifier of e.g. another file which gives as many as possible details of the history event. A descriptor to keep track of the treatment of the physical entity before or during the experiment (NXnote allows to add pictures, audio, movies). Alternatively, a reference to the location or a unique identifier or other metadata file. In the case these are not available, free-text description. This should only be used in case that there is no rigorous description using the base classes above. This group can also be used to pull in any activities that are not well described by an existing base class definition. Any number of instances of NXnote are allowed for describing extra details of this activity. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXimage.nxdl.xml0000644000077000000000000006161115046415443025572 0ustar00rosborn Number of images in the stack, for stacks the slowest dimension. Number of image points along the slow dimension (k equivalent to z). Number of image points along the fast dimension (j equivalent to y). Number of image points along the fastest dimension (i equivalent to x). Base class for reporting a set of images representing specializations of NXdata. The most commonly used scanning methods are supported. That is one-, two-, three-dimensional ROIs discretized using regular Euclidean tilings. Colloquially, an image is understood as a discretized representation of intensity distribution detected or simulated for some ROI. When discretized with regular Euclidean tilings, the terms pixel and voxel identify the smallest discretization unit. In this case, pixel and voxel are polygonal or polyhedral unit cells respectively of the underlying tiling of the ROI within the reference space. For all other tilings e.g. non-equispaced, the shape and size of pixel and voxel differs. Using the term image point is eventually more appropriate when working with such tilings. Therefore, all docstrings in this base class refer to points. Points are considered exact synonyms for pixel and voxel, which are terms used for regular tilings. Point coordinates identify the location of the barycenter. For images in reciprocal space in practice, complex numbers are encoded via some formatted pair of real values. Typically, fast algorithms for computing Fourier transformations (FFT) are used to encode images in reciprocal (frequency) space. FFT libraries are used for implementing the key functionalities of these mathematical operations. Different libraries use different representations and encoding of the images. Details can be found in the respective sections of the typical FFT libraries documentations: * `FFTW by M. Frigo and S. G. Johnson <https://www.fftw.org/fftw3_doc/Tutorial.html#Tutorial>`_ * `Intel MKL by the Intel Co. <https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-c/2024-2/fourier-transform-functions.html>`_ * `cuFFT by the NVidia Co. <https://docs.nvidia.com/cuda/cufft/index.html>`_ * `NFFT by the TU Chemnitz group <https://www-user.tu-chemnitz.de/~potts/nfft/>`_ for non-equispaced computations Users are strongly advised to inspect carefully which specific conventions their library uses to enable storing and modifying the implementation of their code such that the serialized representations as they are detailed here for NeXus match. It is often the case that several images are combined using processing. In this case, the number of images which are combined into collections is not necessarily the same for each collection. The NXimage base class addresses this logical distinction through the notation of indices_image and indices_group concepts. That is indices_image are always counting from offset in increments of one as each image is its own entity. By contrast, a group may contain no, or several images. Consequently, indices_group are not required to be contiguous. Details how NXdata instance were processed from detector readings/raw data. Resolvable data artifact (e.g. file) from which all values in the :ref:`NXdata` instances in this :ref:`NXimage` were loaded during parsing. Possibility to document from which specific other serialized resource as the source pieces of information were processed when using NeXus as a semantic file format to serialize that information differently. The group in combination with an added field *context* therein adds context. Reference to a location inside the artifact that points to the specific group of values that were processed if the artifacts contains several groups of values and thus further resolving of ambiguities is required. Link or name of an :ref:`NXdetector` instance with which the data were collected. Program used for processing. One-dimensional image. Intensity for real-valued images as an alternative for real. Magnitude of the image intensity for complex-valued data. Real part of the image intensity per point. Imaginary part of the image intensity per point. Image intensity as a complex number as an alternative to real and imag fields if values are stored as interleaved complex numbers. Point coordinate along the fastest dimension. Point coordinate along the fastest dimension. Two-dimensional image. Intensity for real-valued images as an alternative for real. Magnitude of the image intensity for complex-valued data. Real part of the image intensity per point. Imaginary part of the image intensity per point. Image intensity as a complex number as an alternative to real and imag fields if values are stored as interleaved complex numbers. Point coordinate along the fast dimension. Point coordinate along the fast dimension. Point coordinate along the fastest dimension. Point coordinate along the fastest dimension. Three-dimensional image. Intensity for real-valued images as an alternative for real. Magnitude of the image intensity for complex-valued data. Real part of the image intensity per point. Imaginary part of the image intensity per point. Image intensity as a complex number as an alternative to real and imag fields if values are stored as interleaved complex numbers. Point coordinate along the slow dimension. Point coordinate along the slow dimension. Point coordinate along the fast dimension. Point coordinate along the fast dimension. Point coordinate along the fastest dimension. Point coordinate along the fastest dimension. Collection of one-dimensional images. Intensity for real-valued images as an alternative for real. Magnitude of the image intensity for complex-valued data. Real part of the image intensity per point. Imaginary part of the image intensity per point. Image intensity as a complex number as an alternative to real and imag fields if values are stored as interleaved complex numbers. Group identifier Group identifier Image identifier Image identifier Point coordinate along the fastest dimension. Point coordinate along the fastest dimension. Collection of two-dimensional images. Intensity for real-valued images as an alternative for real. Magnitude of the image intensity for complex-valued data. Real part of the image intensity per point. Imaginary part of the image intensity per point. Image intensity as a complex number as an alternative to real and imag fields if values are stored as interleaved complex numbers. Group identifier Group identifier Image identifier Image identifier. Point coordinate along the fast dimension. Point coordinate along the fast dimension. Point coordinate along the fastest dimension. Point coordinate along the fastest dimension. Collection of three-dimensional images. Intensity for real-valued images as an alternative for real. Magnitude of the image intensity for complex-valued data. Real part of the image intensity per point. Imaginary part of the image intensity per point. Image intensity as a complex number as an alternative to real and imag fields if values are stored as interleaved complex numbers. Group identifier Group identifier Image identifier Image identifier Point coordinate along the slow dimension. Point coordinate along the slow dimension. Point coordinate along the fast dimension. Point coordinate along the fast dimension. Point coordinate along the fastest dimension. Point coordinate along the fastest dimension. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXinsertion_device.nxdl.xml0000644000077000000000000000700714777236751030055 0ustar00rosborn An insertion device, as used in a synchrotron light source. separation between opposing pairs of magnetic poles angular of gap difference between upstream and downstream ends of the insertion device number of poles beam displacement parameter length of insertion device total power delivered by insertion device energy of peak intensity in output spectrum bandwidth of peak energy harmonic number of peak spectrum of insertion device "Engineering" position of insertion device This group describes the shape of the beam line component .. todo:: Add a definition for the reference point of a insertion device. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1748458975.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXinstrument.nxdl.xml0000644000077000000000000000605115015656737026726 0ustar00rosborn Collection of the components of the instrument or beamline. Template of instrument descriptions comprising various beamline components. Each component will also be a NeXus group defined by its distance from the sample. Negative distances represent beamline components that are before the sample while positive distances represent components that are after the sample. This device allows the unique identification of beamline components in a way that is valid for both reactor and pulsed instrumentation. Name of instrument short name for instrument, perhaps the acronym ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXinstrument_apm.nxdl.xml0000644000077000000000000004173015046415443027555 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Number of pulses collected in between start_time and end_time inside a parent instance of :ref:`NXevent_data_apm`. Base class for instrument-related details of a real or simulated atom probe tomograph or field-ion microscope. For collecting data and experiments which are simulations of an atom probe microscope or a session with such instrument use the :ref:`NXapm` application definition and the :ref:`NXevent_data_apm` groups it provides. This base class implements the concept of :ref:`NXapm` whereby (meta)data are distinguished whether these typically change during a session, so-called dynamic, or not, so-called static metadata. This design allows to store e.g. hardware related concepts only once instead of demanding that each image or spectrum from the session needs to be stored also with the static metadata. Which type of instrument. Location of the lab or place where the instrument is installed. Using GEOREF is preferred. Nominal flight path The value can be extracted from the CAnalysis.CSpatial.fFlightPath field of a CamecaRoot ROOT file. Device which reduces ToF differences of ions in ToF experiments. For atom probe the reflectron can be considered an energy compensation device. Such a device can be realized technically e.g. with a Poschenrieder lens. Consult the following U.S. patents for further details: * 3863068 and 6740872 for the reflectron * 8134119 for the curved reflectron Was the reflectron used? The maximum voltage applied to the reflectron, relative to system ground. A counter electrode of the LEAP 6000 series atom probes. A local electrode guiding the ion flight path. Also called counter or extraction electrode. Acceleration voltage The type of aperture used when the local_electrode has an aperture or acts as an aperture in addition to acting as an extraction electrode. The local electrode is a component which combines functionalities of :ref:`NXlens_em`, :ref:`NXaperture`, if not even :ref:`NXdeflector`: * "n/a", use when no aperture is present in the experiment * "conical", conical aperture with a circular hole * "feedthrough", an aperture where the specimen protrudes through a circular hole * "custom", a user modified aperture, which is otherwise non-standard Detector for taking raw time-of-flight and ion/hit impact positions data. Amplitude of the signal detected on the multi-channel plate (MCP). This field should be used for storing the signal amplitude quantity within ATO files when the detector was an MCP. The ATO file format is used primarily by the atom probe group of the GPM in Rouen, France. The value can be extracted from the CRunHeader.fMcpEfficiency field of a CamecaRoot RHIT file. The value can be extracted from the CRunHeader.fMeshEfficiency field of a CamecaRoot RHIT file. Laser- and/or voltage-pulsing device to trigger ion removal. When the base class NXinstrument_apm is used in the NXapm application definition, the values for the following fields: * pulse_frequency * pulse_fraction * pulse_voltage * pulse_number * standing_voltage * pulse_energy * incidence_vector * pinhole_position * spot_position should be recorded in the order of, and assumed associated, with the pulse_id in an instance of :ref:`NXevent_data_apm`. Detail whereby ion extraction is triggered methodologically. Frequency with which the pulser fire(s). Fraction of the pulse_voltage that is applied in addition to the standing_voltage at peak voltage of a pulse. If a standing voltage is applied, this gives nominal pulse fraction (as a function of standing voltage). Otherwise, this field should not be present. Pulsed voltage, in laser pulsing mode this field can be omitted. Absolute number of pulses starting from the beginning of the experiment. Direct current voltage between the specimen and the (local electrode) in the case of local electrode atom probe (LEAP) instrument. Otherwise, the standing voltage applied to the sample, relative to system ground. Group to store details about components that enable laser pulsing strategies. When multiple sources are available, these should be named source1, source2; the LEAP 6000 series instruments have two sources. The majority of instruments still has one source. In this case the variable part "ID" can be omitted. Consequently the group should be named "source" when writing instance data. Atom probe microscopes use controlled laser, voltage, or a combination of pulsing strategies to trigger ion extraction via exciting and eventual field evaporation field emission of ion at the specimen surface. The wavelength of the radiation emitted by the source. Nominal power of the laser source while illuminating the specimen. Average energy of the laser at peak of each pulse. Path to pulse_id Details about specific positions along the laser beam which illuminates the (atom probe) specimen. Track time-dependent settings over the course of the measurement how the laser beam shines on the specimen, i.e. the mean vector is parallel to the laser propagation direction. Track time-dependent settings over the course of the measurement where the laser beam exits the focusing optics. Track time-dependent settings over the course of the measurement where the laser hits the specimen. Affine transformations which describe the geometry how the laser focusing optics/pinhole-attached coordinate system is defined, how it has to be transformed so that it aligns with the specimen coordinate system. The value can be extracted from the CRunHeader.CAnalysis.fSpecimenTemperature field of a CamecaRoot RHIT file. The space inside the atom probe along which ions pass nominally when they leave the specimen and travel to the detector. The value can be extracted from the CRunHeader.CLasHeader.fAnalysisPressure field of a CamecaRoot RHIT file. Free-text field for additional comments. Relevant quantities during a measurement with a LEAP system as were suggested by `T. Blum et al. <https://doi.org/10.1002/9781119227250.ch18>`_. Parameter that defines the rules and control loops whereby the pulser and other components of the instrument are controlled during evaporation. Parameter that assure maintenance of a significant yet not too high ion influx on the detector to avoid detection losses. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXlens_em.nxdl.xml0000644000077000000000000001171215046415443026127 0ustar00rosborn Base class for an electro-magnetic lens or a compound lens. For :ref:`NXtransformations` the origin of the coordinate system is placed in the center of the lens its polepiece, pinhole, or another point of reference. The origin should be specified in the :ref:`NXtransformations`. For details of electro-magnetic lenses in the literature see e.g. * `L. Reimer: Scanning Electron Microscopy <https://doi.org/10.1007/978-3-540-38967-5>`_ * `P. Hawkes: Magnetic Electron Lenses <https://link.springer.com/book/10.1007/978-3-642-81516-4>`_ * `Y. Liao: Practical Electron Microscopy and Database <https://www.globalsino.com/EM/>`_ Name of the lens. Ideally, use instances of ``identifierNAME`` to point to a resource that provides further details. If such a resource does not exist or should not be used, use this free text, although it is not recommended. Descriptor for the lens excitation when the exact technical details are unknown or not directly controllable as the control software of the microscope does not enable or was not configured to display these values for users. Although this value does not document the exact physical voltage or excitation, it can still give useful context to reproduce the lens setting, provided a properly working instrument and software sets the lens into a similar state to the technical level possible when no more information is available physically or accessible legally. Descriptor for the operation mode of the lens when other details are not directly controllable as the control software of the microscope does not enable or is not configured to display these values. Like value, the mode can only be interpreted for a specific microscope but can still be useful to guide users as to how to repeat the measurement. Excitation voltage of the lens. For dipoles it is a single number. For higher order multipoles, it is an array. Excitation current of the lens. For dipoles it is a single number. For higher-order multipoles, it is an array. Qualitative type of lens with respect to the number of pole pieces. Qualitative description of the lens based on the number of pole pieces. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXlog.nxdl.xml0000644000077000000000000001223014777236751025277 0ustar00rosborn Information recorded as a function of time. Description of information that is recorded against time. There are two common use cases for this: - When logging data such as temperature during a run - When data is taken in streaming mode data acquisition, i.e. just timestamp, value pairs are stored and correlated later in data reduction with other data, In both cases, NXlog contains the logged or streamed values and the times at which they were measured as elapsed time since a starting time recorded in ISO8601 format. The time units are specified in the units attribute. An optional scaling attribute can be used to accomodate non standard clocks. This method of storing logged data helps to distinguish instances in which a variable contains signal or axis coordinate values of plottable data, in which case it is stored in an :ref:`NXdata` group, and instances in which it is logged during the run, when it should be stored in an :ref:`NXlog` group. In order to make random access to timestamped data faster there is an optional array pair of ``cue_timestamp_zero`` and ``cue_index``. The ``cue_timestamp_zero`` will contain coarser timestamps than in the time array, say every five minutes. The ``cue_index`` will then contain the index into the time,value pair of arrays for that coarser ``cue_timestamp_zero``. Time of logged entry. The times are relative to the "start" attribute and in the units specified in the "units" attribute. Please note that absolute timestamps under unix are relative to ``1970-01-01T00:00:00.0Z``. The scaling_factor, when present, has to be applied to the time values in order to arrive at the units specified in the units attribute. The scaling_factor allows for arbitrary time units such as ticks of some hardware clock. Array of logged value, such as temperature. If this is a single value the dimensionality is nEntries. However, NXlog can also be used to store multi dimensional time stamped data such as images. In this example the dimensionality of values would be value[nEntries,xdim,ydim]. Array of raw information, such as thermocouple voltage Description of logged value estimated uncertainty (often used: standard deviation) of average_value estimated uncertainty (often used: standard deviation) of average_value Total time log was taken Timestamps matching the corresponding cue_index into the time, value pair. If missing start is assumed to be the same as for "time". If missing start is assumed to be the same as for "time". Index into the time, value pair matching the corresponding cue_timestamp_zero. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXmanipulator.nxdl.xml0000644000077000000000000002257215046415443027046 0ustar00rosborn Base class to describe the use of manipulators and sample stages. Name of the manipulator. A description of the manipulator. Type of manipulator, Hexapod, Rod, etc. Cryostat for cooling the sample (and, potentially, the whole manipulator). In case of a fixed or averaged cooling temperature, this is the scalar temperature setpoint. It can also be a 1D array of temperature setpoints (without time stamps). In the case of an experiment in which the temperature is changed and the setpoints are recorded with time stamps, this is an array of temperature setpoints. Temperature sensor measuring the sample temperature. In case of a single or averaged temperature measurement, this is the scalar temperature measured by the sample temperature sensor. It can also be a 1D array of measured temperatures (without time stamps). In the case of an experiment in which the temperature changes and is recorded with time stamps, this is an array of length m of temperatures. Device to heat the sample. In case of a fixed or averaged heating power, this is the scalar heater power. It can also be a 1D array of heater powers (without time stamps). In the case of an experiment in which the heater power is changed and recorded with time stamps, this is an array of length m of temperature setpoints. In case of a fixed or averaged temperature, this is the scalar temperature setpoint. It can also be a 1D array of temperature setpoints (without time stamps). In the case of an experiment in which the temperature is changed and the setpoints are recorded with time stamps, this is an array of length m of temperature setpoints. Ammeter measuring the drain current of the sample and sample holder. In case of a single or averaged drain current measurement, this is the scalar drain current measured between the sample and sample holder. It can also be an 1D array of measured currents (without time stamps). In the case of an experiment in which the current changes and is recorded with time stamps, this is an array of length m of currents. Actuator applying a voltage between sample holder and sample. In case of a fixed or averaged applied bias, this is the scalar voltage applied between sample and sample holder. It can also be an 1D array of voltage setpoints (without time stamps). In the case of an experiment in which the bias is changed and the setpoints are recorded with time stamps, this is an array of length m of voltage setpoints. Sensor measuring the voltage applied to sample and sample holder. In case of a single or averaged bias measurement, this is the scalar voltage measured between sample and sample holder. It can also be an 1D array of measured voltages (without time stamps). In the case of an experiment in which the bias changes and is recorded with time stamps, this is an array of length m of voltages. Any additional actuator on the manipulator used to control an external condition. Any additional sensors on the manipulator used to monitor an external condition. Class to describe the motors that are used in the manipulator. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXmirror.nxdl.xml0000644000077000000000000001444214777236751026037 0ustar00rosborn A beamline mirror or supermirror. mirror with a single material as a reflecting surface mirror with stacked, multiple layers as a reflecting surface description of this mirror Reflectivity as function of wavelength external material outside substrate The m value for a supermirror, which defines the supermirror regime in multiples of the critical angle of Nickel. An array describing the thickness of each layer A NXshape group describing the shape of the mirror Numerical description of the surface figure of the mirror. This group describes the shape of the beam line component Given a flat mirror, the reference plane is the plane which contains the "entry" surface of the mirror. The reference point of the mirror in the x and y axis is the centre of the mirror on that plane. The reference plane is orthogonal to the z axis and the location of this plane is the reference point on the z axis. The mirror faces negative z values. .. image:: mirror/mirror.png :width: 40% ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXmoderator.nxdl.xml0000644000077000000000000000673714777236751026531 0ustar00rosborn A neutron moderator "Engineering" position of moderator Effective distance as seen by measuring radiation. Note, it is recommended to use NXtransformations instead. whether the moderator is coupled The material used for coupling. Usually Cd. average/nominal moderator temperature log file of moderator temperature moderator pulse shape This group describes the shape of the moderator The reference point of the moderator is its center in the x and y axis. The reference point on the z axis is the surface of the moderator pointing towards the source (the negative part of the z axis). .. image:: moderator/moderator.png :width: 40% ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXmonitor.nxdl.xml0000644000077000000000000001267114777236751026216 0ustar00rosborn A monitor of incident beam data. It is similar to the :ref:`NXdata` groups containing monitor data and its associated axis coordinates, e.g. time_of_flight or wavelength in pulsed neutron instruments. However, it may also include integrals, or scalar monitor counts, which are often used in both in both pulsed and steady-state instrumentation. Count to a preset value based on either clock time (timer) or received monitor counts (monitor). Starting time of measurement Ending time of measurement preset value for time or monitor Distance of monitor from sample Range (X-axis, Time-of-flight, etc.) over which the integral was calculated Nominal reading to be used for normalisation purposes. Total integral monitor counts Time variation of monitor counts Time-of-flight Monitor efficiency Monitor data The rank (``dataRank``) of the ``data`` must satisfy ``1 <= dataRank <= NX_MAXRANK=32``. At least one ``dim`` must have length ``n``. Proportion of incident beam sampled by the monitor (0<x<1) Geometry of the monitor Elapsed actual counting time, can be an array of size ``np`` when scanning. This is not the difference of the calendar time but the time the instrument was really counting, without pauses or times lost due beam unavailability This group describes the shape of the beam line component The reference plane of the monitor contains the surface of the detector that faces the source and is the entry point of the beam. The reference point of the monitor in the x and y axis is its centre on this surface. The reference plane is orthogonal to the the z axis and the reference point on this z axis is where they intersect. .. image:: monitor/monitor.png :width: 40% ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXmonochromator.nxdl.xml0000644000077000000000000000772114777236751027416 0ustar00rosborn A wavelength defining device. This is a base class for everything which selects a wavelength or energy, be it a monochromator crystal, a velocity selector, an undulator or whatever. The expected units are: * wavelength: angstrom * energy: eV wavelength selected wavelength standard deviation wavelength standard deviation energy selected energy standard deviation energy standard deviation Energy dispersion at the exit slit. Wavelength dispersion at the exit slit. Size, position and shape of the entrance slit of the monochromator. Size, position and shape of the exit slit of the monochromator. This group describes the shape of the beam line component Use as many crystals as necessary to describe For diffraction grating based monochromators .. todo:: Add a definition for the reference point of a monochromator. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXnote.nxdl.xml0000644000077000000000000000574114777236751025474 0ustar00rosborn Any additional freeform information not covered by the other base classes. This class can be used to store additional information in a NeXus file e.g. pictures, movies, audio, additional text logs Author or creator of note Date note created/added Mime content type of note data field e.g. image/jpeg, text/plain, text/html Name of original file name if note was read from an external source Identifier of the resource if that resource that has been serialized. For example, the identifier to a resource in another database. Value of the hash that is obtained when running algorithm on the content of the resource referred to by ``identifierNAME``. Name of the algorithm whereby the ``checksum`` was computed. Examples: md5, sha256 Title of an image or other details of the note Sequence index of note, for placing a sequence of multiple **NXnote** groups in an order. Starts with 1. Binary note data - if text, line terminator is [CR][LF]. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXobject.nxdl.xml0000644000077000000000000002362214777236751025773 0ustar00rosborn This is the base object of NeXus. The groups and fields contained within this file are allowed to be present in any derived base class. If nameType="partial", the placeholders (e.g., FIELDNAME or GROUPNAME) can be replaced by the name of any object (field or group, respectively) that exists within the same group. NXlog group containing logged values of GROUPNAME. Target values of FIELDNAME. Uncertainties of FIELDNAME values. Weights of FIELDNAME values. Boolean mask of FIELDNAME values. The value is masked if set to 1. An identifier for a (persistent) resource. An identifier, provided by some authority, that has been assigned to an object described by this ``NXobject``. To be useful, the identifier must not be reassigned to a different real-world object. It is typical for there to be some mechanism to resolve an identifier, obtaining metadata about the object. Identifiers for which some guarantees exist regarding this resolution process are called persistent identifiers. Persistent identifiers are also known as PIDs. The type of identifier used. It is recommended to use the most specific type when describing the identifier. For example, all IGSNs (see below) are DOIs and all DOIs are Handles; however, an IGSN should have type IGSN (and not DOI or Hdl). Similarly, an ARK, Purl, ORCID and ROR identifiers should have their corresponding types and should not use the more generic URL identifier. Archival Resource Key. An ARK is a Uniform Resource Identifier (URI) designed to support long-term access to a variety of information objects. Syntax: https://NMA/ark:/NAAN/Name[Qualifier]. Brackets indicate optional elements. Example: https://example.org/ark:/12345/abcde Digital Object Identifier. A DOI is a unique alphanumeric string used to identify digital content. It consists of a prefix and a suffix, separated by a slash. Syntax: 10.XXXX/XXXXXX Example: 10.1107/S1600576714027575 A handle is a unique identifier that consists of a prefix indicating the naming authority and a suffix representing the local name of a resource. A handle is a unique identifier used to facilitate the identification and management of digital objects. It is composed of a prefix that indicates the naming authority and a suffix that specifies the resource's local name. This refers specifically to an ID in the Handle system operated by the Corporation for National Research Initiatives (CNRI). Syntax: prefix/identifier Example: 123456789/abc123 International Generic Sample Number. The IGSN is a unique identifier assigned to a specific sample or specimen in the context of scientific research. Since 2021, IGSNs are issued by DataCite, meaning that there are now DataCite-issued DOIs for all IGSNs, including those historical IGSNs issued beforehand. Therefore, the syntax is the same as for DOIs. Syntax: 10.XXXX/XXXXXX Example: 10.1107/S1600576714027575 ISNI is an ISO standard to uniquely identify individuals and organizations involved in creative work, including pseudonyms and other public personas. An ISNI-ID is made up of 16 digits, the last character being a check character. The check character may be either a decimal digit or the character “X”. A URL can be generated from the ISNI ID by combining it with the prefix https://isni.org/isni/, resulting in https://isni.org/isni/{ISNI-ID}. Syntax: 16 base-10 digits stored without any spaces. Example: 0000000121032683 International Standard Serial Number An ISSN is an 8-digit unique identifier used to distinguish a serial publication, whether in print or electronic form. The last character (a digit or 'X') serves as a check character, making the ISSN uniquely defined by its first seven digits. Syntax: NNNN-NNNC, where N a decimal digit character (i.e., in the set {0,1,2,...,9}), and C is in {0,1,2,...,9,X} Example: 1234-5678 or 1234-567X Linking ISSN The linking ISSN, or ISSN-L, is a specific ISSN that groups the different media of the same serial publication. Syntax: NNNN-NNNC, where N a decimal digit character (i.e., in the set {0,1,2,...,9}), and C is in {0,1,2,...,9,X} Example: 1234-5678 or 1234-567X Open Researcher and Contributor identifier. ORCID provides a free and persistent identifier that uniquely distinguishes authors and contributors in scientific research. Syntax: https://orcid.org/XXXX-XXXX-XXXX-XXXX Example: https://orcid.org/0000-0002-1825-0097 Persistent Uniform Resource Locator. A Persistent Uniform Resource Locator (PURL) is a type of URL designed to provide a stable, long-term reference to a web resource by using a resolver to redirect users to the resource's current location, even if it moves over time. A PURL has three parts: (1) a protocol, (2) a resolver address, and (3) a name. Syntax: https://purl.org/foo/bar Example: https://purl.org/dc/elements/1.1/title Research Organization Registry A ROR ID is a globally unique identifier for research organizations, enabling unambiguous linking of institutions across systems. Syntax: https://ror.org/{ROR-ID} Example: https://ror.org/052gg0110 Uniform Resource Locator Also known as web address, a URL is the address used to access a resource on the internet, specifying its location and the protocol to retrieve it. Syntax: scheme://domain:port/path?query_string#fragment_id Example: https://www.example.com/about Uniform Resource Name A URN is a unique, persistent identifier for a resource regardless of where it is stored. It is recommended that identifiers with more specific type attribute (such as DOI or ISSN) values should not be stored as a URN, even when this is valid. As an example, the URN doi:10.1107/S1600576714027575 is a valid URN-based representation for the DOI 10.1107/S1600576714027575, but it is recommended to use type="DOI" in this case. Syntax: urn:<namespace>:<namespace-specific-string>. The leading urn: sequence is case-insensitive. Example: urn:isbn:0000000000000 .. index:: plotting Declares which child group contains a path leading to a :ref:`NXdata` group or a group using a base class extending :ref:`NXdata`. It is recommended (as of NIAC2014) to use this attribute to help define the path to the default dataset to be plotted. See https://www.nexusformat.org/2014_How_to_find_default_data.html for a summary of the discussion. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXoff_geometry.nxdl.xml0000644000077000000000000000747314777236751027220 0ustar00rosborn These symbols will be used below. number of vertices in the shape number of faces in the shape number faces which are detecting surfaces or form the boundary of detecting volumes Geometry (shape) description. The format closely matches the Object File Format (OFF) which can be output by most CAD software. It can be used to describe the shape of any component, including detectors. In the case of detectors it can be used to define the shape of a single pixel, or, if the pixel shapes are non-uniform, to describe the shape of the whole detector. List of x,y,z coordinates for vertices. The origin of the coordinates is the position of the parent component, for example the NXdetector which the geometry describes. If the shape describes a single pixel for a detector with uniform pixel shape then the origin is the position of each pixel as described by the ``x/y/z_pixel_offset`` datasets in ``NXdetector``. List of indices of vertices in the ``vertices`` dataset to form each face, right-hand rule for face normal. The start index in ``winding_order`` for each face. List of pairs of index in the "faces" dataset and detector id. Face IDs in the first column, and corresponding detector IDs in the second column. This dataset should only be used only if the ``NXoff_geometry`` group is describing a detector. Note, the face indices must be in ascending order but need not be consecutive as not every face in faces need be a detecting surface or boundary of detecting volume. Can use multiple entries with the same detector id to define detector volumes. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXoptical_lens.nxdl.xml0000644000077000000000000001626115046415443027165 0ustar00rosborn Size of the wavelength array for which the refractive index of the material is given. Size of the wavelength array for which the refractive index of the coating is given. Size of the wavelength array for which the reflectance or transmission of the lens is given. Description of an optical lens. Type of the lens (e.g. concave, convex etc.). Is it a chromatic lens? Diameter of the lens. Properties of the substrate material of the lens. If the lens has a coating specify the coating material and its properties in 'coating'. Specify the substrate material of the lens. Thickness of the lens substrate at the optical axis. Complex index of refraction of the lens material. Specify at given wavelength (or energy, wavenumber etc.) values. If the lens has a coating describe the material and its properties. Some basic information can be found e.g. [here] (https://www.opto-e.com/basics/reflection-transmission-and-coatings). If the back and front side of the lens are coated with different materials, use separate COATING(NXsample) fields to describe the coatings on the front and back side, respectively. For example: coating_front(NXsample) and coating_back(NXsample). Specify the coating type (e.g. dielectric, anti-reflection (AR), multilayer coating etc.). Describe the coating material (e.g. MgF2). Thickness of the coating. Complex index of refraction of the coating. Specify at given spectral values (wavelength, energy, wavenumber etc.). Reflectance of the lens at given spectral values. Transmission of the lens at given spectral values. Focal length of the lens on the front side (first value), i.e. where the beam is incident, and on the back side (second value). Curvature radius of the lens. Instead of 'FACE' in the name of this field, the user is advised to specify for which surface (e.g. front or back) the curvature is provided: e.g. curvature_radius_front or curvature_radius_back. The front face is the surface on which the light beam is incident, while the back face is the one from which the light beam exits the lens. Abbe number (or V-number) of the lens. The numerical aperture of the lens. Magnification of the lens ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXoptical_window.nxdl.xml0000644000077000000000000001302115046415443027522 0ustar00rosborn A window of a cryostat, heater, vacuum chamber or a simple glass slide. This describes cryostat windows and other possible influences for ellipsometry measurements. For environmental measurements, the environment (liquid, vapor etc.) is enclosed in a cell, which has windows both in the direction of the source (entry window) and the detector (exit window) (looking from the sample). The windows also add a phase shift to the light altering the measured signal. This shift has to be corrected based on measuring a known sample (reference sample) or the actual sample of interest in the environmental cell. State if a window correction has been performed in 'window_effects_corrected'. Reference measurements should be considered as a separate experiment (with a separate NeXus file), and the reference data shall be :ref:`linked <Design-Links>` in ``reference_data_link``. The window is considered to be a part of the sample stage but also beam path. Hence, its position within the beam path should be defined by the 'depends_on' field. Was a window correction performed? If so, describe the window correction procedure in ``window_correction/procedure``. Type of effects due to this window on the measurement. Group to describe any window correction - if none performed, then omit this Describe when (before or after the main measurement + time stamp in 'date') and how the window effects have been corrected, i.e. either mathematically or by performing a reference measurement. In the latter case, provide the link to to the reference data in ``reference_data_file``. :ref:`External link <Design-Links>` to the data field in the NeXus file which describes the reference data if a reference measurement for window correction was performed. Ideally, the reference measurement was performed on the same sample, using the same conditions as for the actual measurement, with and, if possible, without windows. It should have been conducted as close in time to the actual measurement as possible. Ideally, the link uses the relative path with respect to the actual NeXus file. The material of the window. If you specified 'other' as material, describe here what it is. Thickness of the window. Angle of the window normal (outer) vs. the substrate normal (similar to the angle of incidence). ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXorientation.nxdl.xml0000644000077000000000000000477214777236751027065 0ustar00rosborn legacy class - recommend to use :ref:`NXtransformations` now Description for a general orientation of a component - used by :ref:`NXgeometry` Link to another object if we are using relative positioning, else absent The orientation information is stored as direction cosines. The direction cosines will be between the local coordinate directions and the reference directions (to origin or relative NXgeometry). Calling the local unit vectors (x',y',z') and the reference unit vectors (x,y,z) the six numbers will be [x' dot x, x' dot y, x' dot z, y' dot x, y' dot y, y' dot z] where "dot" is the scalar dot product (cosine of the angle between the unit vectors). The unit vectors in both the local and reference coordinates are right-handed and orthonormal. The pair of groups NXtranslation and NXorientation together describe the position of a component. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1748719305.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXparameters.nxdl.xml0000644000077000000000000000763515016653311026654 0ustar00rosborn Container for parameters used in processing or analysing data. Typically, this group is stored in a :ref:`NXprocess` group in order to contain parameters that are either inputs to or resulting from the process defined by the parent group. However, this base class can also be added to other groups for use in other contexts. The base class defines a number of attributes that can be used if the parameter values result from, e.g., fitting a function or model to the measured data. If multiple functions are used, there can be additional NXparameter groups for each one. The name of the model used in optimizing the parameter values. Fitting packages such as LMFIT (https://lmfit.github.io/lmfit-py/) provide models, which instantiate functions to be fitted to the data. If this attribute is provided, it is assumed that all the parameters in this group are associated with this model. A parameter that is used in or results from processing. The standard deviation of the parameter after optimizing its value. A string representing an expression that can be used to relate the parameter to another parameter's value. The format of this string is dependent on the program used to optimize the parameters and is not specified by NeXus. The initial value of the parameter used in optimization. The upper bound of the parameter used in optimization. The lower bound of the parameter used in optimization. True if the parameter was varied during optimization. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXpdb.nxdl.xml0000644000077000000000000001403514777236751025270 0ustar00rosborn A NeXus transliteration of a PDB file, to be validated only as a PDB rather than in NeXus. Use :ref:`NXpdb` to incorporate the information in an arbitrary PDB into a NeXus file. The main suggestion is to use this as a container class for a PDB entry to describe a sample in NXsample, but it may be more appropriate to place this higher in the hierarchy, say in NXentry. The structure has to follow the structure of a PDB with each PDB data block mapped to a NeXus group of class NXpdb, using a lowercase version of the data block name as the name of the NeXus group, each PDB category in that data block mapped to a NeXus group of class NXpdb and with each PDB column mapped to a NeXus field. Each column in a looped PDB category should always be presented as a 1-dimensional array. The columns in an unlooped PDB category should be presented as scalar values. If a PDB category specifies particular units for columns, the same units should beused for the corresponding fields. A PDB entry is unambigous when all information is carried as text. All text data should be presented as quoted strings, with the quote marks except for the null values "." or "?" For clarity in NXpdb form, numeric data may be presented using the numeric types specified in the mmCIF dictionary. In that case, if a PDB null value, "." or "?", is contained in a numeric column, the IEEE nan should be used for "?" and the IEEE inf should be used for ".". An arbitrary DDL2 CIF file can be represented in NeXus using NXpdb. However, if save frames are required, an NXpdb_class attribute with the value "CBF_cbfsf" is required for each NeXus group representing a save frame. NXpdb attributes are not required for other CIF components, but may be used to provide internal documentation. The nesting of NXpdb groups and datasets that correspond to a CIF with two categories and one saveframe, including the NXpdb_class attribues is:: (datablock1):NXpdb @NXpdb_class:CBF_cbfdb (category1):NXpdb @NXpdb_class:CBF_cbfcat (column_name1):[...] (column_name2):[...] (column_name3):[...] ... (category2):NXpdb @NXpdb_class:CBF_cbfcat (column_name4):[...] (column_name5):[...] (column_name6):[...] ... (saveframe1):NXpdb @NXpdb_class:CBF_cbfsf (category3):NXpdb @NXpdb_class:CBF_cbfcat (column_name7):[...] (column_name8):[...] (column_name9):[...] ... ... ... For example, a PDB entry that begins:: data_1YVA # _entry.id 1YVA # _audit_conform.dict_name mmcif_pdbx.dic _audit_conform.dict_version 5.279 _audit_conform.dict_location http://mmcif.pdb.org/dictionaries/ascii/mmcif_pdbx.dic # loop_ _database_2.database_id _database_2.database_code PDB 1YVA RCSB RCSB031959 WWPDB D_1000031959 # would produce:: sample:NXsample 1yva:NXpdb entry:NXpdb id:"1YVA" audit_conform:NXpdb dict_name:"mmcif_pdbx.dic" dict_version:"5.279" dict_location:"http://mmcif.pdb.org/dictionaries/ascii/mmcif_pdbx.dic" database_2:NXpdb database_id:["PDB","RCSB","WWPDB"] database_code:["1YVA","RCSB031959","D_1000031959"] another example is the following excerpt from pdb entry 9ins, giving the sequences of the two chains:: loop_ _entity_poly.entity_id _entity_poly.nstd_linkage _entity_poly.nstd_monomer _entity_poly.pdbx_seq_one_letter_code _entity_poly.pdbx_seq_one_letter_code_can _entity_poly.type 1 no no GIVEQCCTSICSLYQLENYCN GIVEQCCTSICSLYQLENYCN polypeptide(L) 2 no no FVNQHLCGSHLVEALYLVCGERGFFYTPKA FVNQHLCGSHLVEALYLVCGERGFFYTPKA polypeptide(L) which converts to:: entity_poly:NXpdb @NXpdb_class:CBF_cbfcat entity_id:["1", "2"] nstd_linkage:["no", "no"] nstd_monomer:["no", "no"] pdbx_seq_one_letter_code:["GIVEQCCTSICSLYQLENYCN","FVNQHLCGSHLVEALYLVCGERGFFYTPKA"] pdbx_seq_one_letter_code_can:["GIVEQCCTSICSLYQLENYCN","FVNQHLCGSHLVEALYLVCGERGFFYTPKA"] type:["polypeptide(L)", "polypeptide(L)"] ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXpeak.nxdl.xml0000644000077000000000000000716115046415443025430 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Rank of the dependent and independent data arrays (for multivariate scalar-valued fit). Base class for describing a peak, its functional form, and support values i.e., the discretization points at which the function has been evaluated. Human-readable label which specifies which concept/entity the peak represents/identifies. Position values along one or more data dimensions (to hold the values for the independent variable). The ``position`` field must have the same rank ``dimRank`` as the ``intensity`` field. Each individual dimension of ``position`` must have the same number of points as the corresponding dimension in the ``intensity`` field. This array holds the intensity/count values of the fitted peak at each position. The ``intensity`` field must have the same rank ``dimRank`` as the ``intensity`` field. Each individual dimension of ``position`` must have the same number of points as the corresponding dimension in the ``position`` field. The functional form of the peak. This could be a Gaussian, Lorentzian, Voigt, etc. Total area under the curve. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXpid_controller.nxdl.xml0000644000077000000000000002051214777236751027537 0ustar00rosborn A description of a feedback system in terms of the settings of a proportional-integral-derivative (PID) controller. Automated control of a physical quantity is often achieved by connecting the output of a sensor to an actuator (e.g. using a thermocouple to monitor the effect of a heater and influence the power provided to it). The physical quantity being operated on is typically referred to as the "Process Variable", with the desired value being the "Setpoint" (which may vary as a function of time) and the "Error Value" is the time-varying function of the difference between the Setpoint value and the concurrent measurement of the Process Variable (Error Value = Setpoint - Process Variable). A PID controller calculates an output value for use as an input signal to an actuator via the weighted sum of four terms: * Proportional: the current Error Value * Integral: the integral of the Error Value function * Derivative: the first derivative of the Error Value function * Feed Forward: A model of the physical system (optional) The weightings of these terms are given by the corresponding constants: * K_p * K_i * K_d * K_ff A classic PID controller only implements the P, I and D terms and the values of the K_p, K_i and K_d constants are sufficient to fully describe the behaviour of the feedback system implemented by such a PID controller. The inclusion of a Feed Forward term in a feedback system is a modern adaptation that aids optimisation of the automated control. It is not present in all PID controllers, but it is also not uncommon. Note that the ``NXpid_controller`` is designed to be a child object of the actuator that its output is connected to. The parent object representing the actuator is likely to be represented by an ``NXactuator`` or ``NXpositioner`` base class, but there is a wide variety of possible applications for PID controllers. Description of how the Process Value for the PID controller is produced by sensor(s) in the setup. For example, a set of sensors could be averaged over before feeding it back into the loop. The sensor representing the Process Value used in the feedback loop for the PID. In case multiple sensors were used, this NXsensor should contain the proper calculated/aggregated value. The actual timeseries data fed back into the PID controller. The Setpoint(s) used as an input for the PID controller. It can also be a link to an ``NXsensor.value`` field. Proportional gain constant. This constant determines how strongly the output value directly follows the current Error Value. When this constant dominates, the output value is linearly proportional to the Error Value. Integral gain constant. This constant determines how strongly the output value should react to an accumulated offset in the Error Value that should have been corrected previously. since the integral term is proportional to both the magnitude and persistence of the Error Value over time. Derivative gain constant. This constant determines how much the feedback system should anticipate the future value of the Error Value function through adjustment of the output value that is proportional to the rate of change (i.e. derivative) of the Error Value. This term is important for damping oscillations in the feedback system. Feed Forward gain constant. This constant determines how much the feedback system should rely on a calculated output value to achieve the desired Process Variable value. A Feed Forward system uses a model of the physical system to calculate an appropriate output value to achieve a desired Setpoint value. A description of this model should be provided in the ``feed_forward_model`` field. A description of the model used for the Feed Forward part of the feedback system. Note that such models typically involve the Setpoint value, but not the Error Value. The simplest model is simply proportional to the Setpoint value. For example, the position (Process Variable) of a sample is measured by a a linear optical encoder (sensor) and manipulated by a piezoelectric scanning stage (actuator). The corresponding Feed Forward model could be that the output value (voltage applied to the piezo) is proportional to the Setpoint value (measured position of the sample). A complex model could involve any number of input variables, mathematical functions, and coefficients in order to describe the physical system relevant to the PID controller. The Error Value of PID feedback system is normally constructed in terms of the correction needed to bring the Process Variable towards a match with the Setpoint. This "direct" control action means that a measurement of the Process Variable that is lower than the Setpoint results in a positive Error Value and a generally positive control output that tells the actuator to push the value of the Process Variable upwards. In some implementations, the actuator will respond to a more positive control output by pushing the Process Variable towards lower values (e.g. a Peltier cooler) and so the output of the feedback system must be reversed to match the behaviour of the physical system. A feedback system may also be implemented with reverse action in order to ensure that failures (e.g. disconnected sensor output or actuator input) result in a safe state (e.g. a valve should be left open to release pressure). ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXpinhole.nxdl.xml0000644000077000000000000000365514777236751026167 0ustar00rosborn A simple pinhole. For more complex geometries, :ref:`NXaperture` should be used. The reference direction of the pinhole is parallel with the z axis. The reference point of the pinhole is its center in the x and y axis. The reference point on the z axis is the plane which overlaps the side of the opening of the pin hole pointing towards the source (minus on the z axis). .. image:: pinhole/pinhole.png :width: 40% Size of the circular hole defining the transmitted beam size. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXpolarizer.nxdl.xml0000644000077000000000000000406314777236751026532 0ustar00rosborn A spin polarizer. one of these values: "crystal", "supermirror", "3He" description of the composition of the polarizing material [hkl] values of nominal reflection polarizing efficiency .. todo:: Add a definition for the reference point of a polarizer. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXpositioner.nxdl.xml0000644000077000000000000000657214777236751026725 0ustar00rosborn A generic positioner such as a motor or piezo-electric transducer. symbolic or mnemonic name (one word) description of positioner best known value of positioner - need [n] as may be scanned raw value of positioner - need [n] as may be scanned targeted (commanded) value of positioner - need [n] as may be scanned maximum allowable difference between target_value and value minimum allowed limit to set value maximum allowed limit to set value velocity of the positioner (distance moved per unit time) time to ramp the velocity up to full speed Hardware device record, e.g. EPICS process variable, taco/tango ... .. todo:: Add a definition for the reference point of a positioner. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1751925833.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXprocess.nxdl.xml0000644000077000000000000000533115033042111026143 0ustar00rosborn The :ref:`NXprocess` class describes an operation used to process data as part of an analysis workflow, providing information such as the software used, the date of the operation, the input parameters, and the resulting data. Name of the program used Sequence index of processing, for determining the order of multiple **NXprocess** steps. Starts with 1. Version of the program used Date and time of processing. The note will contain information about how the data was processed or anything about the data provenance. The contents of the note can be anything that the processing code can understand, or simple text. The name will be numbered to allow for ordering of steps. Parameters used in performing the data analysis. The data resulting from the operation. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXprogram.nxdl.xml0000644000077000000000000000410415046415443026151 0ustar00rosborn Base class to describe a software tool or library. Given name of the program. Program can be a commercial one a script, or a library or a library component. Program version plus build number, or commit hash. Description of an ideally ever persistent resource where the source code of the program or this specific compiled version of the program can be found so that the program yields repeatably exactly the same numerical and categorical results. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXpump.nxdl.xml0000644000077000000000000000556015046415443025472 0ustar00rosborn Device to reduce an atmosphere to a controlled pressure. Principle type of the pump. The minimum pressure achievable in a chamber after it has been pumped down for an extended period. The material being moved by the pump. Pumps intending to create a vacuum should state "vacuum" as the medium, while pumps having the primary purpose of creating a flow or pressure of gas should state "gas" as the medium. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXreflections.nxdl.xml0000644000077000000000000004661414777236751027050 0ustar00rosborn number of reflections number of experiments Reflection data from diffraction experiments The experiments from which the reflection data derives The h component of the miller index Describes the dataset The k component of the miller index Describes the dataset The l component of the miller index Describes the dataset The id of the experiment which resulted in the reflection. If the value is greater than 0, the experiments must link to a multi-experiment NXmx group Describes the dataset The id of the reflection. Multiple partials from the same reflection should all have the same id Describes the dataset Is the reflection entering or exiting the Ewald sphere Describes the dataset The detector module on which the reflection was recorded Describes the dataset Status flags describing the reflection. This is a bit mask. The bits in the mask follow the convention used by DIALS, and have the following names: === ========================================== bit name === ========================================== 0 ``predicted`` 1 ``observed`` 2 ``indexed`` 3 ``used_in_refinement`` 4 ``strong`` 5 ``reference_spot`` 6 ``dont_integrate`` 7 ``integrated_sum`` 8 ``integrated_prf`` 9 ``integrated`` 10 ``overloaded`` 11 ``overlapped`` 12 ``overlapped_fg`` 13 ``in_powder_ring`` 14 ``foreground_includes_bad_pixels`` 15 ``background_includes_bad_pixels`` 16 ``includes_bad_pixels`` 17 ``bad_shoebox`` 18 ``bad_spot`` 19 ``used_in_modelling`` 20 ``centroid_outlier`` 21 ``failed_during_background_modelling`` 22 ``failed_during_summation`` 23 ``failed_during_profile_fitting`` 24 ``bad_reference`` === ========================================== Describes the dataset The resolution of the reflection Describes the dataset The partiality of the reflection. Dividing by this number will inflate the measured intensity to the full reflection equivalent. Describes the dataset The frame on which the bragg peak of the reflection is predicted Describes the dataset The x position at which the bragg peak of the reflection is predicted Describes the dataset The y position at which the bragg peak of the reflection is predicted Describes the dataset The phi angle at which the bragg peak of the reflection is predicted Describes the dataset The x pixel position at which the bragg peak of the reflection is predicted Describes the dataset The y pixel position at which the bragg peak of the reflection is predicted Describes the dataset The estimate of the frame at which the central impact of the reflection was recorded Describes the dataset The variance on the estimate of the frame at which the central impact of the reflection was recorded Describes the dataset The standard deviation of the estimate of the frame at which the central impact of the reflection was recorded Describes the dataset The estimate of the pixel x position at which the central impact of the reflection was recorded Describes the dataset The variance on the estimate of the pixel x position at which the central impact of the reflection was recorded Describes the dataset The standard deviation of the estimate of the pixel x position at which the central impact of the reflection was recorded Describes the dataset The estimate of the pixel y position at which the central impact of the reflection was recorded Describes the dataset The variance on the estimate of the pixel y position at which the central impact of the reflection was recorded Describes the dataset The standard deviation of the estimate of the pixel y position at which the central impact of the reflection was recorded Describes the dataset The estimate of the phi angle at which the central impact of the reflection was recorded Describes the dataset The variance on the estimate of the phi angle at which the central impact of the reflection was recorded Describes the dataset The standard deviation of the estimate of the phi angle at which the central impact of the reflection was recorded Describes the dataset The estimate of the x position at which the central impact of the reflection was recorded Describes the dataset The variance on the estimate of the x position at which the central impact of the reflection was recorded Describes the dataset The standard deviation of the estimate of the x position at which the central impact of the reflection was recorded Describes the dataset The estimate of the y position at which the central impact of the reflection was recorded Describes the dataset The variance on the estimate of the y position at which the central impact of the reflection was recorded Describes the dataset The standard deviation of the estimate of the y position at which the central impact of the reflection was recorded Describes the dataset The bounding box around the recorded recorded reflection. Should be an integer array of length 6, where the 6 values are pixel positions or frame numbers, as follows: ===== =========================== index meaning ===== =========================== 0 The lower pixel x position 1 The upper pixel x position 2 The lower pixel y position 3 The upper pixel y position 4 The lower frame number 5 The upper frame number ===== =========================== Describes the dataset The mean background under the reflection peak Describes the dataset The estimate of the reflection intensity by profile fitting Describes the dataset The variance on the estimate of the reflection intensity by profile fitting Describes the dataset The standard deviation of the estimate of the reflection intensity by profile fitting Describes the dataset The estimate of the reflection intensity by summation Describes the dataset The variance on the estimate of the reflection intensity by summation Describes the dataset The standard deviation of the estimate of the reflection intensity by summation Describes the dataset The LP correction factor to be applied to the reflection intensities Describes the dataset The correlation of the reflection profile with the reference profile used in profile fitting Describes the dataset An adjacency list specifying the spatial overlaps of reflections. The adjacency list is specified using an array data type where the elements of the array are the indices of the adjacent overlapped reflection Describes the dataset Polar angle of reflection centroid, following the NeXus simple (spherical polar) coordinate system Describes the dataset Azimuthal angle of reflection centroid, following the NeXus simple (spherical polar) coordinate system Describes the dataset ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXregistration.nxdl.xml0000644000077000000000000000403514777236751027234 0ustar00rosborn Describes image registration procedures. Has the registration been applied? Specifies the position by pointing to the last transformation in the transformation chain in the NXtransformations group. To describe the operations of image registration (combinations of rigid translations and rotations) Description of the procedures employed. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXresolution.nxdl.xml0000644000077000000000000001167615046415443026721 0ustar00rosborn Describes the resolution of a physical quantity. The physical quantity of the resolution, e.g., energy, momentum, time, area, etc. The process by which the resolution was determined. Additional details of the estimate or description of the calibration procedure The resolution of the physical quantity. Standard deviation of the resolution of the physical quantity. Ratio of the resolution at a specified measurand value to that measurand value. Standard deviation of the relative resolution of the physical quantity. The response of the instrument or part of the instrument to a infinitesimally sharp input signal along the physical quantity of this group. This is also sometimes called instrument response function for time resolution or point spread function for spatial response. The resolution is typically determined by taking the full width at half maximum (FWHM) of the response function. This could have an AXISNAME field ```input``` (the input axis or grid of the response function) and a ``DATA`` field ```magnitude```. Both of these should have the same unit. The dimensions should match those of the :ref:`resolution </NXresolution/resolution-field>` field. Symbols linking to another path in the NeXus tree to be referred to from the `resolution_formula_description` field. The ``TERM`` should be a valid path inside this application definition, i.e., of the form /entry/instrument/my_part/my_field. A description of the resolution formula to determine the resolution from a set of symbols as entered by the `formula_...` fields. This should be an english description of the math used. .. index:: plotting Declares which child group contains a path leading to a :ref:`NXdata` group. It is recommended (as of NIAC2014) to use this attribute to help define the path to the default dataset to be plotted. See https://www.nexusformat.org/2014_How_to_find_default_data.html for a summary of the discussion. For storing details and data of a calibration to derive a resolution from data. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXroi_process.nxdl.xml0000644000077000000000000000466215046415443027042 0ustar00rosborn Base class to report on the characterization of an area or volume of material. This area or volume of material is considered a region-of-interest (ROI). This base class should be used when the characterization was achieved by processing data from experiment or computer simulations into models of the microstructure of the material and the properties of the material or its crystal defects within this ROI. Microstructural features is a narrow synonym for these crystal defects. This base class can also be used to store data and metadata of the representation of the ROI, i.e. its discretization and shape. Methods from computational geometry are typically used for defining a discretization of the area and volume. Do not confuse this base class with :ref:`NXregion`. The purpose of the :ref:`NXregion` base class is to document data access i.e. I/O pattern on arrays. Therefore, concepts from :ref:`NXregion` operate in data space rather than in real or simulated real space. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXroot.nxdl.xml0000644000077000000000000001351414777236751025507 0ustar00rosborn The root of a NeXus file. In the NeXus standard, only NXentry groups are allowed at the root level of a file, although it is permitted to include additional groups and fields that are not part of the NeXus standard and will not be validated by NeXus tools. NeXus defines a number of root-level attributes that can be used to annotate the NeXus tree. Note that NXroot is the only base class that does not inherit from the NXobject class, since the latter permits the inclusion of NeXus objects that are not allowed at the root level. Date and time file was originally created File name of original NeXus file Date and time of last file change at close Version of NeXus API used in writing the file. Note that this is different from the version of the base class or application definition version number. A repository containing the application definitions used for creating this file. If the ``NeXus_release`` attribute contains a commit distance and hash, this should refer to this repository. The version of NeXus definitions used in writing the file. This can either be a date-based NeXus release (e.g., YYYY.MM), see https://github.com/nexusformat/definitions/releases or a version tag that includes additional development information, such as a commit distance and a Git hash. This is typically formatted as `vYYYY.MM.post1.dev<commit-distance>-g<git-hash>`, where `YYYY.MM` refers to the base version of the NeXus definitions. `post1.dev<commit-distance>` indicates that the definitions are based on a commit after the base version (post1), with `<commit-distance>` being the number of commits since that version. `g<git-hash>` is the abbreviated Git hash that identifies the specific commit of the definitions being used. If the version includes both a commit distance and a Git hash, the ``NeXus_repository`` attribute must be included, specifying the URL of the repository containing that version. Version of HDF (version 4) library used in writing the file Version of HDF5 library used in writing the file. Note this attribute is spelled with uppercase "V", different than other version attributes. Version of XML support library used in writing the XML file Version of h5py Python package used in writing the file facility or program where file originated Version of facility or program used in writing the file entries .. index:: find the default plottable data .. index:: plotting .. index:: default attribute value Declares which :ref:`NXentry` group contains the data to be shown by default. It is used to resolve ambiguity when more than one :ref:`NXentry` group exists. The value :ref:`names <validItemName>` the default :ref:`NXentry` group. The value must be the name of a child of the current group. The child must be a NeXus group or a link to a NeXus group. It is recommended (as of NIAC2014) to use this attribute to help define the path to the default dataset to be plotted. See https://www.nexusformat.org/2014_How_to_find_default_data.html for a summary of the discussion. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXsample.nxdl.xml0000644000077000000000000003511714777236751026010 0ustar00rosborn symbolic array lengths to be coordinated between various fields number of compositions number of temperatures number of values in applied electric field number of values in applied magnetic field number of values in applied pressure field number of values in applied stress field Any information on the sample. This could include scanned variables that are associated with one of the data dimensions, e.g. the magnetic field, or logged data, e.g. monitored temperature vs elapsed time. Descriptive name of sample The chemical formula specified using CIF conventions. Abbreviated version of CIF standard: * Only recognized element symbols may be used. * Each element symbol is followed by a 'count' number. A count of '1' may be omitted. * A space or parenthesis must separate each cluster of (element symbol + count). * Where a group of elements is enclosed in parentheses, the multiplier for the group must follow the closing parentheses. That is, all element and group multipliers are assumed to be printed as subscripted numbers. * Unless the elements are ordered in a manner that corresponds to their chemical structure, the order of the elements within any group or moiety depends on whether or not carbon is present. * If carbon is present, the order should be: - C, then H, then the other elements in alphabetical order of their symbol. - If carbon is not present, the elements are listed purely in alphabetic order of their symbol. * This is the *Hill* system used by Chemical Abstracts. Sample temperature. This could be a scanned variable Applied electric field Applied magnetic field Applied external stress field Applied pressure Sample changer position Crystallography unit cell parameters a, b, and c Crystallography unit cell parameters alpha, beta, and gamma Unit cell parameters (lengths and angles) Volume of the unit cell This will follow the Busing-Levy convention: W. R. Busing and H. A. Levy (1967). Acta Cryst. 22, 457-464 Orientation matrix of single crystal sample using Busing-Levy convention: W. R. Busing and H. A. Levy (1967). Acta Cryst. 22, 457-464 UB matrix of single crystal sample using Busing-Levy convention: W. R. Busing and H. A. Levy (1967). Acta Cryst. 22, 457-464. This is the multiplication of the orientation_matrix, given above, with the :math:`B` matrix which can be derived from the lattice constants. Mass of sample Density of sample Relative Molecular Mass of sample The atmosphere will be one of the components, which is where its details will be stored; the relevant components will be indicated by the entry in the sample_component member. Description of the sample Date of preparation of the sample The position and orientation of the center of mass of the sample Details of beam incident on sample - used to calculate sample/beam interaction point One group per sample component This is the perferred way of recording per component information over the n_comp arrays Details of the component of the sample and/or can Type of component Concentration of each component Volume fraction of each component Scattering length density of each component In case it is all we know and we want to record/document it Crystallographic space group Crystallographic point group, deprecated if space_group present Path length through sample/can for simple case when it does not vary with scattering direction Thickness of a beam entry/exit window on the can (mm) - assumed same for entry and exit sample thickness As a function of Wavelength temperature_log.value is a link to e.g. temperature_env.sensor1.value_log.value Additional sample temperature environment information magnetic_field.value is a link to e.g. magnetic_field_env.sensor1.value magnetic_field_log.value is a link to e.g. magnetic_field_env.sensor1.value_log.value Additional sample magnetic environment information value sent to user's sample setup logged value (or logic state) read from user's setup 20 character fixed length sample description for legends Optional rotation angle for the case when the powder diagram has been obtained through an omega-2theta scan like from a traditional single detector powder diffractometer. Note, it is recommended to use NXtransformations instead. Translation of the sample along the X-direction of the laboratory coordinate system Note, it is recommended to use NXtransformations instead. Translation of the sample along the Z-direction of the laboratory coordinate system. Note, it is recommended to use NXtransformations instead. Any positioner (motor, PZT, ...) used to locate the sample This group describes the shape of the sample Physical form of the sample material. Examples include single crystal, foil, pellet, powder, thin film, disc, foam, gas, liquid, amorphous. Any environmental or external stimuli/measurements. These can include, among others: applied pressure, surrounding gas phase and gas pressure, external electric/magnetic/mechanical fields, temperature, ... A set of physical processes that occurred to the sample prior/during experiment. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXsample_component.nxdl.xml0000644000077000000000000001373215046415443030054 0ustar00rosborn symbolic array lengths to be coordinated between various fields number of temperatures number of values in applied electric field number of values in applied magnetic field number of values in applied pressure field number of values in applied stress field One group like this per component can be recorded for a sample consisting of multiple components. Descriptive name of sample component The chemical formula specified using CIF conventions. Abbreviated version of CIF standard: * Only recognized element symbols may be used. * Each element symbol is followed by a 'count' number. A count of '1' may be omitted. * A space or parenthesis must separate each cluster of (element symbol + count). * Where a group of elements is enclosed in parentheses, the multiplier for the group must follow the closing parentheses. That is, all element and group multipliers are assumed to be printed as subscripted numbers. * Unless the elements are ordered in a manner that corresponds to their chemical structure, the order of the elements within any group or moiety depends on whether or not carbon is present. * If carbon is present, the order should be: - C, then H, then the other elements in alphabetical order of their symbol. - If carbon is not present, the elements are listed purely in alphabetic order of their symbol. * This is the *Hill* system used by Chemical Abstracts. Crystallography unit cell parameters a, b, and c Crystallography unit cell parameters alpha, beta, and gamma Volume of the unit cell This will follow the Busing and Levy convention from Acta.Crysta v22, p457 (1967) Orientation matrix of single crystal sample component. This will follow the Busing and Levy convention from Acta.Crysta v22, p457 (1967) Mass of sample component Density of sample component Relative Molecular Mass of sample component Description of the sample component Volume fraction of component Scattering length density of component In case it is all we know and we want to record/document it Crystallographic space group Crystallographic point group, deprecated if space_group present As a function of Wavelength A set of physical processes that occurred to the sample component prior/during experiment. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXsensor.nxdl.xml0000644000077000000000000001342414777236751026035 0ustar00rosborn A sensor used to monitor an external condition The condition itself is described in :ref:`NXenvironment`. Sensor identification code/model number Name for the sensor Short name of sensor used e.g. on monitor display program where sensor is attached to ("sample" | "can") Defines the axes for logged vector quantities if they are not the global instrument axes. name for measured signal The type of hardware used for the measurement. Examples (suggestions but not restrictions): :Temperature: J | K | T | E | R | S | Pt100 | Rh/Fe :pH: Hg/Hg2Cl2 | Ag/AgCl | ISFET :Ion selective electrode: specify species; e.g. Ca2+ :Magnetic field: Hall :Surface pressure: wilhelmy plate Is data collection controlled or synchronised to this quantity: 1=no, 0=to "value", 1=to "value_deriv1", etc. Upper control bound of sensor reading if using run_control Lower control bound of sensor reading if using run_control nominal setpoint or average value - need [n] as may be a vector Nominal/average first derivative of value e.g. strain rate - same dimensions as "value" (may be a vector) Nominal/average second derivative of value - same dimensions as "value" (may be a vector) Time history of sensor readings Time history of first derivative of sensor readings Time history of second derivative of sensor readings For complex external fields not satisfied by External_field_brief This group describes the shape of the sensor when necessary. .. index:: plotting Declares which child group contains a path leading to a :ref:`NXdata` group. It is recommended (as of NIAC2014) to use this attribute to help define the path to the default dataset to be plotted. See https://www.nexusformat.org/2014_How_to_find_default_data.html for a summary of the discussion. .. todo:: Add a definition for the reference point of a sensor. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXshape.nxdl.xml0000644000077000000000000000622314777236751025623 0ustar00rosborn legacy class - (used by :ref:`NXgeometry`) - the shape and size of a component. This is the description of the general shape and size of a component, which may be made up of ``numobj`` separate elements - it is used by the :ref:`NXgeometry` class general shape of a component physical extent of the object along its local axes (after NXorientation) with the center of mass at the local origin (after NXtranslation). The meaning and location of these axes will vary according to the value of the "shape" variable. ``nshapepar`` defines how many parameters: - For "nxcylinder" type the parameters are (diameter,height) and a three value orientation vector of the cylinder. - For the "nxbox" type the parameters are (length,width,height). - For the "nxsphere" type the parameters are (diameter). - For nxcone cone half aperture - For nxelliptical, semi-major axis, semi-minor-axis, angle of major axis and pole - For nxtoroidal, major radius, minor radius - For nxparabolic, parabolic parameter a - For nxpolynomial, an array of polynom coefficients, the dimension of the array encodes the degree of the polynom ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXslit.nxdl.xml0000644000077000000000000000446514777236751025504 0ustar00rosborn A simple slit. For more complex geometries, :ref:`NXaperture` should be used. If desired the location of the slit can also be described relative to an NXbeam, which will allow a simple description of a non-centred slit. The reference plane of the slit is orthogonal to the z axis and includes the surface that is the entry surface of the slit. The reference point of the slit is the centre of the slit opening in the x and y axis on the reference plane. The reference point on the z axis is the reference plane. .. image:: slit/slit.png :width: 40% Size of the gap opening in the first dimension of the local coordinate system. Size of the gap opening in the second dimension of the local coordinate system. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXsource.nxdl.xml0000644000077000000000000002241614777236751026025 0ustar00rosborn Radiation source emitting a beam. Examples include particle sources (electrons, neutrons, protons) or sources for electromagnetic radiation (photons). This base class can also be used to describe neutron or x-ray storage ring/facilities. Effective distance from sample Distance as seen by radiation from sample. This number should be negative to signify that it is upstream of the sample. Name of source short name for source, perhaps the acronym type of radiation source (pick one from the enumerated list and spell exactly) type of radiation probe (pick one from the enumerated list and spell exactly) Source power Source emittance (nm-rad) in X (horizontal) direction. Source emittance (nm-rad) in Y (horizontal) direction. particle beam size in x particle beam size in y Source intensity/area (example: s-1 cm-2) Source energy. Typically, this would be the energy of the emitted beam. For storage rings, this would be the particle beam energy. Accelerator, X-ray tube, or storage ring current Accelerator voltage Frequency of pulsed source Period of pulsed source Pulsed source target material any source/facility related messages/events that occurred during the experiment For storage rings, description of the bunch pattern. This is useful to describe irregular bunch patterns. name of the bunch pattern For storage rings, the number of bunches in use. For storage rings, temporal length of the bunch For storage rings, time between bunches temporal width of source pulse source pulse shape source operating mode for storage rings for storage rings Is the synchrotron operating in top_up mode? For storage rings, the current at the end of the most recent injection. date and time of the most recent injection. The wavelength of the radiation emitted by the source. For pulsed sources, the energy of a single pulse. For pulsed sources, the pulse energy divided by the pulse duration Material of the anode (for X-ray tubes). Filament current (for X-ray tubes). Emission current of the generated beam. Gas pressure inside ionization source. Single instance or list of instances of NXsource pointing to the sources from which a beam originated to reach this source. This can be used, for example, for secondary sources to describe which other source(s) they are derived from. An example is the white light source in transient absorption spectroscopy, which is a supercontinuum crystal that is pumped by a another laser. In case of a primary source, this field should not be filled. "Engineering" location of source. The size and position of an aperture inside the source. Individual electromagnetic lenses inside the source. Deflectors inside the source. This group describes the shape of the beam line component The wavelength or energy distribution of the source The reference point of the source plane is its center in the x and y axis. The source is considered infinitely thin in the z axis. .. image:: source/source.png :width: 40% ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXspectrum.nxdl.xml0000644000077000000000000004567715046415443026370 0ustar00rosborn Number of spectra in the stack, for stacks the slowest dimension. Number of image points along the slower dimension (k equivalent to z). Number of image points along the slow dimension (j equivalent to y). Number of image points along the fast dimension (i equivalent to x). Number of energy bins (always the fastest dimension). Base class container for reporting a set of spectra. The mostly commonly used scanning methods are supported. That is one-, two-, three-dimensional ROIs discretized using regular Euclidean tilings. Use stack for all other tilings. Details how spectra were processed from the detector readings. Resolvable data artifact (e.g. filename) from which all values in the :ref:`NXdata` instances in this :ref:`NXspectrum` were loaded during parsing. Possibility to document from which specific other serialized resource as the source pieces of information were processed when using NeXus as a semantic file format to serialize that information differently. The group in combination with an added field *context* therein adds context. Reference to a location inside the artifact that points to the specific group of values that were processed if the artifacts contains several groups of values and thus further resolving of ambiguities is required. Imaging (data collection) mode of the instrument during acquisition of the data in this :ref:`NXspectrum` instance. Link or name of an :ref:`NXdetector` instance with which the data were collected. One spectrum for a point of a 0d ROI. Also known as spot measurement. Counts Counts Energy axis Energy One spectrum for each point of a 1d ROI. Counts Counts Point coordinate along the fast dimension Point coordinate along the fast dimension Energy axis Energy One spectrum for each scan point of 2d ROI. Counts Counts Point coordinate along the slow dimension Point coordinate along the slow dimension Point coordinate along the fast dimension Point coordinate along the fast dimension Energy axis Energy One spectrum for point of a 3d ROI. Counts Counts Point coordinate along the slower dimension Point coordinate along the slower dimension Point coordinate along the slow dimension Point coordinate along the slow dimension Point coordinate along the fast dimension Point coordinate along the fast dimension Energy axis Energy Multiple instances of spectrum_0d. Counts Counts Group identifier Group identifier Spectrum identifier Spectrum identifier Energy axis Energy Multiple instances of spectrum_2d. Counts Counts Group identifier Group identifier Spectrum identifier Spectrum identifier Point coordinate along the slow dimension Point coordinate along the slow dimension Point coordinate along the fast dimension Point coordinate along the fast dimension Energy axis Energy Multiple instances of spectrum_3d. Counts Counts Group identifier Group identifier Spectrum identifier Spectrum identifier Point coordinate along the slower dimension Point coordinate along the slower dimension Point coordinate along the slow dimension Point coordinate along the slow dimension Point coordinate along the fast dimension Point coordinate along the fast dimension Energy axis Energy ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXspindispersion.nxdl.xml0000644000077000000000000000602415046415443027556 0ustar00rosborn Class to describe spin filters in photoemission experiments. Type of spin detector, VLEED, SPLEED, Mott, etc. Figure of merit of the spin detector Effective Shermann function, calibrated spin selectivity factor Energy of the spin-selective scattering Angle of the spin-selective scattering Name of the target A set of activities that occurred to the ``scattering_target`` prior to/during the. experiment. For example, this group can be used to describe the preparation of the ``scattering_target``. Preparation procedure of the spin target Deflectors in the spin dispersive section Individual lenses in the spin dispersive section ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXsubentry.nxdl.xml0000644000077000000000000001562414777236751026403 0ustar00rosborn .. index:: find the default plottable data .. index:: plotting .. index:: default attribute value Declares which :ref:`NXdata` group contains the data to be shown by default. It is used to resolve ambiguity when one :ref:`NXdata` group exists. The value :ref:`names <validItemName>` the default :ref:`NXentry` group. The value must be the name of a child of the current group. The child must be a NeXus group or a link to a NeXus group. For more information about how NeXus identifies the default plottable data, see the :ref:`Find Plottable Data, v3 <Find-Plottable-Data-v3>` section. Group of multiple application definitions for "multi-modal" (e.g. SAXS/WAXS) measurements. ``NXsubentry`` is a base class virtually identical to :ref:`NXentry` and is used as the (overlay) location for application definitions. Use a separate ``NXsubentry`` for each application definition. To use ``NXsubentry`` with a hypothetical application definition called ``NXmyappdef``: * Create a group with attribute ``NX_class="NXsubentry"`` * Within that group, create a field called ``definition="NXmyappdef"``. * There are two optional attributes of definition: ``version`` and ``URL`` The intended use is to define application definitions for a multi-modal (a.k.a. multi-technique) :ref:`NXentry`. Previously, an application definition replaced :ref:`NXentry` with its own definition. With the increasing popularity of instruments combining multiple techniques for data collection (such as SAXS/WAXS instruments), it was recognized the application definitions must be entered in the NeXus data file tree as children of :ref:`NXentry`. ISIS Muon IDF_Version Extended title for entry Unique identifier for the experiment, defined by the facility, possibly linked to the proposals Brief summary of the experiment, including key objectives. Description of the full experiment (document in pdf, latex, ...) User or Data Acquisition defined group of NeXus files or :ref:`NXentry` Brief summary of the collection, including grouping criteria. unique identifier for the measurement, defined by the facility. Official NeXus NXDL schema to which this subentry conforms NXDL version number URL of NXDL file Local NXDL schema extended from the subentry specified in the ``definition`` field. This contains any locally-defined, additional fields in the subentry. NXDL version number URL of NXDL file Starting time of measurement Ending time of measurement Duration of measurement Time transpired actually collecting data i.e. taking out time when collection was suspended due to e.g. temperature out of range Such as "2007-3". Some user facilities organize their beam time into run cycles. Name of program used to generate this file Program version number configuration of the program Revision id of the file due to re-calibration, reprocessing, new analysis, new instrument definition format, ... This is the flightpath before the sample position. This can be determined by a chopper, by the moderator or the source itself. In other words: it the distance to the component which gives the T0 signal to the detector electronics. If another component in the NXinstrument hierarchy provides this information, this should be a link. Notes describing entry A small image that is representative of the entry. An example of this is a 640x480 jpeg image automatically produced by a low resolution plot of the NXdata. The value should be an ``image/*`` ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXtransformations.nxdl.xml0000644000077000000000000002645215046415443027745 0ustar00rosborn Collection of axis-based translations and rotations to describe a geometry. May also contain axes that do not move and therefore do not have a transformation type specified, but are useful in understanding coordinate frames within which transformations are done, or in documenting important directions, such as the direction of gravity. A nested sequence of transformations lists the translation and rotation steps needed to describe the position and orientation of any movable or fixed device. There will be one or more transformations (axes) defined by one or more fields for each transformation. Transformations can also be described by NXlog groups when the values change with time. The all-caps name ``AXISNAME`` designates the particular axis generating a transformation (e.g. a rotation axis or a translation axis or a general axis). The attribute ``units="NX_TRANSFORMATION"`` designates the units will be appropriate to the ``transformation_type`` attribute: * ``NX_LENGTH`` for ``translation`` * ``NX_ANGLE`` for ``rotation`` * ``NX_UNITLESS`` for axes for which no transformation type is specified This class will usually contain all axes of a sample stage or goniometer or a detector. The NeXus default McSTAS coordinate frame is assumed, but additional useful coordinate axes may be defined by using axes for which no transformation type has been specified. The entry point (``depends_on``) will be outside of this class and point to a field in here (or to an instance of ``NX_coordinate_system``). Following the chain may also require following ``depends_on`` links to transformations outside, for example to a common base table. If a relative path is given, it is relative to the group enclosing the ``depends_on`` specification. For a chain of three transformations, where :math:`T_1` depends on :math:`T_2` and that in turn depends on :math:`T_3`, the final transformation :math:`T_f` is .. math:: T_f = T_3 T_2 T_1 In explicit terms, the transformations are a subset of affine transformations expressed as 4x4 matrices that act on homogeneous coordinates, :math:`w=(x,y,z,1)^T`. For rotation and translation, .. math:: T_r &= \begin{pmatrix} R & o \\ 0_3 & 1 \end{pmatrix} \\ T_t &= \begin{pmatrix} I_3 & t + o \\ 0_3 & 1 \end{pmatrix} where :math:`R` is the usual 3x3 rotation matrix, :math:`o` is an offset vector, :math:`0_3` is a row of 3 zeros, :math:`I_3` is the 3x3 identity matrix and :math:`t` is the translation vector. :math:`o` is given by the ``offset`` attribute, :math:`t` is given by the ``vector`` attribute multiplied by the field value, and :math:`R` is defined as a rotation about an axis in the direction of ``vector``, of angle of the field value. NOTE One possible use of ``NXtransformations`` is to define the motors and transformations for a diffractometer (goniometer). Such use is mentioned in the ``NXinstrument`` base class. Use one ``NXtransformations`` group for each diffractometer and name the group appropriate to the device. Collecting the motors of a sample table or xyz-stage in an NXtransformations group is equally possible. Following the section on the general description of axis in NXtransformations is a section which documents the fields commonly used within NeXus for positioning purposes and their meaning. Whenever there is a need for positioning a beam line component please use the existing names. Use as many fields as needed in order to position the component. Feel free to add more axis if required. In the description given below, only those atttributes which are defined through the name are specified. Add the other attributes of the full set: * vector * offset * transformation_type * depends_on as needed. NOTE ``NXtransformations`` follows the **active** transformation convention. This means that the transformation describes how an object is moved or rotated within the coordinate system. In other words, the transformation actively changes the position or orientation of the object itself. This is in contrast to a **passive** transformation, which changes the frame of reference or coordinate system, while the object remains fixed. In case it is needed to describe multiple coordinate systems, it is strongly suggested to use the :ref:`NXcoordinate_system` base class. Units need to be appropriate for translation or rotation The name of this field is not forced. The user is free to use any name that does not cause confusion. When using more than one ``AXISNAME`` field, make sure that each field name is unique in the same group, as required by HDF5. The values given should be the start points of exposures for the corresponding frames. The end points should be given in ``AXISNAME_end``. The transformation_type may be ``translation``, in which case the values are linear displacements along the axis, ``rotation``, in which case the values are angular rotations around the axis. If this attribute is omitted, this is an axis for which there is no motion to be specified, such as the direction of gravity, or the direction to the source, or a basis vector of a coordinate frame. In this case the value of the ``AXISNAME`` field is not used and can be set to the number ``NaN``. Three values that define the axis for this transformation. The axis should be normalized to unit length, making it dimensionless. For ``translation`` axes the direction should be chosen for increasing displacement. For general axes, an appropriate direction should be chosen. By default, for ``rotation`` axes that do not explicitly depend on a coordinate system, the direction should be chosen for a right-handed rotation with increasing angle. Note, McStas is a right handed coordinate system. If the ``NXtransformation`` depends on a coordinate system (i.e., its ``depends_on`` attribute (or a ``depends_on`` further up the transformation chain) points to an instance of :ref:`NXcoordinate_system`), the rotation convention is the same as the handedness of the coordinate system (as defined by the determinant of its base vectors): * Rotations in left-handed coordinate systems are left-handed (i.e., they follow the left-hand grip rule). In a left-handed coordinate system, positive rotation about an axis is clockwise when looking from a point on the positive axis towards its origin (from infinity towards the origin). * Rotations in right-handed coordinate systems are right-handed (i.e., they follow the right-hand grip rule). In a right-handed coordinate system, positive rotation about an axis is counter-clockwise when looking from a point on the positive axis towards its origin (from infinity towards the origin). Note that by using this convention, the transformation matrices in both left- and right-handed coordinate systems are the same. A fixed offset applied before the transformation (three vector components). This is not intended to be a substitute for a fixed ``translation`` axis but, for example, as the mechanical offset from mounting the axis to its dependency. Units of the offset. Values should be consistent with NX_LENGTH. Points to the path of a field defining the axis on which this instance of NXtransformations depends or the string ".". It can also point to an instance of ``NX_coordinate_system`` if this transformation depends on it. If it is the string ".", it is explicitly pointing towards the default `NeXus coordinate system <https://manual.nexusformat.org/design.html#the-nexus-coordinate-system>`_. An arbitrary identifier of a component of the equipment to which the transformation belongs, such as 'detector_arm' or 'detector_module'. NXtransformations with the same equipment_component label form a logical grouping which can be combined together into a single change-of-basis operation. ``AXISNAME_end`` is a placeholder for a name constructed from the actual name of an axis to which ``_end`` has been appended. The values in this field are the end points of the motions that start at the corresponding positions given in the ``AXISNAME`` field. ``AXISNAME_increment_set`` is a placeholder for a name constructed from the actual name of an axis to which ``_increment_set`` has been appended. The value of this optional field is the intended average range through which the corresponding axis moves during the exposure of a frame. Ideally, the value of this field added to each value of ``AXISNAME`` would agree with the corresponding values of ``AXISNAME_end``, but there is a possibility of significant differences. Use of ``AXISNAME_end`` is recommended. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXtranslation.nxdl.xml0000644000077000000000000000425514777236751027064 0ustar00rosborn legacy class - (used by :ref:`NXgeometry`) - general spatial location of a component. Link to other object if we are relative, else absent (x,y,z) This field describes the lateral movement of a component. The pair of groups NXtranslation and NXorientation together describe the position of a component. For absolute position, the origin is the scattering center (where a perfectly aligned sample would be) with the z-axis pointing downstream and the y-axis pointing gravitationally up. For a relative position the NXtranslation is taken into account before the NXorientation. The axes are right-handed and orthonormal. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXunit_cell.nxdl.xml0000644000077000000000000001447715046415443026476 0ustar00rosborn Dimensionality of the lattice. Base class to describe structural aspects of an arrangement of atoms or ions including a crystallographic unit cell. Following recommendations of `CIF <https://www.iucr.org/resources/cif/spec/version1.1>`_ and `International Tables of Crystallography <https://it.iucr.org/>`_. Path to a reference frame in which the unit cell is defined to resolve ambiguity in cases when e.g. a different reference frame than the NeXus default reference frame (McStas) was chosen. Dimensionality of the structure. Geometry of the unit cell quantified via parameters a, b, and c. Geometry of the unit cell quantified individually via parameter a. Geometry of the unit cell quantified individually via parameter b. Geometry of the unit cell quantified individually via parameter c. Geometry of the unit cell quantified via parameters alpha, beta, and gamma. Geometry of the unit cell quantified individually via parameter alpha. Geometry of the unit cell quantified individually via parameter beta. Geometry of the unit cell quantified individually via parameter gamma. Crystal system. For a crystal system in 2D space monoclinic is an exact synonym for oblique. For a crystal system in 2D space orthorhombic is an exact synonym for rectangular. For a crystal system in 2D space tetragonal is an exact synonym for square. Laue group using International Table of Crystallography notation. Point group using International Table of Crystallography notation. Space group from the International Table of Crystallography notation. True if space group is considered a centrosymmetric one. False if space group is considered a non-centrosymmetric one. Centrosymmetric has all types and combinations of symmetry elements (translation, rotational axis, mirror planes, center of inversion) Non-centrosymmetric compared to centrosymmetric is constrained (no inversion). Chiral compared to non-centrosymmetric is constrained (no mirror planes). True if space group is considered a chiral one. False if space group is consider a non-chiral one. Area of the unit cell if dimensionality is 2. Volume of the unit cell if dimensionality is 3. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXuser.nxdl.xml0000644000077000000000000000467114777236751025506 0ustar00rosborn Contact information for a user. The format allows more than one user with the same affiliation and contact information, but a second :ref:`NXuser` group should be used if they have different affiliations, etc. Name of user responsible for this entry Role of user responsible for this entry. Suggested roles are "local_contact", "principal_investigator", and "proposer" Affiliation of user Address of user Telephone number of user Fax number of user Email of user facility based unique identifier for this person e.g. their identification code on the facility address/contact database an author code, Open Researcher and Contributor ID, defined by https://orcid.org and expressed as a URI ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXvelocity_selector.nxdl.xml0000644000077000000000000000607314777236751030264 0ustar00rosborn A neutron velocity selector velocity selector type velocity selector rotation speed radius at beam centre spoke width at beam centre rotor length number of spokes/lamella twist angle along axis offset vertical angle input beam height input beam width wavelength deviation FWHM /Wavelength This group describes the shape of the beam line component .. todo:: Add a definition for the reference point of a velocity selector. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1754929955.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXwaveplate.nxdl.xml0000644000077000000000000001526715046415443026506 0ustar00rosborn Size of the wavelength array for which the refractive index of the material and/or coating is given. Number of discrete wavelengths for which the waveplate is designed. If it operates for a range of wavelengths then N_wavelengths = 2 and the minimum and maximum values of the range should be provided. A waveplate or retarder. Type of waveplate (e.g. achromatic or zero-order). Specify the retardance of the waveplate (e.g. full-wave, half-wave (lambda/2), quarter-wave (lambda/4)). Discrete wavelengths for which the waveplate is designed. If the waveplate operates over an entire range of wavelengths, enter the minimum and maximum values of the wavelength range (in this case N_wavelengths = 2). In this case, also use type="achromatic". Wavelength resolved retardance of the waveplate. Diameter of the waveplate (if the waveplate is circular). Clear aperture of the device (e.g. 90% of diameter for a disc or 90% of length/height for square geometry). Describe the material of the substrate of the waveplate in substrate/substrate_material and provide its index of refraction in substrate/index_of_refraction_substrate, if known. Specify the material of the waveplate. If the device has a coating it should be described in coating/coating_material. Thickness of the waveplate substrate. Complex index of refraction of the waveplate substrate. Specify at given wavelength (or energy, wavenumber etc.) values. Is the waveplate coated? If yes, specify the type and material of the coating and the wavelength range for which it is designed. If known, you may also provide its index of refraction. Specify the coating type (e.g. dielectric, anti-reflection (AR), multilayer coating etc.). Specify the coating material. Thickness of the coating. Wavelength range for which the coating is designed. Enter the minimum and maximum values of the wavelength range. Complex index of refraction of the coating. Specify at given spectral values (wavelength, energy, wavenumber etc.). Average reflectance of the waveplate in percentage. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/NXxraylens.nxdl.xml0000644000077000000000000000712414777236751026371 0ustar00rosborn An X-ray lens, typically at a synchrotron X-ray beam line. Based on information provided by Gerd Wellenreuther (DESY). Geometry of the lens Is the device symmetric? Is the device cylindrical? Orientation of the cylinder axis. The type of focus of the lens Thickness of the lens Length of the lens Radius of the curvature as measured in the middle of the lens Diameter of the lens. Number of lenses that make up the compound lens. Material used to make the lens. Gas used to fill the lens Gas pressure in the lens This group describes the shape of the beam line component .. todo:: Add a definition for the reference point of a x-ray lens. ././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.8240328 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/aperture/0000755000077000000000000000000015060352601024366 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/aperture/aperture.png0000644000077000000000000016521414777236751026761 0ustar00rosbornPNG  IHDR7U /|sRGBeXIfMM*V^(if7U9sX pHYsgR iTXtXML:com.adobe.xmp 1 2 2 5 ώ@IDATx ufXfm}D E4,=ej꟩\nyV*iD\}wypf`xΜ;3]                            Gx@@r!g\(S ZC@@ |ﵡe  Aƣ   @,;kjB c2v&N vn)   ;VsMM  3}ڢ/bv  @h,KC@@ *SJl)   }>gߘ@@ Mg   d_7@@mEzrS?q   dOٳd]ܲNL @>hGs~@@Ȟųg˙@@ !s6z  xl93 $@`1Hfw)   y>gޔ3"S甛@zO#  M~O)^  @% |C@ȽsoN  3?Ad:  x,9 $T7%5t@@2'gYr&@H@yE<٭@@h[nk2Hu컎@@h[n@@ s'YE@@Ȕ3%y@@ uY   @,|;^@KB@ !mf?fV@@@s?S7uC  l}Eu3B)C   >7  S$6@@hśn+B}yhT`z ׷z^  @d-}}   @~J(:@@/g[q$hP@ noaWz/^$W4D?c:>Ոp  gqy|â_a6_nk8@8A9{95FWUzL;^4  gq̵>7h6@9' $K`u>sΗ2*MoNш;ӎ_o5p 0F@ȸ@\> E㍹;㢜@'kS,9E#4u=88@@Ȇ@>4 Oogp^kAA@-^"FK|:o>MViz7Јuq<  @Y?Χ|޿o @%0՚#Su|V>@#~v̩Fx6p F@@Eq,~2ؓZ?OYP@@ ^|Λ+8zQߐcx@@l x}fA|Fo;@@{-yu|Viz_άӈsҞ%uG@@-uY{E|kAA@Z,I;C!#:JBwiď砿?"  8goMK?7x[@@ ٸUn>kii'@@\ x`=|&׭@@ #,4u_tJ[Zӈ [Z7  R eyEY\=EA@2&p)F|_[A=|5z@@-4x~n+N)l) en߈ߎy==f}>4-<w@@@eFל~⍚A qŐKN@4jvMv  -Sh~>]}^o';!*4fk-K  -(9o_sr%J_E}="Hv. ,Z8jAA@@@ $7Cqh@PBoUTX4X,,,l0TE穯m5e%H:t=jIhX;3M h թ5:ܾ}wN]v-b)   1 Kȱvb4KM5O$RKk!&: 7%RSCٔTWh_Z֭[vء$[]IjjP]b4h|];Xk5e   ag!CV-z-++smG AcǎN#87oÇY3xB#:ZP@@@2 @r3 h-PEEE~ zqq! Q@#]Ν݆ Yme5EZhӡ-(   -`Zz x)ynuβxآBiC:&BA dZW^Z&"Mjʇ n]7    4^@v^ֺZjUm݈#Ȱ<*@ "o߾nذa/"wYhYM8"   L.!jZ`ugIT=%9Cd t anݺDHNG A@_XhAm۪K w[   B)x =hi mݻw05͡:ȶ@ii>|ٳQV,p(@@"/@r3D@b0^T}G( g]-Ywá߃w  DfKx-gw- wQ\ @$ڵkFqj'u}HtF"  9 cpCtyٷo_6 ď$M pH85eJEO    @M GU/,Jt.]5Ԋ(,,_vhݚ8/FnquK@@@< <&ZRW)aQQQ᧡얜h: hgn`̊ai@@@ $7{xIZ[O;у5p1( p}aEkq~BKZkAA@@+@r3X`g,5kذaf$VBu EH!CjFz~{@@@ q$7wp9bPAA^VõJ"/5zH׮Zɗ-nQiAA@@%@v%QXŏ- ʴn+))q3&кukWUU 쾦Ox¸   ' y2CC/Z\oQ]YYڴi3J@@N43UE=-fs(?"   J,p?bk}ݻITq{&}-:ŵ @@Hn"r ˼Q }^x@ ZW񐦩_f1bT6   @Hn P\zZGbEj4hM  +m24tTa( @>yvRիi꟰x֢@@\J:cſZܹv4H_@{%2R[V,,Nh   q,`-կ_? =( @JKKrn9  D]lLԯ ϵtJHlI͔FFQ@0 (jfş,>(   @HnF\ _tt  ޲)K.jn,gg@A@@h ܌uչتmGj}Kh۷oѐeG-    5ܠ >mOĢMII߿( u=<>\G9 Nlݺܹis }YL :@T+W[j{}ӏ>   v24aB/}KjrVUU~$O@IfU=tPOfaaam(Jl6o_e5콐Zlx댖xŢHw#  @Hn&r&ƿ[|B;qP~FR߿۷Gp_ S% ۷o|\K n͛VZuP;vONRFz*鶾j'Pj[j#%`Hl(iX(IA@@B/@r3A_WX8(W!GU*YgϞPBPZ@I V29 `|ڠovrw>.BݻGzJ*YTTT 1u܏s eփ-.@@P_VL6Uz;T-tLOf*W_Q§̇}=QJ*+Jlj=Om68AS:ѧFW@v~%'Znh9  $Af2}l@$K U80PR' hx TTҮnQ®[n>}"S#4^ԩ*}vܸqSl޼O߱cSE Ѭ:'%v{ϭXBXY|}ѣ9fDG@@ @r3 W>6FXM4hPJ /JA2s]_%0dfh4{-VKUJv()6lLi_~ߘH_N%٬({)gֵnʕJnXiq ALA@@B'@r3tA,NLKlyhU6S@djFj*uzQFJ]vS ()DbȑJlY;(YOJtjtwе_@ }e _X۞@@&@r3iWc$S2T;>;@A_ٹgb BM[gz~,dH_Jؿ唵{,~P+  $Yf~2κըJPr+45nÆ ~qP{ee9r-#n)SE9FvjZFjMN$R hS/ѵZ\a/(   @Hn挚 P`uΰbS^mfJPr'_v=MSY#55b@c:tƎFGqi $'_^4F3shMV#7/@@ȉ͜0SI4>f$ ARS#<+VOwÆ c].Ej F`+A׫7R]={$ə+#8wءo5j@@@ $7qf}LkMJ4E5$55Z3pÇg}l__ILp}իk7 3Z;o %8-[5u5ϱ~Ԁ  I w@}e*iX,l- @@,@r3W?}uc6=:y~Gi1uY0sq&$`kB? <͞=ۯŹ|r-} chg}bņ@@@ `h=BM +ҝs9$|2CYB$PYY鮹7zhV;… JSZ.%4ڻm۶:Y=@A@@Z"@r%z6_ì[cyyyzYv_Pkj &ʯI^רd%9{7Ҩŋ͇n3dm]SeYe   q$7[Pv㭨@%K?Դk֝~lG 3$PVV.rwQ{ 68FqY#7I OY|g    tL; zȚjQ5uӏhʕ+}rF;w#Gds@yM"4}{;vwm6FsR' %:,Ҽ3*@@Hͤծ];WUU?oٲŷpԨQ~'t%) prVZ1cƸ+OֲK.uׯ? yAMMw؁7x0O    lC#pd%5GS)M47x۷ϵo]venܸqtJ^pr?M}РA^b͚5~$S.еkWV  4Vfc8.WX_VŶ>[J#7)Mvmm⦝@V@SL&M H 4Z@;K+Zs@A@@#@r1JEJkl2u@f|iZWS#65->|+F\u}hٓsM7ym==E@@ l φ`{آLls޽OC׆' /;+@A h6`îիW%gj۶TBĿ@@2!@##_^]t.MՆAD#7;u7 ߿ X-q% M6QӇn)84BfM}6E 0   HnJs-0**ݻ7l6QڵnʕNkm*yUWgO D2ƍ;M6:^xۿϔ3~$[#  @cHn6Fcr%M$â]iitOJ4r֭/5j Ɲ@ :JtR'кukV?Y\(   @C$7|fNĶ;z>dnwynܸqLդqjfhGD'qŮG{%G!  @Hn&񪇳iʩ4US_52LSa/R7dȐS#@ ۷w]ve"GVg☜W^NV4b-  Y TNdb{/-Zk3 zZ@;+yWRRVTT9( /Нq>$\@kl(_   TI֜y$(رc)zW>5G s%Ə&O엊˗lĕM&~dP#^!   0 !֦:Lrr 92ך'!"@ .ќ;wr"o HF#ӭYʂIH  $7k)R_UoS5ѩr~ZS^, @*++ZSX.]iC0J/q/MOo?>g@@@ $7x;)m۶u*̓awymذFmR!pQky9ZucmXnt¨p\PB_(O;v!Cꠜ(lZJ#٭h3@@+@r3>_=Лor%6~k@IDAT&6'M^^|EeQf5#kW3sl/e*T}{'N'_xoE_&zxY?P@@@ dv^IVljn6mV^8묳ѣOɒJRN*)%ݩ5rnıECShQoLG?kV02PSQ'OlHNsO?k'1cƸ?hAԴ38>/4JmϞ=~+V_-^ic#=];/(y^QQ1ٹsg~'ԹZT;߇"3  @cGs>B L$7t5%6viJ:x%.4z);e'3<&J2};q?ϳ̙3}u;͊f̘>|'5<|w|Sֺd6aY;]o}顥t;rL@I}3,X!  h*D |TkM]fQm#X*aYJiObQ~(Yfu.~ 3p@&F*]5e^Su*>]SYD?=zpSNuO=zD_:mTkj֭z.?@@@ $7~?%3Ǧ+//gw:Bӝ(2`Zq(~ FjCw7UvPWE#dɩ$+Tvgqqqp nC( &M}YvZu1}1d#oLcr@@.@r3W8SvhF;BIzO7մiӦ1xiܳgv\npsOdN>h%m FwnذvtgP?ktg0S6m_CaÆ9k+W$]-`~F?[>v@@@ 竛߾i;;M$Yrx}Bߋ/ؕ?eU@k*᧑*z)]tQVɕ49ݩ5<_y?S+ToZkSucOhFzϜ9'95slBV/fլ^N   F|zT\m:ܵS駟S&h'zĩ]vnsz+;طo_z; ֭[G#uJrzp3F^r% N-qѧO 9`GY~  Ltx9ًI/w`ӎպps49Pm֬Yn˖- /9=U(ݺAYj$;_~e9Vѝ;HvjZ{iiip n[ PVV.SO$DewA;vGXV y)  [fO[Q7|Ji}CRlq6 5bS;+s]wӧgĝ):w7o ־vZ6yYp?.Y^^Κ|h1c"[/xjm   @,HnS#+-{[+BVFnݺկVIظ&@t}Y&ڡ{S"h%=YNM#v';^֘:ZS]hc/R۶m7,>t  @Hno˪LiԦlS?~ٳ',YA|7} Z7sӦMRdYkaڝ^ `"js'LݩS5SPNPrw- 0`L#]kM޼b d  $BqsVG%6 BSΦE׏ 6TBsΜ9N 4MM(h۶8qEqTSIjMV;J|23tSm߾mذ'{ߩSGdJk@@/@r38W=~&Yo;xw^Cٹs*Fr>;vlYm:|+RԴv|Fw.ZwUIk-͹(){gٳg)Ꚗ]RRx޴FojZmK  1h>ѥ h,4j3FRMi50n݌3fMewΝKb3it -yu;5Gu_}Oh~ttѦ> 8ПS_9r$ɔMk>K@@@@$7OmG$6ۻw)Zl`E;uS2'Q|3gt/Oni |+͘9М]s5~{o#]0k,BtZݖjѣGJ4_&޼,N>o  ;9x;+2Mݸqo6: (Q?iȚO~WGY{z~FpR 3ƕu7W\ǞM=m@Vג'@@@x_lVAkMKMmޡ$ʰaÜp ,[o*o:M.\.ҖWB@#nߗy bѱ tUVnʔ)uKM6e>Ep7ZOzG7@@Hnkp)]`Ms=zhbyl0S3_O?ݯy柘WN`>XgϞC:qD -o߾.͒C79   P+@r;MN#6pھ}߸C s64]@1iMG})Ӷm[ww:7n\O+!3K.MDÇ޽{iLOwKY| Y$o$C@@ $7C~BijhkԦgx6ofΜGhjjů}kM Pm|hLZݻ%}zPї&V:[|8z  @HnGX%4BsgܲvZw!Y64M@_|h*C=䧤4i' zm@5gΜ:qF>Y&ѻkt6Z)7wE@@h ܌W#Q,&ٳvwI&1°o%Zf̘ϟ^{nxI|>FTN9&M4^K?ǞH཮]:mdee@@b'@r3v4o5WRS$&TWWNG״ʤR4]=~k Orݻwox8묳71}YQws_HjibfR@@ V$7cu9s=t$oqFֲ v$Ή~+ѨGyo?yh"weEg4? ~rvrs CBֺ*Zj֊_jI}#o@@܌ͥIG*US7:xZ*&Lp۷OJ6kijȑ#?~_34Aw} ,6?Tu7׭[6Am*d iM:@@@ $7qJ^d6HjѨ']ףG7dȐ24ߚ]}Q?ZLI;͛7ύ(dVK.q7p_{6MU6lGG7-kyt3l@@)@r3Ѫ5SjrEܹs_NS'O Nݲe9s;].IJuVo>֮(f7c ꫯi\s[x'?͉J< o]p~tN9&Eꋛ$mԪU+u^LL}F@@ $7p߇>V]t~m!Akl* 2z`:c[&i oOQrkmjmR U]ti>:GmoW#X4zՖ/D  @Hn*f*RnJXơCNçvZ #<,YGg?[h| O o۾ޏEQCǎ뛪ӏ9fgi_}N>pB@@ȺͬGj^S\~qZuI:{nSOgyi!}O~>Ky r-N87YhСSN~I,_*@@ ܌~'[m]nvZi|B#^>߂ hիWĀFǽ+nDK#loӦ{衇[l{ļG&\Heƍ>b! E@@l^B^ثx!!]>Mm yf@8liS3g9s^'Ov7 B#!pg:TBMyWO>W^~S!}RB[hi   DHf.VZlu^zF2޷o_q>^z%cGJKK6k&BCha ۜk9s熻9n]ōI+m۶R)>ݘ_@@.@r3W0WbXi]?U4+Ef̘^}U?=ꫯv/vԧBIu(**r?|.\j]vu|Sqq~, q'}C@@ $7xU3'?%]&lTUU%r6`?nΝOIWgϞI|K \|=k,x2 -[$rͲ2.jae5MA@@܌ȅC3[Zm&$}+AK,[h+V1~)b) ޽{/vd͕_7=I}  D]fԯ`;uJf9Iz)O;m4|psϹNlR=s=󣒣ާL?7ӒW);ey@@Ȳ,GW횪ե2f̘Dt-X=n~o}[W^qg}v" dr>򑏸S#G8MO+Э[7WYYI֖nӦMIR+  Q 嫗knY՝:u^-!=s0%SS4~܋6M̙:&Mϟo$ڍ hs;m,ͱEJҿ_% "  QpYnu~Œ*(H<15jmܹs7n>?mذaY~qz+пwF ~(woIޕvE%@@@|p?)Ob$NIߴiIYyԦFjsM;?zꪫo>8^ o/=(4rQԗ I*δkݺaw  @THnFe.qSҕۼy9rdxfQk >nǎW^~Fo>$ (C9픽|rlP_+**߉ NM@@X ܌emQT:$ntMG?|ȝ!o[xoFi.Zȏ k{i=z[}5gf(?GKVhzJZrS3=I" DRf$/[V)#^eĈlկ~i}͎;f-58wסBƁmM4;Iԏ>%@@ ܌%jSTCȕVܹo(ҦM7tа4+ذa?瞛ssB*`#՝vOWY``+}T0X,snܸX'q| [nn&wg9sզQUUUUB!kb֚DgM#  2-˫Ϸ(¸MD{xdS-8/ ez!+VիW'Z&( I@@ $7|263w)X?.XO.-n~ Yov2Fr_җ<ٳIКL[ܹ31 5KT[GY't@@ ܌bS}r3Imݻi89`,p۷o ?~|D 7M;b^P3T4h?iPfkٴMOY @@d LWY(W䦦VhFs FmjZi.]U@ޤvOWYp =e0宵9gLMό#gA@@ [$7%Q)-U>jS}dM)Ph^OO0k,w,¯eee~`4x覓l4"  yaU[oSSҵr6m\޽Cu1PI~7ӨW_}5iݯo~j}"w?JiV0ĸt @@H ܌ehْ4%=Ħq. ~ӦM&LsWYВ?я|J{ArSSӓ2U*YS&wE@@p uW+X=-;t萯6`:eGz (Ua~ifB ~_6m_ogӳ˓HI^M'Jp&][@[@@B"ak!Aq3iLidJvH߿%Ov]Oƍ璴j*˧6>|[n[d:th>kLB!LȚ@W;g-JV'FLIx@  g |r3폶|%'u6+++]aaaNg%O}ꎣ@UU;-^x/I4]״>LMO—cinJPChń7( gKo~Ν̙㴛zJyySoϞ=n׮]cǎ~AAB̖4qľt2%Glꋰ$q)<΃@f-ڵKgg EaQbi-ѩ6JNM!9k[{Q$7~_.Ã>ܾ]v9wn.2dEh@=u]n)SxWO8^M90 E=`H @r@f tBMx(O|HqRz"6M]xӓ-lѣ+RvJr<]"<;! @ ` BʸYZZri{Ī{MB҃Xn@˖-OS7ys J׿ jQ(ZoA @ *`ܬL2n*Ç]Az17j_.s7;&Ol98?( Ÿ*Ro+ @ snvl/)O7߽z2AzS!!92b%nݺ:gώUBNS|J"@ ٷb .i)R7nmuY./^E?ISNGu"̜9Bsή8UCP=0*S4JB @ 0n&|$pa!4Ќ G$'>a.r<2Mµ  @0wSf=7~Ϟ=жm[Ӯ] t&fˌ #c9Ͼ 6 $LqydG˿ @9sP2n)fM6oTs3GǤׯַę6mQ!7oܔ!SRȃA7~ @@*`L2T";ک1^ 6I޽{Dˋ}z^{po߷q˓ K7aƇ @@`ܬ,팛,TޓȇMVy`F>رckݺ9rdFB  `?|޼yFԳãfKUk-{XξuE/@ ʹT Ҹ=r1#cǺɔ .|3qN<>|8+GNnR&-SBje}  @I'q3+[+Gr;CF!A97B$$=A @x衇gϞY&RM-b$ffj @H iYӪInFN(%%%Nmۺ0s&6s!P/*d裏sg͚edbME:Eg @(<g5yf|8e{uspɼO0۷owRs91K'p 7+9r(<]͚~i޼~W^!@ YxqXn܌SBoMwk>p@㽨⒅y! '?1mڴqϟx'UCUA Z?+ @ pk֠>ߦ zMB Ey P{}5ַ ӧO7YM٤I j{"M<73ƨ@ 7ӳVyDnr1fb7ء7ɷK ~F)#B{x/yݛ9# E~G[]# @ y`<7lԳ-=@ Ah)wm֬Y.4@ W*[)vB vm-k-1nz &,n5)& !޸ٽ{ԫh C&yoʫ<-,/4Aaty tطoQA&0f'jj-Z)$ o3LS`ܔ"޸)ͬqͬ/6AԮ]={΄J`f'ѱcGӷo͛%H3G!$(+ļo^&xP?ƍp>H@?K.u),= Mve,TWE@E2l0"C 9ﭢRQ"lC 9$Rf4JκSv"M|o|f&Zm9VLԉIW eK8 :UC!aUAb? @L M} m9gu7;t6oJHz/,cĸIXz:LƋl L 4Hqt QNkQ#G7p송KپR:a]#$@M|ͬK_54 ͟G~W1ny!=J$k/u?i;  $@RrnD?>rK܄vo塚ϪYC 8c 'l=7q:V~RF~W[o΂@"R\k/=a>VI @!qSaW>,vL7-tu͝;w;1cdE9d9sLqq{ӡC̨qfDvA dTtۯ@ @ 0(*|d; -`SȇEm,SxͱcǚM"B #m*$=b$kؠ 87"q3o8vlvm @@ ʸIyJsM W<ήj"y-q|3C|, #7PF9 @&OOy2.wըQGPii0bBTJh($﹙5DždZ蹼v^|5 &B|@@føIy.w0I9LGn8s4rr9xٶmfrI P[l1K,qtڵ.&X뿏/pblGN)+\}4@ y2nvK%8fmWm޼hпӳgz)@צ v &  C!M;OǥqxCXIIͺh$@VmŸ+2D@ m` T;h I>Bi0'gZH%%%fŊ94۷ω7x#"6Xk׺1-[f&L L A fm  4IK |:\YOkիjGd@ 6lؐ1(7 ; %3߿ߨЊ͢E23:-vڕmݺu<7v]DB ΰvwH`F@@ Tg$<@̞=Nsp {fϞ=Yfcǎz_`a눉!P"{a5Qs@y&z>Pbx@֯__~FUQglV~$ Ppw.L_?ڌ5wu *C "/Հ@#uq L@U9V8)Ta:@QÇ]lϷŐt-ϵ=8S\Պ1@>@(lsn8@ t4oNF2 r@@@-c쪌,qܔ,4@hѢy'; {f iST{p7'bh%R;elo; @ Ȱ9hР|O@= Y7Vg܌Ѿ^j°]g3R~m4**&Ժukӻw4^Zd;7ZH=}RN;|K_2Y5oer#֭[ŋ`YĸkQ ` ~}`}nj|OϰK$0;w6۷OHq1پ"l]'N?g?T ()8S7U㢋.Jĵqݺuθٷo_3JKFrKu!icLzUۿfEOZe5՟#d$ӧOGL@$ШOj_e/l8"+rLZY6m&7n\a&d@ .`7s~0 'mv m~ @@CQP>l}ݩЋھ5z۱pHnXf:܍gf |^A ͬK4#xnƻϮ'm?` i @ 2nFa)lN{~~vZ|1ni9όq3L$ ߌʴb2KB2.\7 MjA`=櫶۟v @,|7=,hUq{Ń;%5o ܹs F5m|q1nƵ G@~턭;$@@V ӸeFzFᷝqp~ظqc7فNM發駟nT@4$=ˆ[K]֏Npd:DY}E:DGJ@ P3B7Q`<74i1K7ɷUExf37n,+KXzW7-}_l/l'lBA ^q7=-[4,}SСC{c'gSS)=g(,@TK/IԞlWͶi @@i܌"l=J#;4 ~Yo޸)= vuֺmݺթq9]@mf-ZtHx@IDATϺ~gu#w6zW (l)/]a_}4@ I1nFaU [zئ|z·B씈^7o6ӧU@b L:֡CW,@0``]=*"jM@a_}߶ @@ MPL}z2KTK2݈eݛFɛ`kN|'2aF t tv]"/!ߨ> @ DDɘ{>.fF,c*SPcs f: !%YIk>Ҥk7㦀 @ 1@i`Bӳfńȷ_B9bOF ,K鄥'zy @ 7Yh MxdVsC]RRzwek6mjN?$dpJZCHnyݻqǎs3hBGQ鿋*jNĊ⹙ @ HrͺksYfÞ=*68!JM62#o|Hz׮]e顒Se0nf} @ 0nar#3nFnr3jGɒq| z}Gy]#.\Ш0?OWݾv G`ꈪhJ֛mbYh-[4sS_ʕ #G4 ?g0Zc{2 gϛ7ڵ˥رcDnW㢢"0Ad)Xųh@@-T_C9VyQdv;l!;:M!+1̒56UM?tMnܝе xOL麆*Ϸk&zCJaezʺh_<˃p @CǶ)"v'nv{6 KEn ;{g.y .pU駟\i|cN:uQ۷sz2ՕX6C I߶m[0իYo17OUƄ @ 5raܔ=}mFOpk!+{nJbEmeoޜqN3M@:oҤIEV<&z~mFǬ8_eW<&z~eg_t̊U6^cWv|f(M0 fW=H!@@JlO+YضmώIZ㹩Ho7[%5j֭[Ϳ˿T~{\55w[Ế!';v;*<Ȧh>O޽{ 7M͹yUWpn}z<No3޿I)/UU!7DY5Ad/cee;d*kt ]zX.ہwqSۧ.gcmwN+<BqӇHfٸKhСf@}μ!nf8To[Ӿ2emx|Æ 3hv*A?Fe-,獛TJ߯Z PsgZF^-V< A '۲ڞܾ`~dIv?f@qSa!4oܔfuV(r+橧 ayk{5'|rq/Rwy?躼|{衇L=*_ULasŨj7C˷-qi^=x&% @h<Ğ;v_=`i{e-boox-v=75jQ6/2>A"3'Qxm*;L&Mކ乩KcEҹ,rDd  @'q3 \ziII ]L7Fٿmgo#OƈJml޸C(<` PrJjU!EQK/vy#o$$ʔ.qE-[|Mͣ;^!@ s36Na3lX7j1z^E۷o79ƍsŔ}]Ug}/| ۠1(SJ޸B6-X|j%>Za @@Mdu 928A %t5UFn%}Uo8D*oѢ9s_ҥKSBC ve͛ s3㦊 (m@@mmoؾv^`mWRV!S3Hf&|hgܳgO̝x܇RndtUV [n%"RJ@UU-]3!xëpe)]:|מN's0 @ L 6/mf9B4d*e@ `,0MuԳߢM!Bj*.$^{c+Y:JUc@'!qc_2mWvߚڍ'lWg2,B f7c^w7h Сߘwd>bӥKJ_%@  t{5QǎSrȑ#ğqӓ P5#P,ovWdT@`L*'CPMa+VG=5jdƏr4iRL0-E`…R?t)[UTf͚UrDvɠ[DEfOC4 @;ڸȈʋ53ob="S2DfVgTx|* bh<7G<[ou 1#EK/Yo=Mg$ͬ_@ hxc ti|~yd;ȔK]X€'LV2+R M#{e_5TͶmۚUV|+;@q3tV]1u"1np N@}m77Un+'g2(A A0n&h1bEU\x@-1 ;6ZlYa'Nl Utf 1 NSw`\r nٲiѢE:RG~#7_S @A=ڻ>_zLȉH&\BJ&۵kW!u.t޶m[5y>}̐!CbĉF޻4@vm=Э[3|HzH^3J)͔] @UjjY S 7ӲRe qqFNP7q՜9s=Au$**4T*vfϲ^o+ @Uh6$Gx2EMdͬhJ4K#\Ƀ MWtVoC]~R_<b@oԙ _޸bB;w47ntB2n#G\ -VuH8 &&Gڌ9!S2Df#FQqS^e7q1Rt&S )Wرc_ @oԖZ(nڷoo6mZ[D?.U4  @0^ɟY&2f Mh 2pZnr)hȅ#F02رy睡\ 6vj &U7F܊k1n^!@UWd>_zLȉH&ލ%wr7nbI5guy`d?~)**2+3pb SOa^7*B@N L0ڍG߶o[d;ȔKQc{Qhʗ`a)]UMWtGfڴi- ӧO7E٦MӪUB³cl#7+>@@fۏQ8+>JS%ne[%հ+j@.]hNRQr5kCiɒ%!^{6Cu'Vz;!2mޜpb0%h @'##;gWLKv?DM3B^uÄs 739SIx q;wn(jW9*+n!B$BM<;v2o߾ݐ@@| rG춌QPe767ռ6> MX2EfU pKN÷mf֭[*c-̹xM SI{n#T}NQcH-;BrD`mV)nhlfܾy<#Ȕ $n% ē/ %_Hظqc+ !lkonj9 4 _֭[7ZdgfƍF>/qb(QMqϧBh $L+*]Xjͷ2'ڮQUWٹeYRZQ"fH=V\BkM,.$74? .:3׾5SNɬGȣpMk%ՠt* ximC3locZ_a#̪La9XƜ*1͎Vݻ9Pvf{躷m֜y]we6lM p4 ={̿뿚q]qnYlS{wE" a_Xڣ- @ wϴGUet'k.>fM*LfW~O:5RRx\p N 9yĈ.,UyXǡA _#S{<7[liWͣk{Ǐw~ߛ{.EbvM??+ҬZȋ/wjqw5^ W"{eJĀ@ `,<47+C.C^Ϟ=)Փѣn-+ ,O=6loF2_Gi;zӾRc" !_Xڣ- @ ^MJU< -2% 2@ cIN@Cm?]ՀCWnpԤIrcg-ɋkҥFUw='C,Yb:j٪~eCfpPæ_~<2YƇ+Jh O@iӔSicҒ(SR  N͂#Ö́kEFBެ .p'?1oV)# /~Fe_uP6W_}3pLzC''n۶MZUc @ Y)BL6_7Ck;vtBcP{v2xO8хVv 3f0cǎ5sV蹼7Qp~")㦚Rs!Ohm Mw @@ ˯ ny2du)%lt+$ǎF/+  @@8n)Q೪<TBk2ȡ{zph *W!wtʎcJ^0Ç7?\ڍnLK{mnٲ#VB @ 0np (<;tۋrpޜ3g#K2h WpD O-/k)"bX7x+rJӶm[}%8SQz#G82 M @@ ̿MWʳk׮-a3lUN xG;J@7+V0z2gqh XO?+]ȑ#ͥ^d")[e߿p§klv_1n @ s3+|mEطw^К7ASaw AiƜuY竫x>@.]j>n=ܹk̸q\U8dJҜoQ֭[鵩¾=A@ @f7kf;,? B0(&۷wl-G]wq 3z!3bؤIgaK.1KndN'N E%/)&  @H)[}JFXئMBDPlUF?g8vBysgݻ̘1cܵZHY<ԩSxʳ)O֭[vSl_74@ @ ]0nke;Ç;,"۪U+pVz˽Q*?j(ow^@͗e9{lW 碋.2W\qi׮]"%vիW5kָ2ʌRP7 @NBi_ȯ=q^ MBl2p*4Ϟ=.7]UZݻy 2& PH_]^x +VpG%\d@_p+Ըq㠍7onP- @)#q3e EE!眔qiӦ.Zacze vL881:l/KwWr*tכ}cLwhՃ m߾z4D @  ,=++Y=i>nݺYCsdܱc g8piѢEa`={E; k˖-3'}#?lN>d#oDZL⊢l>:(}ݾз)A @ RC|m" ?c)? c7on;;v]8?׺P/h㾟뼩6JvufS`R7`h& @Ͱ׿+<:dˠr8*8湸ج] 64iҤ|3q R^ҷ~|,U QfϞm*SOz2G(-ytRpп6E5/՟,gB @I#@XzV$]wz" *Eɓs8rٳG*M&Nh8~РT{q2)\zΫzc-?Qdzfr|8zߨ,w @@z ๙޵KAn2V)O3UuVx¯ݥK$S"dPx7A%oN#++h ӲexIЬ ї׶n;^A @@P!C*Jqp>}Lc%S߿̟?!sM` B՛ߗ6%r.qfܸqsqh&rJU&:ur5e̦]Gw`~;w+VeihsK @ $UȆ O"ȑ#Sy7~|ȓv 1˖-s U~MoO7 m%B}Qs}畫=z4 yX>yg]_y6 oqY}׮]+m?zC @Ef3Nm>cˠk`t؇lSFNu*?Drʻ3j$`P2}]3qD3c ' ]p\y\7x)|ut>ryMvy\ @b$q3F3VPlU@xbSkKMUQrVl*$NآE>ϙ%Ku+,U;2 )]{6=z|fO[OK!@ }7ƅpqG{ G΢E\>bCkw7zVݩh٩W0l/'e  @:Y_*jG;F@+W]t:tJ4Uyw5X;'1m殻2OcZ4xgEE F k!Vmmߡ74@ @ 7X8TŶ$G\˰vZag?l[M4w7zVݩh(ggyy.$_@⬳r艆Q _4֭3M6uvΝ&ؽ_c@ @f"B @'q3k ;wLxk%+&ҥKbCKԕ-2ۺuqŊ^uҥܻSNyOiӦa ~/ڏcs!#i %`->xWͲeܚ(f۶m&*Ǧ͵iq2h @@`X=vy%Q?S_Rҏ~SN'ȞLw씗rwm2:9! ϪPމ'S)oMym# ɓ… ] hm߾}|%xEK+$ۯH@ &f23fpt5&I?<6ucmwVNA @ޚ'AVmC&A|pAgT *2T|ø& h(B<ێ\2x* QWӧ޽{2K2˳ݶ#+4A @ǩ@;\[zY2Ȱz ଞ%ܝ޻SFOGmT8*4g'P޽YjF״a?j#@ @ 7YyM41Ç7zUN@F)y*)D]E.rrUH UE2e?o߾[n?A׭[g֯_) @ 6a1P(5BgFz%7nl;Q{5K.5*DΪ L@o6'f ;˗//glY)| @ Bf @5/M >-%YԼy 5jTnM GdR@TW_5˖-sUԉӓx8p@I3 @͐V;y"}tbdģUN@l:vh=8UQ}^@ QK/UV9AtL0Y~;@ @@0nrMM+'7SG$<Ny6m8pg) ' .g̃Z,YM~=Z! @@@0nVQ,'ZIDAT Um'؛"QUMy{nW\iOy8 H۷U9t BJZ,/^l/}/4 @#q3O Ooa OW9hUS^߳gٰaٹs+LBh&vZ3i$ ByjZjUh1R9"~ KA @8p&FWZĞFF+!gv &2ln۶0`ӤI@ .\h^y"BJ!ff:gVCNVtC@ @ 0n'՟p&M65[h)/0N$˗>}- K M@3f0ӦMsSw 8Z. G GT @$q3EOʛl{ll׮]2x[-yo*L]%%%fɒ%[n>@"믿nϟٳׯp@Xir?fr3 @ TJfX#vlT\\쪀S$v!Cn;B$UWHm[l@ @.0nօI5;6tȿYPa&ӫX(2 c6o3gW gKŃ֭[SUU!@ @0n'D@7/~CF!Pz6m1SbZtQrqR~\9+[vҤI.O4ƀo2s~Bn{Cr: @ 0/~ UceaHaԭ[NY ũ")2l*D}ٲepgZr I K@Oz-|/Z8 @Z:A!(Ѱ5ņڶmUoڳgOSF@}, 6]v5 2͛7O&WQWRl[ne @ s8/NoG~E*} Y`RDM!@ BY̑oW q޽]8i' q۷իW|_9xx1TgU>={3g-+5OVM~Q6 @ rEq$NmQҖ-[<[LU9Z)ﷅ ^t&=J)l/3+<2 E7vY` Lv @ \d Lt[A]vE͚5[_TTd4ZU]͛g ExenS_~egW  5x|r m  @@ k'6W xw9Oo͚5FC{ԨQfQ~3z֯_oyWKG*f^AYŚlۦ o  @@>p'vɶޢE 3l0r`5dܔSN56e1bFgc֭[gfΜYnԔ!Sa{w1LyےQSMT?74@ @"q3_d7N=lۺuk3d@!̭PT\Y=gؔsȑxцpĨڵk 2jXPϞ=1h]mۦpt5{mvf@ @ `7^>흕#rNuNz96m8eG- " aoܸ )rS\8ʽtRo=㎚@ @ 'q !ΰf{ۛArndC>\]P :t(0̔)!̝;lٲ馿]ݻc,j+-Œ%K|O o]N @ wL3UǎI' "#Ν;]Do}u{fM &i̟?̛7`ިQrOMy K`Ϟ=fѢEް{;l.@ LfȫZUrcZLk{n>,coT^Nytʳ{9o#GeT sT$V2l5dgY @ %q+!ʫBWމsFUe*G<]{y&p!qHHFH35"/ u/} @ Bf 7RC% ֭[SOd6l˓ڼys0fʩyQ'@1e̔QSMZ<6gF{╊!@ P ` u{Uq߫W/ӳgpI$HsTQyr*d]7nl  LЂX7/^5) ͫsuiz=;p['پv @ X`܌;L_!+,Gl۶mΣ3ZH{C qEIK7y\RUڵk *$/MmӦ Zf4czm$"@ @ࢣ#pmx$Uǖ7e2zz1%rNJ+V\QԚʠ)æ׺/[Xb7ljtPC@ @ 0nfueѫΰΪ,'"M^TuhcQ]ܝPH`OuѫG1߿K^׫ ސ)cWהSKv-i&~zczϬHF;@ @ 0nfa!_ہ_p.5ZXdBoА 2rTFê^5 0Uv*ˀYB|Mh>ͯ.YL}F +W"QeϾ߰(- @ f7Ӽz^=$~5L*E MA@dR7tW!RGuo'5eԫF+|Bֵik:^+oti @@0n~m)ݻG9c PN{_zc ڧh1eg4Ԗ,Y9lj{>A @H ȑtJ:}Ev` TPեKW>7UJ , @ 2$XR@І m2{ :tpyk7GAmd,zؾ,^_{w[W]qw>?F1H \0BD# hMD>$bP?L0>b2{hSoF9/pνmׁ.|{@@N\xQbCڵk5]#@xGxG'k  MiGS=xi`|$#u\S#ԓ۔dzU@@@r|RN-vmRuttdO;F hyؘXPnQ4@@@^ O{HJ ?lQ ށٹ:Gu@ ۷8Նk @@$u)#Vo4u8[[[Y3'uȸ@X a:-z ު%4>  T+rK \+?tUUUnݺ:Å@ {333aΝ6uU  TJzK: O|;6n4uc@ x]W_}5>ݬ^G@@`ZzWhҠ\:::|5VqOB %.l r噔tn   Lj)3,PԽ?\<ꆇCccc0 +-0;;5.l>\Qh   @ 0-17wRB9_)vuu'P< i^_sbb·SPPV,4@@@ 73Ʉu<3C}}_@wC߷os6W~@@@L 0-=SMH`Z}RyY:==ݠZ3ԔP,diА¦G{@@@ 0r3sNXt]!ś}jjjSΦQnQ b|@@ ,v\TRTQf   y(Wtwwj!@<6څo++ @@@D%"@cMH8s  566&-.%055ܡk_@)V?   PN,E_"pnŌ |---Z~IC &Aa߾}N^[nD.  #7WC`EST(j4wTWkjj '"|) ;v^own'ԭ)+.B)&]@@@R+@$! +W7ڼys4ӯi P0H#5=bkja ` !@@@P\߃@VU6 Xaosk~AC@@X[$-Ъ|MYR+vuu:::"q}XB`ll,|>+:    '@qn P.tgjkkƍC{{_@ e}޽^W3MܥaPʞA@@Y^ϋ" ݏ+Moz4HXjhC0uǔە= @@@$(n$ ?@ /*QU-*rz!*app00hff~WD@@*Wf>[,[ݯ(TriӚ:[- >|8ZWsbb~vud   @ PܬGˍeT\7׬Ym:B')FjWɗ)@@@VVziEJuE ! .rh G)jNcS   7/!PU ʝYV!pG %#5棊Gk<+    %+w([|+鑜4 e \mGjg=   $@qs )|)yC 48FQa].   й$ xG9x!yMΚEC b1v< }M#ʞ8   $$@q3!x.@ \Nr9OWoll[42'0;;D|(AE;M    PL֟#VM8Psss&g[[X988 B|#:qQe_&G@@@tPHsE[FE 6PZXQO9*?_}Ct@@@R$O\DW@ Q>lpBg}}ߢ!Pz~hX}<Q~IC@@H?@ \ż^r\---9u=ixԜ=mʽ@@@/@q3ψ"+OYF*e=[.Ԕ~Q^Ks(^}? @@@YN"*&FG{ںSS-#.P,H4JSkik:JZz>?|S4@@@2Yf""\!Qq+F׮]˴Uv>=:|VU^Sh    @q"@ Zԇ(7))Q{mNFuGVUU .~Rq3>y"[K)-d[Y3S4@@@|"Gnʹ%yΏ:tEO8(7qh 16tBfkg   "@qsULmQ<ܑ(.|o`䍍| 1 2 2 5 ώ@IDATx eU}LP%huQ)ʲ&qDIæ%L]$j)i|@0R4¤ؔj(<0C=̙;?}gYk{=gp=6 @ @ @ @ @ @ @ @ @ @ @ @ @ش' @(!^> @U=;#@ wmq1 @rY@6!!%/J @('%r/^[O @@e/nr_@UC vi 1l% @ 07 Pb~m鵍 @  @n鼍 @  ]͝XXUO\^6 @'^|~Z&@DgSq:o#@ @`~ge @` sli @j@Q lzvɵ}# @6"ez&@-Q}b=Qus`v @܋7# P16>]g#@ @ {|Z"@T1}{: @܋ ǜڧ6 @fp/>,p[e0T%19t]F @g7 i>^O @ {\!@R 1r=S= @܋S x,}ĀXgz=S @@u}֫Є @H((  @{B /mTF @܋oL  -? <G@[f׬g^u @2g?c @8<3J)>T?c#@ @`oJ4(ј3N%OsvV؆___GCokrbuq  @5܋'15ߺ:.'@%8ӚuR;CmGx#ȓ;קz/Zzo @@ (zT @r ]zK `tϮ17uz{j` 0o @d^q_ @`&E#>;踝5SnC)8E @`5ދO3{lLޣ&vs @ȹO؞vA<~& @jtKWEioc @3 *Zho2Ou&x‰$@ PB{/}燢o @fd4hcj7q;+IwK @(-Pxk8h>6 @@㢕ƼS?Cl+ιX9gG @@eQ{OOO @-uo6uj{_tW{sj`%@XjşMK&lm 0?c)}0mr~TaX۩e+o|1QF @@(G~!ψv @Eot~ 51vwo @K-pQ̾EA]mqE1(!~QFfxgs @髠}i_ymG`|-  @`.+}сou^;$@ @`6GwHZ}^vG` C #(/q|oC @fxꏜrnکæt<>4~,' /  @ (5 h5Lxjg'vH @GXM( @@Wvzw! @ps.%@ Y?\:&@ @K/NCT!œmgGQA 8m @ @`͹j `/qw @dXzvR  @`i3?'זV  @ @OnzSQ(#ʕQl @ @pN PŌUݬL @F%Q- @ @ 7[ { @ @F% r, @ @p'@ @ @`TQ- @ @ 7[ { @ @F% r, @ @p'@ @ @`TQ- @ @ 7[ { @ @F% r, @ @p'@ @ @`TQ- @ @ 7[ { @ @F% r, @ @p'@ @ @`TQ- @ @ 7[ { @ @F% r, @ @p'@ @ @`TQ- @ @ 7[ { @ @F% r, @ @p'@ @ @`TQ- @ @ 7[ { @ @F% r, @ @p'@ @ @`TQ- @ @ 7[ { @ @F% r, @ @p'@ @ @`TQ- @ @ 7[ { @ @F% r, @ @p'@ @ @`TQ- @ @ 7[ { @ @F% r, @ @p'@ @ @`TQ- @ @ 7[ { @ @F% r, @ @p'@ @ @`TQ- @ @ 7[ { @ @F% r, @ @p'@ @ @`TQ- @ @ 7[ { @ @F% r, @ @p'@ @ @`TQ- @ @ 7[ { @ @F% r, @ @p'@ @ @`TQ- @ @ 7[ { @ @F% r, @ @p'@ @ @`TQ- @ @ 7[ { @ @F% r, @ @p'@ @ @`TQ- @ @ 7[ { @ @F% r, @ @j#cvrXճ49x*O緭,Qn] @n.Z`1U$P1Tl,. @@]ͺs)Ӝvڱ]< \r盫epC3Xo9c&.یW_}K~ @<|PNیgTC`_-^} @b x|hXR[/]ٛ6v ppD9~ו @S 0âGyޠ9|ӏA W 76DQV6޲ @<N8hV #?-#G1/-t͔Lj/W`>.2wnNր  Cࠃ65~r4 1V>"(ύY @|ҟ-ʏη C`_fVJ_KOK`oX J`'|̆+@@9nҏ=io=YGߑ @ sheQ2O݉  @Xra.и }76qeH嗢xlgK[mQ3<ٶI 0@KGyCӢlrṿam @r ?CCc/6(=U  @X[cQ^%OFIO:6 @R nv NG8&@ @ @zl(Fy|7F. .Vzd5Qҗ;CQF @M>c(GFV`fVž @@9xǢ<˹@`fw:[j8&@ PF7FLz!@_Tֻٝ  @Rt((c`#@+0Djyl'@ PN([ωQy @`TC](w5 @(#[(iQc1uQl @Q,JŚ|l7 @ 0<6a @`6-xF @:˪  @ ,'7C6! @ @ 7j @ @Ⱥ @`ナ1-ܒ @@~E!):k@1Eb:"@~4_on[ߺyhN<䓏i^g4(1 @0ψn_('Fyp/D*Dy{;܌Y`98lvb(m^o#L4~SO=vSFLMX`KϿ<([  @" (e_6E2͘-}K͛أkfs7M{ c6  @Lwb<6dp8?Ҙ桪M L!3ptO|^ ?=hs~QsMy4W^g?i{_Wߝq.n @ GLG('E(=q({~}7ޘ8j G'_,-pm;'{4O6C~~Xsj>>yۛSN9y 1ͅUGm.˩lzԉhV s|8ʎ(黢叢Q(WDbEѦ1V͡W@E[w4ag椓٫߿yOo:h}C2 @O }Ji]Wv^qDe81%|n=5kSKi6EKwЫ_}}􃚳x%|~kgyØfS&܋OxIǿO^ǧ>yqCcʩ- &0Kc.och()=%N+J{3K.t9>amnN<]:cs=)k/߹s30U'@{cIѝ|6뼞vo~mӘz3H`1_k9!tnqz|ιw^|_yQGk_]J|Ø6rXKZB'@`߼L^u%ƴQ1fDΜ/sz bv^;$@\=}ouw]ǻMXKZB'@@f|QgF\O`D94WD3Oq5qІ9{E{v6G5msi}L^ӭ?>mN7k]p/^Y'S`s|b`nNS3vۜoZÓtOϹnMkoni;G`i/Q|3.{il_Eyh};Gّ^ 0o<`WwܱwOx c %^|-! PRZGǓu4%ƴ& W  ׯB8/Ril\;m}ww3yptz5Ap/n* 0gMw?N99q}d<'&XKcZKU g ~3ʧ'0>5qKUw߿3߇6pӘ'@ @`1\g7i10 sn>>FyH/8%*マJj~Voۦ1*&^|5 ()Ng_){jnziLU$9)?ʡSqS;EyԣǛl|ӛ{ۗ _*x[w47|r-;|saLpp/RKt4NSlNgq|JyhFaLp-@rI^T~[+ o>~@/!^ 0syڮfw츷yիvK_lO:wa~Ү߲u͵~}kCǴ!  @@9A@n ; Og3/ݹi?n?776}Lp9z68gwxW:QD(6M9>pus5BshN?qCrPwwK_ڣ?yܴiBxLJDfL6fy,1v{E޾ا@D~wu~ @ I'\u6 9j|o]tdxw/rȞAuSu15Y' @`^%]r \ _BO^M _DyUzvծl˚4uNX 3_9nwyjm;cfn&ҏ ѿo7wD'r扫ܾHc盷8>h<[ۘ68}֭6yQz2O+h>=~DG&dpn{ڀ4}wg{< mLK #0c( K#Gޤg{{jWsV @3Lϖc8m_+L64'IDAT2aW h^? 3?sB@,  @jxuL7W& 2Eӂz$@`ozǛNcs}B`Ǵ0A PdA}4[db81 <^\Py{Ls꩏n^47/8.! @,bx(,PqL Bc ,  ! ]_ESy @`~bgcZ@&C"PFceB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dnf @ @eeB @ @@fffP @ @ PF@YY/ @ @dؔ=-e]lz @ҿ[m @ ' ξdSgW\qRc} @%%i @X,\rJ͵ @Hf0k @ -5RIENDB`././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.8252432 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/beam_stop/0000755000077000000000000000000015060352601024510 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/beam_stop/beam_stop.png0000644000077000000000000005426014777236751027223 0ustar00rosbornPNG  IHDR7U /|sRGBeXIfMM*V^(if7U9sX pHYsgR iTXtXML:com.adobe.xmp 1 2 2 5 ώ@IDATx %W}!ְ <!@20Hb-BY •q XI;6Ko"\HvXJ@(0"c A$!ף~]u}g5}o @ @ @ @ @ @ @ @ @ @ @ @ @ @~;w  @J/ @j˪ @{񮍑 @xR(io#@ @{rz"MZXF6 @ EWyL gܻP- @Vh @Mf[k @p/|c= @ -i^ @X{X`g(p3Nm @,OlL`m: @W7sez @X{jX]g#@ @ {|Z"@VTʘBt @|YjXA1ۢt @܋/nnX @`E>nsOץm @,.^|qC- @+.>9{W  @p/KR; @J  /:ճ @ _x;5 Nc["@`E^s}N5 @ [:@"@V[ MQQR=06 @=܋@S 8?^ 6: @ ߾F-?^#@RhW @d^u @;ۢOS;6 @.^|V$0 @4[p*~jwloE6\taQl u\B @ @ QM/l  @xoi:+v6 @@'E+e~xN @^Q( @^a_Gj{F% r &+Gy~got^;$@ @`1Gϩ~ҜsN?s. @`<W #3 ^ @P5 h5LΌO! @ &HFOn@9O^i:  @ @RKa(VN }g 0 @Xzqr @ Y<9Dyf[F @* \*  P@ 63gvƹߜs) @ ]cI5H;fSQ>&N @E|r( P-1rRoFI_|8 @na Dʄ @ @`RKr, @ @p'@ @ @`RI- @ @ 7[ { @ @&% ܜr, @ @p'@ @ @`RI- @ @ 7[ { @ @&% ܜr, @ @p'@ @ @`RI- @ @ 7[ { @ @&% ܜr, @ @p'@ @ @`RI- @ @ 7[ { @ @&% ܜr, @ @p'@ @ @`RI- @ @ 7[ { @ @&% ܜr, @ @p'@ @ @`RI- @ @ 7[ { @ @&% ܜr, @ @p'@ @ @`RI- @ @ 7[ { @ @&% ܜr, @ @p'@ @ @`RI- @ @ 7[ { @ @&% ܜr, @ @p'@ @ @`RI- @ @ 7[ { @ @&% ܜr, @ @p'@ @ @`RI- @ @ 7[ { @ @&% ܜr, @ @p'@ @ @`RI- @ @ 7[ { @ @&% ܜr, @ @p'@ @ @`RI- @ @ 7[ { @ @&% ܜr, @ @p'@ @ @`RI- @ @ 7[ { @ @&% ܜr, @ @p'@ @ @`RI- @ @ 7[ { @ @&% ܜr, @ @p'@ @ @`RI- @ @ 7[ { @ @&% ܜr, @ @p'@ @ @`RI- @ @ 7[ { @ @&% ܜr, @ @p'@ @ @`RI- @ @ hxTQz&G`O`e48xs/c8FA @`u)|jL, T'pf(  @% ܬk=7Olr)i5 0}ovj4g\Ql @Q (kQF @'0ZsOm @2Lp(ύ2X{ @Hfz:j-ʏFyH @`C(/(6 @/;( c @`MO  @LPc\4C&@.pc[_W @%\!@F/pc_v$@P =j9O(6 @@MWG  @F(;e-JM @`e 7=v2LL @`D)<'Zl@ @)',?|5'۬Zڷo_slj|5%Uck,4/ᅠuC`K`xC>vnR-(&;3X#%@e ΘPNۂTAHΏ-馛JtǵFC xUW]7m pp?r+ @@qox:$@A_AGs8䣧A 0zCOGY(]o @`'x2&Ws񮑑 :{c:5SH?,#wW!ssrLsLsEhJ 0-{c׮}E(gGI @`yF8Rm 7K_KOJ8޶@3w޽{ەU @@( .hvYs= @|\(޾;>F$w%ʻF4.C!@[ 7M|8^(%[`_ನzfl͞=m @H(F97Z 3-}am k K 4>Ϣ,hOU @67.&  (ItFX)E.T|{c @ (O(7D @VB WJ$ʮ(Fy{ @XgWE95ʳ\[Ql @jnX[o%  @H_Q<^]O @ 7zW1 @2֟]: e  @`L~mu33! @:1~r:d"@ @ @ p3  @ @( , 'p=nP4%1  @c!):k@11f1 Pg>onnNhN`|'65rJǤ17"!>O4i&KJԉhqߎEQ%}W-QF9%DIۉQ>b Ѧ1-V͡W@,Empg<8h<ͅ^ؤ>яYƔSc @xT 靡%?y.qCcʩ-#X$<;MkSKi6,E }B{ܹ?mx"o"z @{/ @z蛏0/{Ww'㜇ƔSS[F&Hc._chri`۞'7J{ͻ9}w]vj_ݟzꩇΧGӿL͘zj+.^|> ہ8y=;'O7c-=#X$Lߕ(:eݎWF9vm(io#@RhI'ԤϏ|ɇ~Wa'|aL N]] I`wg0鑨{:~'TiL}!0b#zY粇qzιqWl~.^CdHl?=p?{׿ 1S6p/ *}d[5߻:۽Ę+zX4LS}S?92_p[-  PyCot0{w.}ޘzөH ; #>z0{̓Pgv\O`B94݋|3񳢤Oqۧ =sX@7H4ks l[}uۜo^{tϻ9("^Nآ;əkg.l[}uۜo^{tϻ9+#+ܼ5^ۃ/<:JnQ^ lc9P[q/51-*ItG@ir|:%f_oM/1M\@`9xo0j~!mN @`w}J6m7k]p/^ZGl"pc3;^sF.pޘSr}Zg¯{_?4=J<;#@@W~'3צoЩ?;w<:ׁ1p/>)kN꼞w 7ӏqE Sߘ: +׏?FyzC,EOnjOO7;O}Sk8|8XqmEXHB|* :"gW};}l'GwopƴJ $oG_`HZmQ? x3ywټomnC'?|s{lsYgzl^,/{˚/~2'@bŋQmsmtDIwċuNO\y^_X/& >mr@=;OG ;mnYu:(}lq(?F 5r>פ3h/o>O={>tKr gVmL[ q p/NM++EnR+ʭQΈ2޸wҙUӖP\DE> q_]:o|/#}FR'~/nwH>k_g=9K7j(^|Wݜ LG1;C~L_G 6'ї2uM`@E7Ƹ8FbfG^ӛu~ @ ݻK/9=Ascۼ/m.樣{otam1m0e  @ {Z$@ KyYq>}G(yug<ٹzM`eL/\pMzF`nփ[jN8&{6qK^򒃗o;Tƴ]@"{%MT @@n8zzEI5\Ʃq HwHs/ƴ@=~f=fBJ_Pv&WW/OsƴS @1Tl;vS\fj19"  ^{msW8sF11  @jxqLW'[#4 P^@Y\IDATLPxGs]w5O~?3Fc @5 bL&}yH&610Xzys= 0AO?9Ӛ?͎sc2 @y+9qL#1 [ؖ_K\<1> @VJ'G81iLD8 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @, 9 @ @78 @ @̠#@ @ @p^ @ @,#s{_ݻw#44 0-V @ 7/ 7pX_ @`EvEj @F# R,u o^oq )l[fM @` BM{R^IENDB`././@PaxHeader0000000000000000000000000000005400000000000010214 xustar0017 gid=660979062 27 mtime=1757533568.825904 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/collimator/0000755000077000000000000000000015060352601024704 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/collimator/collimator.png0000644000077000000000000006263114777236751027614 0ustar00rosbornPNG  IHDREbsRGBeXIfMM*V^(ifEbz pHYsgR iTXtXML:com.adobe.xmp 1 2 2 5 ώ@IDATx dE} 0『(Bd1 !JqL0 ]u`ܸd9Y$bjI'1Fe0 l՗6鯿~TwuuJGݪjosowU) @ @ @ @ @ @ @ @ @ @ @ @ @ @Ge=ӌ @z г=Ԑ @Sj УݏC  @p/>>k#.nO @ lC @sn Op5 @{ Yp8&D @F/^|F @tpNϸ @ 0z76 @`}Ñ6q?W @{ ] 0c ݫmq?W @{ Uph+ @NlLXTpNv @ OoGEx}e$S.a-u~˝&@ @` /un @S7 X<@Ք @@{@҄ 0 NgN!@ @ {tz"@%к[2>) @p/RO @ -wZ'>}vB @Ň7|G]'x 85ĿWsb{ @܋o @@W=~ʁFq @E @ pD=~N!@ @`p۹x}~jD(L;u2 @S'0=M  @ usPuA+ ( @p/>K @)N + @/^3WJOM岚.a~]N @X CF>Cr @@wZ?9g> @ л{ޭ$0˦~&Hxeg!C~h~ 衣?moф @@Ji )}ڟ5 @ \zkb?Gu<탖䙍[ @F!0 嫡~x$@"pxhMK/b9 A-%&@H.0-Cmޏ}orQ @zh&{qYM/W6 \wAW.i @{ * @ <*xSac0h3ՋmힶH;  @J 3{۱$_ A5w$)& @`6N lޘڎ(A [$kYEp @Pv/ d>Sa{P @@? 7&)?caz.u"|5Em"@ 0jid:2_ߣ#l1 @8 9I(! ڜ1mAk_Oy @F-0n^P;CU @^FoNFU_ڂ p9 @!0_nOZ{> K0p}2_5l>Hq.>U @4ߋז3l3& @@VQmqrà;Cu|?8v1 @)0P{R @"hޤj;iG`د ̸ @3-0Džm>lW !X!@ ]C6/S?__Q^>?=n P IB @`|/ﹿA>}?A(Bee3/\hc3%/F @(̾m~XA}-:ֻ'1P1d e VƶM @oƯz|7? } УJ3*ow6={aӍ} @ 'p).n6m^v9S! ):h.pgPOmDrqQc& @ :F`V>?+oH/.:b @@F2mh'Iщ[ @X׈+aƾM @8/tB 0'䌆ş4m @ @ %>o38 @L~M#xB~3uP  @HIщ\A @`bB "@ @#Y  @x ^? @ @T/ @`dꡡj k* @ @`$E'zyG"{F'0 @ E]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.]p"@ @ @`$EoM͈ @ @.˺sj !>RE]/pOC @r$EYiLSVȢ%@`HX[==#@ 0YKE3GYsb-ՅLW^YmݺuV^][n PM͛7ljx4 @$E [nLuYF.dضm[ǤhG/8?:)ZDDO @@?T  @ @$Es% @ @ HhB&@ @ @`pI\I @ @@.  @ @\@Rtp;W @ @ Ph&d @ @Ε @ @( )Z  @ @$Es% @ @ ,+0f!)p7V}{۷r˫#8s=[vY]Տ~ֱzcOR,gQǞRL3͛7w)W\qEu?4׸?>׸~+VN9j  @V@B|Dܰ׼5Yg%<_&@_3?5zv_kL(t~$CL'E`BU5kִoٲO>9ϩ緎_~sIIn_rioߥ/䰖;v쨮͂rjڵ}SŸwe. @+ ):K>]~}7%Ecz!+g}\Rtۗ{T'~w)K39w1)q"w;Kfi?L\Z* @#Y+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @r$EY+ @ @ @@R4. @ @(G@R) @ @ $E  @ @rH  @ M0- 0*c8?ws Ph (| @"e$ 0)kC *L.) @ \` #<:*K> W^YmݺuV^][n PM*I  @@LuYc0C`۶mA>0 Z  @ @( ) @ @_@RtF$@ @ @ hF|C @ @ 0~I @ @ M @ @$EonD @ @2 Hf74 @ @  @ @( ) @ @_@RtF$@ @ @ hF|C @ @ 0~e҈ @-K۷2+VTrJMRI%g),5]cy_p|l̵ܿ~m}}c"):k @ Ї@L^x]83Z'$r34 Yk?֭[X;Y1Nش{5jc u?#)Y @ -P?!jժj͚5lRx㍻)nݺmg>QwC͵KFNJku"):k @ 0@L_uƍ璢m~bL㌧ufw+Wz۟a36iQ>)~h-m  @ @(^@R%4 @ @GK[ @ @-~ M @ @~$EҖ @ @$E_B @ @ @I~%@ @ @xI @ @G@R-m  @ @(^@R%4 @ @GK[ @ @-~ M @ @~$EҖ @ @$E_B @ @ @I~%@ @ @xINt_W6 @B}~H  @ LbR0zkCP @F+o5B=5T 0&dVq: >3T @ <& > j|JT!@L@Τh|=nPsW @̄@L|Ʒ6U!@̔@Dd|=~C P @F/_?=׆ @ +)#f @ @ 2)]w @Lwm͌H$0-n @!_P @ER%E @F(_?% OO* @K zN @@L|PcBԯ Џ Iq0=&+m4o喹\sMu=;Zǯo_rioߥ/䰖;w]( @Sq[@3vn{hsݓORI%"戧'uJe3Ksf|Bl z|Uغukk[obm/^{mk{)}ɱG~m}Ҿ?Z:N* @`roIX!0xb3;I')#),͵6n:e˖vx~Zڛ#++tP ҩk @ }ݗ# @@)?x'8  0k֬=ӋɣSN_Hcܾ:?mƃŒ KCI.6R @`r('Lm! ՓF"#@`Fik׮֯_ߺ.*^L/=7voϞKNrcO~.} &SYƹwyG!!Qh ć~3 n5-ŏp QFlH4t3н4L @4 t{}~z~)!  @x8tyY 5^7q @aJ.  @H._pLJzXP @.!oueuO`  @PWP?P @6Q$E!^_K$@ 0>e6T׏H @@AL6^԰M @`<<'gh @&W`\IѦ  @G;a uu'P^ @`erzB աn* @FP7ӡE`ӦMߥS @ =ϙmԯA8xtB}U @ 0zE)3~iOUY(pOݼy\]x P$EnXKC}B  @NBP*~sG"@JĤhmY^_$@ @`!. pEJtCKq @ @#)  @ @4II[ @ @<ϛXT`StѠ @ @!C}FkC?ozMWPw:"qj HN @,WwB/?&u}gK~1Q1ZX hЅJ @Lj{ၶx.gŮFO T4M @LBkrޡPlXՈ[a;&߭|dS6.$0]$ED Bݭq7m7@l @@h.!@`+#VZyR p^L > / qƾM @p/>+ @h= f鷉Ӟ HF_ yayƧFr]ب1 @ '^|8?W V`Fw6loӼ~k=}N}i^ߩ ǚ}ש6;w%fNbC}徰n$@@ozӛիW.[reu'WGvzhqK=RoݺE܋);:lX}.l"%4 0{)2"oǗŹE.u @%܋/4ch>|P6_m~_1 ̀@ʤhzo_os] @ O7h>#)*UZ uRuxؚj1 @p/So &pW毾7/j-aF~~;~Pk$@ @`p۹|=t{sۿ7>jD}|}\x?S? D0 7?#5a|}Ck? uP @p/> ƧA(zLyk=a{cc6n'Мa78l77=%lo @܋o #?05:)lšƯ|#|%~%mNrYi#)aY]n 婏?7*lطI @@{Ғ |u76~|؎y7mU|}EL7I^/;m;Pjðݼq& @]܋wqZ"|Sp<><>Ըߩh;Xfw9v-~j3/~WBag,m  @L{i^]i;/"IDATs#0=yT:2B!z}{3ڥ<1':ԟHR3@ @\0Bʱj;0p9ْ2[ @ @`g;?|&1EBu$Eq @-];'1 r|g9k%R @ 0k 1ԏL~ca(G@R) ~Wzd=,c21Mx @F*>X`3q7u$o~⋫n۫۷WvXvq{\?}[l>P|]wUr!ՁX=Ϭ7W{Xk}cUkm۶=zg% /Ӳe (hI @" ):f Ck_Zu饗s=O?g>Sرׯ_:C%FʕW^ G?;ι'1cLg?٭|5c8ӡi__ǘӷoEb @ -lK@'Z/_^nuqUp@%?OV'tR]+z#>Yf|e%/yIuŴf͚C_sӦM͘jÆ 'Ux;k 5Z) @ @DIWM,)pV]w]']1n3o}[s @ )Z*6o޼SO=u>ⓣWֿ/-vǓ7Pm}luͤufL/?U3&O.J @L/L ~f]{w;~6u>^{}ul7[nuyiժUNGuThh`R~ӦC11u]Ν;;5s @LD/T?A#8w+rȂӷz;wqG^bzӞj7bb4ui3,mݖ:$ @ @ t|x @`4)ƺ*ς&i&j{MNԥm74V{Lwygf @ @ ,:ضx3tfRv}c5_pb< :uSN#@ @( ):"&h&wرd?6_d_pb˗$[ {[ۋmоu @ @I OdSf4S5lLsxA @! ):ec 0vfR=)q$E=Q$ O*|{L9uru @L$Z`jS{[K6Ȩn} S4nЩwj @DII\1 0nhm/q뭷.8u!,Os%oۭq9'Yrev։F{L??8k @! )Z:><{oum;m4~r1y]i&Nkol&wY-k3(5 @ @I~%@?|A7w_z1Nv]ve ;1A/|uxFk;F\?.;ta-  @ 0:b#@``'>AԺ@ܸ袋ᄏuNhme۶mz'>jOm{챻c~P?\. xӟ hq-tgul  @tII_! 0 _ֵi .?֡cF'xbkXfM?~%/է<[cX_o뮻֡ӺuZF/}iw:Ӫn>g3_]Iژ0K!g?O @ P,x+^Q?c|gM6U_}>:#͛7/x<6zV=q[rzh6/r_QckWUL>/WW_}KcLoyc_///so טIo}[Ֆ-[׽oC @Jh)+%N?tVOxZs==5E/zQ,c'F㓬 ׏% ~4oK.%!cٟQ2 @T@Rt:'@ GY_eW|vۭZjU7zӛTN%ž1WsώzUs9m&]N9E>~'R1uk @L'rYE@J+VTQz5\3?xiO{Zo|cvoS\a_1ʯk+W)hRI1kc?^^_Lо-o|ǖ ?\LG}t  @IiXEs @g߿:ꨣ;kЇ6>O:1Ikg>3zْ9*gg'ZH @ 0^E'_֞3StI9C16 @(J@R,{E__ƂqcL/;;;eoooqu-`E>^fˌ]v=ٖ_wi{=5k@j-YɚNy{ă @P~s[)+lk!@^ 2^OJwM @`k8==-gggmnnݲxܔkO4Kki|ֹuν1_I{-r{(e{{w @z!1}l͟fMj @ @rA @ @@R( @ @"A @ @uJ:' @ @Rt i @ @ (E뜌"@ @ @` Jсm @ @ P's2 @ @(ErA @ @@R( @ @"A @ @uuÌUN]Z @K 4 @dUS5U'q )Nb @ \@)گ]~-j  @7B!^&@ @m Om$ IENDB`././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.8264694 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/disk_chopper/0000755000077000000000000000000015060352601025211 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/disk_chopper/disk_chopper.png0000644000077000000000000011353714777236751030430 0ustar00rosbornPNG  IHDR5Sك\sRGBeXIfMM*V^(if5Sb? pHYsgR iTXtXML:com.adobe.xmp 1 2 2 5 ώ@IDATx \U}8K^$a' [HW**,h(n`/ ĵ.ֿummV (@VDhP)@e_d,q޼m|s23w9w'yߜ{oY @ @ @ @ @ @ @ @ @ @ @ @ @ P! UW  @I{=1^ @:'xlLc1Z @`L{Oo:"N- @tN{٪(ѿYi @ x/9[5 @%X}'1zL- @_{@W~f @@˭Y6 @aY__=~  @H_."P34v_BU꿅 @tA{. k(ѭzcB @@o @ m̬oKY @hT P!-G'.[= @&. @S~ PqWG  @ 0q'n @F[l:6 @v x/nQ @XlNZu:B @# F  P1׍=n9 @@zǕP @j /~e8J:R`!@ 0ǁ @@8*xc @.A frXE@&ؿ?N @|Oy @z#E4x&Q, @q |1hcWz_"* @({v.WCh @`4[NGhc7ߋhc_ o޴K @({f^(X @89cWK)ѴK @({_DNV 0^Ł7xLjy[4\]|` miV @@^nxROS"B8 Fvzl>ޯxaúy @ MOˣߋt 0adtyjWze0SֽWi @e/ ߉}q@3:'0'>O}bub}tàtw/ã5 ?e(( @({Q! @]83Zvl|L닰\A\o!x1 @TZ}lcZe(X{1P1@CLTആ 5}[c\HjbA =jW7מ @ 01m8|ZP+#PTuM Sϛ@$@ C'zض ]LͶ8?W7 @ uT@Ԭh@{rRCMix) @hf[9UF ki8_VVB  @ @N?8 PJW{F2S$%6- @ @#aU)J/ c * @ 6REXK @ @ Q^ @wG.2/ʣQҝ2ʥQ, @ @U9J+pMN @ @ N? @ @fIf  @ @ȵfGp @ @4 Hj6xM @ @@$5s=<#@ @ @Y@RYk @ @r-  @ @"^ @ @ kI\ @ @hl @ @\ HjzxG @ @@f @ @Z@R3#8 @ @$5E&@ @ @  @ @ , ,5 @ @ @ @fIf  @ @ȵfGp @ @4 Hj6xM @ @@$5s=<#@ @ @Y@RYk @ @r-  @ @"^ @ @ kI\ @ @hl @ @\ HjzxG @ @@f @ @Z@R3#8 @ @$5E&@ @ @  @ @ , ,5 @ @ @ @fIf  @ @ȵfGp @ @4 Hj6xM @ @@$5s=<#@ @ @Y@RYk @ @r-  @ @"^ @ @ kI\ @ @hl @ @\ HjzxG @ @@f @ @Z@R3#8 @ @$5E&@ @ @  @ @ , ,5 @ @ @ @fIf  @ @ȵfGp @ @4 Hj6xM @ @@$5s=<#@ @ @Y@RYk @ @r-  @ @"^ @ @ kI\ @ @hl @ @\ HjzxG @ @@f @ @Z@R3#8 @ @$5E&@ @ @  @ @ , ,5 @ @ @ @fIf  @ @ȵfGp @ @4 Hj6xM @ @@r PqvGq+7duAnÆ Oĺ'cxJSĺ{֭[wM7t5kk  @(fO]`ҤI#99x^[l.\aѢED+b_k׮E-zjJZ @ @@n$5s;4#@@{"y2[ Jz 4;7D3_{w\o~N!@ @=!  GHbΉaQj!y歋獱Hv^+}>tz @tE@R+!@@"99z(xԣtٳXz,V]t+4g> @ nIv]>$wFɘyi8_3\|gkxZ @ @$5'LhDXw`]3fs1fr^ @ 0fI19)07;ad7ft ߍuG3]B @F !m#ʨ;t(~Ǿ{Yg=[ @ @@f Hp >3f;_뾱~8'Ai @r) a-twXh~S @^@RsV$@ ̎.Qc#yDG @(7zDc37_4W7?~Sc @ i35;-~(|I''E: ^ @]@R# 0^̘185#n9 @+ ^O @@f?rKHn+_ @,xz$IiHnӊ+( @ @/"I)n? r}  @ @`7TTP %7!~}$7?37 . @ @'=a(H`j$7Hn~K4B @@n$5s;4#@ loS߶tt @: TU @@lĝ_Yi '@ @@$5;ZI&pժUW^ @( FLU@$KuM 068%yܼ8~^r9c; @ 0P*ȹ@ey~$HΉdU$= @g5-']|mV @&( 9A@@JD2O.Fh?$f "@`Bm^?/PM&@ @@$5+<^,uY~̏D6D^{J@v˗"$@ @@$55!@$,Sc÷" 254c)K,V wN|korGK| @F @l$I$: kS͇]Rsovȭ@n}8~`n @r$  @\M>nذ=˖-vl @ ώ4~z```Zރ @z) K}mhXxq_$44V_4mn2%?O~J˝l$@ s<9;f`WĬ:X @ @=4F8 42YZR=zN@wɓ' ~i7+^gDL @HjvU"fgFq̏#qXbIq? *'F,~G9OH @誀fW5F V\9'f\w9dxtZyu?N`%;ѳMJ;"@ @($5G e7ٙEBgt|Q;E{O`jۘ_˖-۶xዘ @Ԝ(dɒ1bv湑rڳhOUj!@ />}Q9MH @言fGyUN w͟?H0+"zx]>~ο?xlkk @ԜC $3~?fg^4Ҿ w Xz,?i ~s{  @ 0kjzw d=\}cc<5N:nJ @蹀fχ@eEVo\@5+/Dbs(tF f @ I #n1eʔK"p@zu$Z?C@g&Gb Z  @轀f@%G"ѝإ qJyML_ ~揉/Y~bŊ_  @ [Ik˖-3xI9R߆ >F@]_hU @읽K ӧO(*Bw"InaH}sy|ou6G& @z( C|M[`ժUE~e߂䔥KN)X%@`LǬ TP @B@R3 3ߎsy<Ξ=#c3%+g͚C K @TH@RBm$f:}8Ɂ"vHn P(+WܿP  @  h%0000-f7})m_Am8 ̏09U @켱J w8vʔ)ߍ~ S² TN`\  @(@_{:,h3ΏftV35ӍC>y]mč X&O>}iӦmw&mm:]{ufĶ-Xnزii\p7xc<@cSO=}kYK @]r85ejtӣO?se_x⾝wy]nרHPx}<ڍ02Զɓk  g)yׯ^f.  @LH@RsB|.@$G4K/#qNzcRr{DqHTJX5&(79Xplg}Y @TT@Rۭ"y\kj=5qs"qn~f=SƧl%^RDMQ\d֬Yߌc#hq{"r @. Yֿ1 fDBSq`nUVg>[ V.:.1PK`Hbl@v8|9uY @ @ m@TEy<=]OTޯ+%1cTKuç⌄H &pfm+VugW؅K @@$5+0Ⱥ8:Hh/^ޥ:qӠ5Eݒ%KΝ;}٫; r~qh @ HjnDbEF95%;;(q}ޟ~e^eӼ,>#f:wx~gyKAb& @Ԭ bkHM{Uck$59sGea"{e$1@Av36+hM @@$5K63&MOoQ%9cVCyj$DU׫"y@=x^ؼgSO=ghB @昸\"M?Kԧvue)SyTdoqjGuYtfY=&?{ŗ kgrM @@&J5ȿ@RBsz}4h7wvŋ"qGKwFBxHg[U;# DbsHl~;~6 @褀Uw.G2ďG8/fHV-Nq]mDެnkgl^x^ @_L11]91O Wt:hۑy(w] 0~=:/.SyМH @_@Rsv,@$$B~uDqJ'X|Vd~ٳoY_$vu 1Ewx뎵b @ # 9 o_WM6k֬w8eua$qڴiEev֯.'#ҵwϏYkUK @2IM J/ E'Ӎ,HXLt8wb,^7E(/G 3bVf9K8 @X@RăkY3,/ Oo <28Q/Wq)/@7D @ P&Ʌ2@ <$rʾx^w&?x,F"EQ.d1GX PH# Ϳ   @(dOK;g8~$n6HuN@ؘbE.Z @&`fFL# DBsN$;n5vs#a|ؘAYO'zH @@/$5{ Dbmf$4vj{*"ae˖hŢ(4}q6 @.`^XY5 @솲6"x 6Jldߛ #i}uɡ '9[O @HjNDϱXh'CQ D"xyx)ڼ%g]"HlӆTA @-/*I?Xw$2Ey_YE[t_ ~Oloe+~Z$@ @e݊-n^sLto+]$@@"ӴiӾ>000P  @\ Hjzx7@\qQ& ;MZ%@ @eՊ)uyE(@~M̬Oa; p @r% hҝtƯćF{ @q}^2h @ Hj~ف_GBj^  PXkN:+n=8 @0b,qb?1%@̌HrJ͐ @@$57f8N[/N4 @1~Ͼ'@ @=N8qWMv  @ //8q  @Hj`Xd6;+ʃ!_T}$/(Go @n HjvS[[J;~+p Q/_vy NL @W@R3c#AHh_(ҥK'w:E @@G$5;ªv hFBKQ__TNٳgY @, ̘1xؑ[`Æ ]ja @ .IvIW~k|Y+V!N ~Oп-s @ȝfD@I ŬAɓ':=S @+ 9^9uL n1=*b|ұFTLyxy|Ƽ'. @! qE@, <%@j 'Z][ @" 9-v\ 8:ސ @ Fp_xq_ @읽fM"Ό7i%TL pTۺK @($5G e 2>|KZ @"߄?[r峋  @讀fw6I'z0&@j ?dɒ^ @ 0p2wM`ŊiZ"@^{Λ7 X @tE@R+i%}VFnjgUW@  @hl!61(@_իx  @茀fg\: qG] @o^O @. Yu8/]oX PHHl'fYM @@[$5ʩ Zy6lxh @ @~ҥCiԇҞF  PhN>  @ U0Vٳg=N+  @.+Vئ# @Ԭޘ!t~vޞq(@|1e\o  @ 0!I 9x!catX?h%W^u @ PIu{@ʞ"(@2M @ 06eq lHh r@}y}[*S  @,p:طE{'@ l?_|V L@ @tT@R*Oß @ٚ[N:] @ȷfǧ(:Y): Gl{101 @ IθuP`CJ  @S1[srT%@ @ RE>d @@^7 :: @ HjT'tQ@ @@lMm @ƿn{S=zG _a\B"@ @mUݯC" M󁁁ilS[ @t_@RoqҥS&MwT  @ wԜ7eʔ7.0 @ VIͶr, ̞={u<̧Az$'x=j[ @tA@R Uj"fiNJ}WȝVn;r @hf(Uf͚Nہ@+VlM @@$5;g[cf!O*q&@< l<&& @&. 9qC5 ĵ40n DͫWw)'!  @lf37l`FL:&g̈\[3o# @ml*,oX @ e[,& @ 0AI :<#G, @@66ms @kx- S7x[46a @ 0Iq9/^ZR`榛n\F&( @% 9.6vm= @< ˤ,Ydjc @c#O >#n{ȭs}]n @cV^Hjٸs WI&3b'$. @c~ XvHmW`''2 @F+ 9Z)@|(< V[+ @9Hy#@ @`@ː8Z+  @@[jՁQt @$ 9 ,[lۘ6XA 4[$D @$5[6iJ WtI?L @ 0p2)t)1KCn@ M0t @ * YЁU3g|U}.h@~r|Q7u @ Hjv߼-Ƈ'@;{ @ @D3~~O(h˩T @" r4 ;=  e6l8j X @ P<IYO"^dHj.I%@kDbsuV% @0pY;wqї @[xq  @% YY1Lk:%߶[`Nկ^ @:# R:000>-.Ut L4i  @% YISLY֓5J _bŊmД& @hf K^͉% @@cym  @@$55^]O>4ݵ ktQ i @ HjN;@~I'g @@Q$52R=szд&  @@"yB  @[5Z~1ojV/  @U @E,hu9p ]6T`8KᐞFq @F% 9*lٲ\  @qàTN @(E.9u%.79 k#Mz  @h- ڧ[cfPg!@+i%@ P@IZC^dhé睆V?U{yq @_a#9s3U6h @g$@(fSO4Nխ^ P]WZu`" @ HjVvŋbKj-ɓ_V% @b Hjs:nvXzeP1( -@B$@ PYISϏz @R]wTu @@$5 4X5fHjvZ k8kar @TX@Rƒ)Nn^ @* }/b @@$50J]1n`f5C/~wɒ%S  @TO@Rzc>lz>,  PMMΝjv]  @[@R3ӵLrd(@m<a  @@$5+7Cw8f[6z @<=k @t-®5! P4ˁW޺  @@e$5+3#v@|}Wq] @ Hj:ʕ+7F4@ (l  @J/ Y!&MzA|`< @8i @9t+Hh:[!@ E.p @(fw]kG @@b @@^$5:2]+:3ٵKiR ,  @eQ+5 @Y١q @< HjqTt9 @ ė{  @S@R:^,MIQkّ*/7Y~U~ @țfFl3O|@뮹 @<  @@J#@F{@IDAT} E$߷[miP`I @@`e.aIOf[;W?}*T]. Y&M}V @K&Q6bw @cH OԘJw!(fFq}X4CA lzzmD @fhNw~NUW]yudΜ9>t6yuezkj[R7* Yԑ@1ä&C  @@%5 0PB$@ <#C&5SR{fepcEذanCn @Hjv9?ryH$ @6A @E@R,#9~]va~nn`!@)J%5i0 @lbsyK Os\DE PIu!l׊uYw ^`ݺuSO=5dO}zplѢE.R}y9d]to?yֳ%3~g^+)^{eO馛H@˅77z @$5K>;3 _򗵀&]|{ף]ҾTR3-iO/%LS+w젃>G"fjZ @?U 8MW`ҥYUm4 4Y~x0b-wm&;c%Kd?ϲo}[ۯL>ق &Ԇ h-%5[J @c_śmYH }/Kw,O׼Lٌ̗3:~W+)/6 .M癵1}W]Lͪ @^ HjRmO4IR暫@v%\]veϛ7/$t{쑝wy֮(5$jo. r{#@ @`P`ݕNo@w֯_Y7 ŋg~Ь?{K^fϞ=׿{ >K5 @昸s&ۦ==| [v-t7 X"{k^ӽwm}oO=To|v| @-|t @@A$5 :p ;xC`twu+Lo~w~g=G^iӦn64Զut>쓭]6; vc4݄ol؛ @vHjC uYf!~e7|sחA-q8S*fxC;f˖-M7JStKJMo{Zb3]o#@`̃SG0 @@'(93fj:={sկsC:ujv4Sއ!wQ ¶v$@ @mfj21aҝ/, (}G*x|sz/x  Ԯ㏷'f~cˮZru]wmy[a+l8 0>߁c8r﴾P!cؤk.s@޿/LdF&ŋڛZ)|#ON/YE]TfR/*5ngUH @ oyœZ; Yoi(5.[-f>/zыtV-{{ܹsG5;c*{Dz.l@qiIyl!@ 1I͎ODJnZ @dR19S4r#Og<@- k-3fdE6u]v~>Hf9cu @Hj:Ã6s1HLKɸ8%>y]v٥zB{kE g-uZ @t5Q8<, @@ڕJe ʾQ,0S3c" Vw)~Z.}o3Y)Yfe&GtzO>dmV7DxTY ΄Ԭ~z@fcn,LH`6X}yѷzϸhK"p]wn;fs[o}[ },@x`w#nt/n8~Zt ׎~o{qԙex]6Kݜ1cF"88cUHӗ( D9>J~y -pJ4O,ǧ_sl,5NOmrz\GH|Ͼn%rl/NFa`{Q^%2J:) @*!0f#Pbe&Qh <@`qنZķzkny/隕/~x㍵F}m3e(rK  @Jj6"SeN4O?T xyk@f͚;r-f7tӰ{!]/.M;pXO01a6YM(X  @tHj֑^c$]|8xD5\2<S2,tzBjeaG}J/8= @Lj66F<7Z-@nA_mjl[{WfΜ93K3S-Y19/?.Ǡ9 @@l ]z35}꒵f%;g'OvF6O~,nᤘӲ`Ak!@`΄{,ps(F9"ʿDqzz X @ "YWrzz];qJLgkYelͫ>Og_|qR󪫮n!8s (Q+|?JZo!@BIF 7jtI| WUVC`}u4% ~ᖝN3xtc~[Zog&Gwy7EZʑTgFY%M`[X @KR4n|31ց/veo}v,%[-֭˾ﴼ9O۱g?on3\})9yn7 A xh]l&P$tz(Bȥ@uX_qq*?ڑx5~=/)axyn3^ْyEX9S/%k̙3v @`h)94bwC @@,{vg>>5H$w1K31/ث{77^{m}oR~C=t@qs0Iyl!@ 1I͎boLDT,n#}e_:~tYfFf'K.{g[6F0Ss  @tH@RCy<$[d|p-4[;1_WW+RKgW\qŨdfm@; 0@|.CXI @[[@!P4t't*3<}ӟ}44{nv-8umce^xath .vy|/̦N:C@ I86 @蠀fqVu|]#o@RBpŵA'ר"|??;쳳t|TwJov/}KUW]5O+_JC9$Kwt 0qɓ':qF5 @@ߘp@a"ͅ tW`1}_nST712eʨy衇jw(Ow)jv!r-tziӲکi6#<٘wuWScW:53ΨŶ>dߨ# <d 0.뮻vfҸ.A' 9>BfjYf&.0k֬lɒ%;_s5>-oyKmXj:z#ڌ d}s} h-w#[oVq|@$5{%߃v&K-f{lvyfl~7dsyөi&i--{G??FχF%/ `%2 0NO 8/a)Ysb/ Hj' ;E'-@Jl/vG>UzUv觟~zv7b8<9=G*_fYW @L: o$5 4txO_+lXמvX fn=i{CuYHwqٚ5kn-;묳K/4{_]^fH֭[}߭O֮yaekBJ Lͻ+a͛y @]gDD٣!e O'?2up5 ֿ{q#w@O~,%ӗNG}t6{>}ҩ_~ytu%#6߼*g쌋A&$IϞvi&T _{9(DʇbݾQnO񘒟{ Ñ9ҭիWG[OF1][ک@cy-RJnr!Swe=jw߽Vdl K?7J_ZZ{^  @ +.wy{N1O5m]ώk=ّ|e$ 歷Z+wuWNNeO 9sd ,: TP`8<赀 @]}0^eMTQ;J}y",2Ol؝Ȳ\ @=)+| @@>S)rN @ eqaݺupsT['@ȏf~Ƣ|35|j\@R(| @Hjf(nč>r1nHD`#9tV @ccBLcAȉd zF\W3ݑ^Mko}[-ܒ|٣>͝;7e]w=;iӦu5,1u[c!GTH({G'ʬ(7D*%Q>(\Mmm&WXz#̯ T! p cxꩧO?=;s 4Sࢋ.tuuUМ5kD?w OL '~n6DV PP/F^etݡoTGc9fF|S#TI %\R CiXޘu<0ȋ@!~Wso*Ї*_~KcU?88Xg?[ISdK3 P"32ٲ!XrY,{^c#{64]L @$4 #ͼ=A ,f$6"yco?߿+ٳgW.K_JRܜ1cF{u;HzTzasSnzj@?t7?ܴuD+"B?|w;X[cI uo,e?XZ$)gۘuYE)[/9E*Gu=+Iqo{eΜ9{6Unz"t ۛޫ  @@!*屾աXP,;l*zjj@F532)q]}@~TOzu'Yw\^7ؘ+LŴG;\ ya4 \]}UƉطjU\S=5E #شi/F u]M'?9\k yc #1MϩRS^ @ os~ʫ6Z}L6GWT_lnst}L@5 ?N?~afG:@~fϞ=ۇZ~RzrL)oӔH US @ @ _;}RX?udi2Z%F|I¬ ["m= sxG虙1jo}VTGhmmmdt @@G);KÓJELcC B/R9c.jV_TSTC1k?OnlZ'@i Tϊ1QS_& E[y[xғҥcU}PݦTnsȽ@oUOU*5miʌN$-ElGѸ=U~YxpZ}Lc3mV[>SVj7ko ܹӕ yD @@Uc>fXNcTYPȤWw:@m[nvR]3gNe޼y?bs'W0|ʕ  @@.6TEX?sfǽV ޶1UaX%gE<^cw:79E/W=*y:_?|swLsetb& 4X `]hQQIuLJWmjbdD@Q3#0V^9f4HRCV gjժfy饗Vq|ϮJOOϮ%Yʫ 1M9*000dYύgU}^=gԾoVܽxq88E)gEoMd'ȘE#ڱcG /lٲex[nݺWm_geŕ7 ׿{Eiwx! N٘m$}W:>j#~Y=v/ɥG14Iȿ z DQ3OlS[x[Zk*wu׮nJRzmqFVcc,P"g,} ,Y%3gyM>r z$yXНwYټysC$˱:ٶm[Oܵ+r{鿊x"k֬o}2!4/okk{c&("b= Tu@lSM͹gX&C _=5?u .AҥK3ўS5H eOEL8W]bz4Wv!| zHA3=H_ yԞY;^ͤɢŴr<,B75V_z|ə31eF!4zC @la;KR%1eF'<\)jjhK/WYpaoN+1"^cӴ[ P/sWz5:v4Sr: <c֔oK*nJ:!q%ŕ׼5ٳgg",Ɣ A@Q8ݩ @@M տ)ŘY@Q3ϣGnl7Z'sIWcʖhLZ`>  @@#7)ŘWfD1PdEG8 @[@Qsl{(=(?eI {Eac{Z'@ ϻޞ2 @|H[lMh NWV>P pI @tJpnGGǝfd7/ PdENNn @&Ym@>1Qsy$ȊonJ0 @ @`6*6m,6R 9"@(f=ƶG;_G[ @Y`KK,$ @-o#G@<0% @pQvkk  @\@Q\Y~^C ?Z @J}tf'@ {eђ @2*Crfͺ Z{R}Z Yfr'8 }?^ @(`fG%1uvv>hx"@'sc  @Ȏfv" ~) #d @ (jf|^Y"ì% 0Y/9ޱ @dK@Q3[㑋hr  @@m_S{ @A@Q37mty6XX!@   @2+١n`벽 @`l5cﶇ @<(ja2c{ܚЄD]tww; @ȅf.){AX7ZDDEs @F@Q37C@c#E&" PSAc# @Ppe+ؘ!"Z )0488xa=6 @ ;E Y'~6[5H @@5s7d 8.yܟ;[Q%p^[l @ @ EhDBF ϩ[[[׏ @yPe$y]#  0BS#6@ @@5s?H e#Q @,b @"(ja3Cּ&¸6 >9  @P,P_ @1Kx?=Nb @@a5 3'5+p_C!xL< @S@QZVֹ  @nyu[[ @ PPE͂lZii_ >J @ (jwlS,E2f,͍K[ @'Y1oZ˗/ fkc:Yޞ w @eP,hƍ/)tK(Ǻ+e @(fyǾ)www>ܔtBe˛ @@58M9&w;(#ա+S @5} 4E 2t(@lZ~i( @5}!4EgїҙN @,f(K$@ @qE-5X`hhcC F P˗]tI @@f ttt<~h {|r# @{ (jmbKۢn`&@DQ;K  @!YŦ <=q(#ENPn @/9 3lЀ5Iپ}{  @O@Qs<&h|C:0R (UV_$E @Z&| Y`ɒ%9sfwW|ċ @ YO;xcʴ?d_ ~^eID! @ (j6X lݺ=񎱏DAmmm @ @@" U5kDg  @ QмiӦM0Q @ lnwz#u~`Ã^^[ @QOWf @ 0RL͑>$w/~aM_Ȱyq/3 @HA@Q3t]-O}0[ @Ǯz{{/(k&@ @`lmcO֯_[\]'%~&.;({ @L{?B f/61b P:AF^ @&&91'G5IkK"{Z,MR7 1pEG-ca  @ (jfh0@{C}R;v,)e&@ @`r`32OE7O} @@1C3y-hޟn$z'@ @ Y@(1[{eL\ @LN@Qsr^n;.Al ~)k @r$03G ׯ %L_(W]$,O @'`7/I#pz{{Z @Q@Q3Vwif^B֯"SI @ P7EͺQj+V/N~Movmm^z"@ @(Y,A֭cWtHB DA_.ͅNTr @4DL͆jQ===ۨKM9.;cSz  @P,ܐ;-[mdbg*;W 踶ʌ @F (j6ZXuXfMqֺ7Ah@|'h @ (j~`Ed؃9IJ"@7nܸLMV @4S _օ ΊM_׆5FuA!fٿ*n#[5H @@5K7J8 DaL6((jo+TV!@ @ 5F: <OD[|S Pq9IDATQ ?'}4ձYM @ PrE͒!q{ɑEG(G./XN!@ @ e= y/5k֨ @`:[[[ϜN%@ @@-35kؖKΟ%or  P,F:o/VJ!@ @ +G]Aw,Xx"ҠF @`*?81}*'; @PܗQ+s   }}}\|OE @dU@Q3##i Da(l>3 N!' @ 'P0H @)М޿H(  {-Q<1 g" @2/!TܷrTpLH`IQмqBG; @hN'yO?}ٳt ȡ@\ra;  @ (jt=9ŋ~]glrg:`,o  @ 7BUXjjQ,?\p"@@>yf>O @.^obՄOr %(h^:N  @ HEFj;sQ|0zU,wd.8 @ '1C9 W @P@Q*?uuGKx(Fo @Pl2#qg6_)lffTB@(h~*q @ xyX,Y3f^KKˑfT* @ @@50 bHU`ٲeό R DȠ@|4Q '$ @J*YҁH(l>5|'#DR xR+H @ (jfnH@6IV %@@8 _PLB!@ @.EM_/^ܹs!B^(x)Po@ @d[ϳ=>kU.][cL  @C@Qs +bŊb* (5mmmӼ @ YL`RXnƥOKяM1] @Y{hY @SpOͩ94s"O&a PF_=4_YL @@ߘ1k nn{m7d XøQм=i @0S~Z*@EL @ (j6ZO&-p)7o޼s2{ 8\ĥ7 =fgޔI @5S@@#供qi;yZ%S}%7nZwwΩ< @hfH ˖-{EqX:N 5|I{{K a @D@Q ) iDsAΈOBAiĠO> 6mwm9#@ @ (jft`E O-z¡zr6 Sb-@r[  @ PBE 4RN{ܹs685KjlkcYgqM @ sE͜ dY3|̙3fryYUlHseR2feu6'@ @} (jC fw/ϫG((b~;.۶m۷V^'@ @@5K6%Kq*p e!&1B X.1cUr  @ @u' God(rΝ-@|m6&"nepm2 @ @`"Qr M(d:7cdI`{s],7Y N, @ El(!?k֬yB;_kfSb\q9ޮ4\A?9P @ @IM 39q?WDkr[@Ûc6ر㺕+W> G @P@Z,YrtgҀHƬ?2UcH MҍQۯ P @ StMQ<(Y:_Ŵ?bڂa濈GGƎ_dv @f(5D@:Cf^rLyD,obJ.e,0O'iWN* @r,:S8S̛7y1qΣ((v}ZX~.{2b݋ @" N Ȫ@ 1 2 2 5 ώ@IDATx eU}DKQED] FV.!Ѫ.&&&4EbkQ6cI*eph CQ$ e^{|;oι{{?saުR @ @ @ @ @ @ @ @ @ @ @ @l&#@ @ G}x> { >5* @LF}dB83bX^ @&#>%G4i  @\`kLF @ +y5w~ @WhwEM|Ji[!@ @]-S&@@y1q5m+ @+>]_ @@>O= jV @hW}xf'@<%uxJi;W @hG}x;KznBS "H?Z/i;W @hG}x;f%@ $ӭQzT @^ e4ɦQgLj  @8+s_sҋm \W90 @kpv3# @wEʨtbi}B @@3Ûq4 t\)ߞÉQ۩_ @ >[hݭKg4.pA̘~5~B @܇h@J&uԧKsU=a& @ ( @`gL۟) @ /s+屻b:  nͅ3+\0 @3%lJ.gXbӸci\ @ 6kjO>5hYqGl@+ @M}ڼ&@ |>bɦiB @܇KoS"=QsLi @<yN:MH \ϻi]$c3^ cwF,o1 @hJ`Ó[DZʽyZKHI[DZy|(E>#W i?] @drcx&1E83"_oXkV ZF'oWs @Qt\]o;7Xx?0`K&\V b?b @hZ 7GxMM h# ֺ 0YGrXo;͗FyC,Zc8u @@voD}6q T4NN(<~{LYRc @@@_ܳ6Z9+J:8?'6V @`4V6Gv%#E @Mt>?޶@ %n:[6^m%VDvnwEcSR  @I }Ѩ?Ưx%@83NA[4ߏEwG9A]׋ @@?ܣ֙VIۻ=h#@F^̘#]ވû:>skIW.L^>Xkk @߇??s sNO%( @`8R[A;zI37%RiOU!@ E^wտob ǻzeE~ O\}c1K㾃?>;y!@ @`}u4/_۝{|%z+Z䯪=rW$@ % s;;;:yYE^ ?/}Oֶ5  @(0W>T^=Y1ɧ5@ckڶ& @GwN_1ⱻ[3+ѡ3M @Sє֭|iZ%@l b9!_E=-{FJ@) @̹Ӝ>!O1?o @s(౻9N- <s_05 @=ɧ], @cߍxQ~G)B @O P*pK #@ @`>$@ @LE@i*%@ @̇|\ggI @T-J @ɧΒ @ 0ɧ[ @ 0Oq% @ @`*OSa( @ @`>$:;K @ @T$nQ @ @|H>uv @ @H>Mݢ @ @|,  @ @S| E  @ @! 4Y @ @" 4v @ @C@i>$@ @LE@i*%@ @̇|\ggI @T-J @ɧΒ @ 0ɧ[ @ 0Oq% @ @`*OSa( @ @`>$:;K @ @T$nQ @ @|H>uv @ @H>Mݢ @ @|,  @ @S| E  @ @! 4Y @ @" 4v @ @C8MgI @fV8K6g={icٽru{%V҃ @tY %~4#T &@ @Oή`d)%x]j|;//s4 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(|*s3 @ @ C@)I @ @2ɧ27 @ @2$2t!@ @(8lQ+!yQSnܻ?#pژi1/8tSk>4# @) Ԧ ̶@J<9}8#T2cQ%"@ .ݭ`s->$4oޜ|zB @$nI3"SE/WJ @3' 4s x~m @J$JԌ!@ @YL: +pUYYP޽saL!c @ кS 0_)t [:;6L>1g? @4-౻EG @ $ DA @ дSӢ#@ @XOK%CVwyuûZb&ݵ+##߹sc>jÆ#y @荀So.@ W %n=)G۫T}=- @N H>url ><:묳f$8뮻ھ}$I'T{ 0S\Ս7tq9 @H>Ev"OW\qEW\sөʭvlٲ7TۥI @@|x/ @ @}|? @ @O8B#@ @]@WP @ @ H>u @ wɧ_A @ @:, #4 @ @@$~O @谀S/ @ @}|? @ @O8B#@ @]@WP @ @ H>u @ wɧ_A @ @:, #4 @ @@$~O @谀S/ @ @}|? @ @O8B#@ @]@WP @ @ H>u @ wɧ_A @ @:, #4 @ @@$~O @谀S/ @ @}|? @ @O8B#@ @]@WP @ @ H>u @ wɧ_A @ @:, #4 @ @@$~O @谀S/ @ @}|? @ @O8B#@ @]@WP @ @ H>u @ wɧ_A @ @:, #4 @ @@$~O @谀S/ @ @}|? @ @O8B#@ @]@WP @ @ H>u @ wɧ_A @ @:, #4 @ @@$~O @谀S/ @ @}|? @ @O8B#@ @]@WP @ @ H>u @ wɧ_A @ @:, #4 @ @@$~O @谀S/ @ @}|? @ @]O>=..  @ 'kQ_6k'| @`]L>m _gQozEMQ @8 >;QQO @u >50+f#@ @`?݇_IcM|J՝usԓ* @/{yQO @|JJQ9Q @HbQ_ h]`ɧX2A!@ 0M 0^;B @-յ%k^X@ɧXK/-Xݚ/ @gx sJ<]Z-䱺MCR;tq _ډQʖ9O5=f @e  @`Jzַ,L@>w#3{S,_BS8󦰪%  @`7L1K @`>;MOi^ύR? @U~'% @c{2>Oߎ @ds2f=v7|7ƎT%Q/KQv\,p{ۋ5 _;~xW~+v_{I'Tz+-q3Ψ^W`/̓7d5/FQv_  !F,_v(^D-䯊~}ĨmbO5y (I> 'Ce-{O{nuW,"@"0lY_usԕ;,~LEs(cwI5A!@ ТZ554+S=70PoaWԇ* @'0x,XEQ?գ" @@7L> hX޹㘨A @"0x,U1^VV2)X@ɧÏ7z,.M @y5ojF(h;T+=ڨ򮋶B @X^f$@5L24kX?鱼-Q=7J @jVXE`ɧzH鱼+_{nFX^ ( @ZX^&@N>գ16^cyum @ x,]_ @`౼El)u~Ի; @̒౼I&ˣ7K'\ @`:]L>%i @ Ю౼vW1;̅@ p'I @'ɧyΕ @ 0aɧ [nٳԢS C @`VSﶮS˧ozE_rھ}{u7Ww_uW'|ruꩧVC9db( @#X'E=9c_ټ9W+Q'Y4Imk @`[clUuӦ :kaE=&]|7 x#V9qpO$<19KZz _ @LNE}8{?%Ό:"I(X-](xk_[sti۰aÊ wYs9׾S$@{"7F;<4qƦP͘sM1DCӟtu5,{衇ݾQuM7U/{˖'?._δSԎY  @:%KEX.N'Qv*PMI||Kݝ~Kmܸqa۶m< /\'?}5CL]j n/ {Nɦ> 5_z'Q*bjK6c^|@҅ {՗/S3/ z^|K}#n!&5E Q##b&7նӿ5%W_0Z[okwV Z4.}۽Bm.ұklڴzK_t[j7S"@ Hz?vZɦ,kɧmfhg9SwQSiTyf㨃 ߨ @`78êON:<9sNˎ()>|$t@k1͵Q!}'TELMq&~"k; S/ ?uQӫBo-g|m^z о3K@3)nM%R|Gv-+}z)Az4I>h\ࡇZZjk 7fs7j>9ިǏoLD}D-B@Z}ǍY덚kO}%s7j>wj_ɧę2h!c򣨿iC!@@7.|LRb_^|Š:TYSLŌN>\ѨbߓG췋 <՟sNJi$F,k.>|u#=j˜\kkm\u:t#g{G{x?u/_MIznNSO<򑏬:/9(5c @ S}x&n.p[mxbm{T|J?TvϨNw[mjj6|za}Y--nhVm[/X1G>rߣ38cdCLMjjkL]Epv}3=5j;Pk7Ss5|:"p|Sb<6^z^mM4.g=:c}V _K^{キ{}{KҘ/4">F Р_\ߩ^98P{=2鱄T[ۿ<ĴBЙdSA[>6 wM.uŠz1=~e-Lo]+x[g?م 6,;}G'o~s>9;f=It jޗokT(>|s"ߍSߗ]qz9;6ү ]WZ}rvzL9k͒^?l_~l0mw){?+bܴi矿׽n^q,ӎ;F[mǴ7q\%p>f P 1Znl_]Q?;t,p:e2iQooE{'c1{3+tX`k6wKɧضmBR|bK32?TicNɧx**t]9C,DUJ>g9Qv7Ҁ HUvQwh{%@@#rJ~.>T=8N>OU=r!+v뷢ӘYi)M oԌ4+pSL~.jT %ҧzԴ=<8s\n#7g9'ܕ/+щ. l.0>ɜthܹw+W'pWҗr-iO{ZUÉqڵk)u/?k1wi-[TW^ye|eqǭ|?ر:<} @H_,~b#MԯGN,Ů;H`Gv^Yi >ٮMv9 @`OxTK?үUɜi̬T` @L gjIIqw6xJZL:Y]'OJPhZꫯ7կ~uŘN  @.Cx}MHc(Z|Z̥_^/UsN7]0 @%ߊI?`ԑbLFK/| 3< 686.4-  @̬<ꇣ>ԑbLh{  Bk]݅.1 @̔:x6]L!ynB @ @aɧAMG @ , lE @ аSà#@ @X|Z"@ @hX@aP @ @, H>-[h @ @4, 0 @ @$- @ @|jt @ @OZ @ @ H>5 j: @ @eɧe - @ @$5 @ @Ӳ @ @@O  @ @`Y@iB @ @aɧAMG @ , lE @ аSà#@ @SH`IDATX|Z"@ @hX@aP @ @, H>-[h @ @4, 0 @ @$- @ @8LG_}e˖ #G  @|ϵ) xa{cTM WMe @|j, }{[? FRijdB @ КSk&&@` aÑձǾe @Hv @ @I H>MZz @ @9|T  @ @O;6Y: B @@$u=DCwRU @ @@؝ @ @@kOњ x Β,]MB +ɧ^].MF0/G  @&p@k3Y'9~ί7ޟ @ CIENDB`././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.8273642 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/mirror/0000755000077000000000000000000015060352601024051 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/mirror/mirror.png0000644000077000000000000005451014777236751026123 0ustar00rosbornPNG  IHDR7U /|sRGBeXIfMM*V^(if7U9sX pHYsgR iTXtXML:com.adobe.xmp 1 2 2 5 ώ@IDATx eU}yA Ԏ Q1hp|du&jj4Z5Ѥ08򹪶|,|t|@ƪU|Ԑh8@{=ܳNw @ @ @ @ @ @ @ @ @ @ @ @ @ @G$@ @`'kl @`.tj#@ @:f!@f\̸;W @u܇q6 ` PB` c @ l\x}J p7#Ȯh雛5 @ 0Y5: h L Z^{ @p>Y_ @s"pE\g樥6 @&+>|F'@@!qwD5Om @LF}d\Jҫ00:`> @ 0q5* 0G)~:>zK%@ 0150 0OOCgk%@ PI1J a+XJ#@@Y,1%>1 @ @#pdmCt @28T|ss&'@s=j y:F @@eB̹qC?γ @ PF}xG @s,;Cy| @p:? 4#fB!̩q,y| @p:?  @{B0-Ŏ"&@ @~}]!@d g/bxg#@ @`eW&<(9ظ\iN @ظ«YiN @]#] >KR @yMyl~H u -Km @ r6 @`P873s< @ '>< @ <$m9!bi @p<'gXSjK0.U^JgSt_*ּ @+Z&ci44M1i)c睶y @݇/e}s @r^'o2Jq,:^Ho흳7<a @+Hˣ{֒iֶ'GA7G؟6 @`d|MNkEy9 @@_ݳ|M㶴'_E]bZOy @Cb G7%_ӸiilOIײ~ ӏ= @&)0f>F7̼3.m 8`Bq>yX޿/o @}.d?lh/x='u  @V%F:4ӥ.BzC-O @Z~>r|s=+ @1HfcRiilIo6.qvwy!@ PK Q'֖9ڿUy LKiMl^̑SZ]79fDZ? _h_+=h[x^o @@ Y| eӱ @"𮘵t-k3Z =ӱF @EwEQ{k:(PmXu?(4I]c @`~7Fp/5aF7W @V'pDtю_&}YnZx\ 7j],&*W/{$a @*IhYxM?^̝ܜ%w@hfH{ @\^wo7ݫ/3M 7Z @`M (PzW5{o @ ?B:0~`lfNc3.S|lvxK @`J?Ҽ%0Qܜ(  0w]{ @N-=5  @@)/ o @n'5 V Wx/s+  @ @ҫ03)p_h=hϱN @psb&@ `W3ǁ @ @K/i0̽!hߟ{  @ 0qܜ8  07ĕ}1 n2DJ4 @ps& @ \WOf\ @4/H @ @ 7T#@ @ @yfK@ @ @C* @ @ мp%R  @ @C! @ @h^@) @ @!搊c @ @4/ l~H @ @psH1 @ @n6D $@ @ @`H@9 @ @ 7_" @ @ 0$ Rq @ @/  @ @n8F @ @@H @ @ 7T#@ @ @yfK@ @ @C* @ @ мp%R  @ @C! @ @h^@) @ @!搊c @ @4/ l~H @ @psH1 @ @n6D $@ @ @`H@9 @ @ 7_" @ @ 0$ Rq @ @/  @ @n8F @ @@H @ @ 7T#@ @ @yfK@ @ @C* @ @ мp%R  @ @C! @ @h^@) @ @!搊c @ @4/ l~H @ @psH1 @ @n6D $@ @ @`H@9 @ @ 7_" @ @ 0$ Rq @ @/  @ @n8F @ @@H @ @ 7T#@ @ @yfK@ @ @C* @ @ мp%R  @ @C! @ @h^@) @ @!搊c @ @4/ l~H @ @psH1 @ @n6D $@ @ @`H@9 @ @ 7_" @ @ 0$ Rq @ @/  @ @n8F @ @@H @ @ 7T#@ @ @yP^R1h&@`Kh @| 7gS\WJ`Wvy#@ 0{[Ůh76׭[׭_ؗ85mرnS|݆ v/}ꫯNx2bˡ @9n٢`sӦMsv.عs`Qޮ5T l޼ynŻb @ B , @ @nA @ @@A  @ @ 7 @ @ @f @ @fz @ @ ЀpEP @ @|3= @ @h@@"( @ @|f @ @4 l`@ @ @@p3L @ @n6J @ @ @ _@o @ @ 7X% @ @ / 7Ӄ @ @ , @ @nA @ @@A  @ @ 7 @ @ @f @ @fz @ @ ЀpEP @ @|3= @ @h@@"( @ @|f @ @4 l`@ @ @@p3L @ @n6J @ @ @ _@o @ @ 7X% @ @ / 7Ӄ @ @ , @ @nA @ @@A  @ @ 7 @ @ @f @ @fz @ @ ЀpEP @ @|3= @ @h@@"( @ @|f @ @4 l`@ @ @@p3L @ @n6J @ @ @ _@o @ @ 7X% @ @ / 7Ӄ @ @ , @ @nA @ @@A  @ @ 7 @ @ @f @ @fz @ @ ЀpEP @ @|3= @ @h@@"( @ @|f @ @4 l`@ @ @@p3L @ @n6J @ @ @ _@o @ @ 7X% @ @ / 7Ӄ @ @ , @ @nA @ @@A  @ @ 7 @ @ @f @ @fz @ @ ЀpEP @ @|3= @ @h@@"( @ @|f @ @4 l`@ @ @@p3L @ @n6J @ @ @ _@o @ @ 7X% @ @ / 7Ӄ @ @ , @ @nA @ @@A  @ @ 7 @ @ @f @ @fz @ @ ЀpEP @ @|3= @ @h@@"( @ @|f @ @4 l`@ @ @@p3L @ @n6J @ @ @ _@o @ @ 7X% @ @ / 7Ӄ @ @ , @ @nA @ @@A  @ @ 7 @ @ @f @ @fz @ @ ЀpEP @ @|3= @ @h@@"( @ @|f @ @4 l`@ @ @@p3L @ @n6J @ @ @ _@o @ @ 7X% @ @ / 7Ӄ @ @ , @ @nA @ @@A  @ @ 7 @ @ @f @ @fz @ @ ЀpEP @ @|3= @ @h@@"( @ @|f @ @4 l`@ @ @@p3L @ @n6J @ @ @ _@o @ @ 7X% @ @ / 7Ӄ @ @ , @ @nA @ @@A  @ @ 7 @ @ @f @ @fz @ @ ЀpEP @ @|3= @ @h@@"( @ @|f @ @4 l`@ @ @@p3L @ @n6J @ @ @ _@o @ @ 7X% @ @ / 7Ӄ @ @ , @ @nA @ @@A  @ @ 7 @ @ @f @ @fz @ @ ЀpEP @ @|3= @ @h@@"( @ @|f @ @4 l`@ @ @@p3L @ @n6J @ @ @ _@o @ @ 7X% @ @ / 7Ӄ @ @ , @ @nA @ @@A  @ @ 7 @ @ @f @ @fz @ @ ЀpEP @ @|3= @ @h@@"( @ @|f @ @4 l`@ @ @@p3L @ @n6J @ @ @ _@o @ @ 7X% @ @ / 7Ӄ @ @ , @ @nA @ @@A  @ @ 7 @ @ @f @ @fz @ @ ЀpEP @ @|3= @ @h@@"( @ @|f @ @4 l`@ @ @@p3L @ @n6J @ @ @ _@o @ @ 7X% @ @ / 7Ӄ @ @ , @ @nA @ @@A  @ @ 7 @ @ @f @ @fz @ @ ЀpEP @ @|3= @ @h@@"( @ @|f @ @4 l`@ @ @@p3L @ @n6J @ @ @ _@o @ @ 7X% @ @ / 7Ӄ @ @ , @ @nA @ @@A  @ @ 7 @ @ @f @ @fz @ @ ЀpEP @ @wу @)p\hG/| P_`"S-!KB @Hf\xD\aj6n68J#@ @` urؚF@`M l۶۱cݮO6lp Іۻn @ @`RiӦBF` ܹs0L(o|6o޼'f]! @ @n䲺( @ @/z+k @@3w"_T @@aQoEoѮvQ @1ѶF!ږh @ J/h6+0 @%pj\N0ډuiuimvz4 @Hmc'D @֤43mhE @ 0YY6F{N# @kZf;_Fy  @TydS @t鬫Y  @[c̍$% %@Χ'@ 7qM_G3 @̯w]9{Ն_;_7 @yg @ $=v1F7<ύf[u۶mΝ;W>LL_60̄4;!wLM"܇O%>|YLN"Ь@N;-=v~h5kN6sرKF fcB)5*܇PwSؽ{f5%K;u> x㍅G4ER"-pWv7otuְTpeqƟGK @`Jwyf6-LI1hMi~ @@tM֭?6Z_(CWPm̼ge_dH}>oOvnўF6f$@ C`4eM77S-6̝駟ޝs9sw.]ae/va @`ߋ)~=- F`p?U&ߍh/hEIO2㧿O>[n݌_#=я~t'm 06F;+hωvDIo3&'1>HEk?0B"9hZCDK<,GV.pQt}Ć M6|=  @%~9j/V3Uof#@4)p*JhgD$h6 @&'0zl1C)ZzF+Ն}+Mmv{4 @=).Q@ @/P2i[8hч^  @ b_hc"3 Ј$?c}! @ xl  @&n/9=h{{l/d @@y75" Ј@pstɣ֟c믎W @d\JLQ`frcoE{{4 @<>A\C @nxh['@ 0YO @+zbt+L? @%0zlqˢet @`J-}cc  @bt @*Zz,}; @ @$ ܜv @ @fH@9CRXwܱ+JЦ!@@9?&Jss;~)o|G?رk]vuzЃSN9[n]wyu~xU.5U6 @tΈi/vzGDWk}#Fh?VsSSMms\ .6mNU*!0a[oK/G`N8{k_ۭ_~GTP,yn֭D{1=hIQ̛N}3>mқ&-l|S`P)  PVo~sn믿{_]sMGnj  @x[Tsƪ;%2#ǎO⭚&jLS̔1= |K_>G׽'>m۶˺:kw7t~cwTZx @ <-jza[GDG>m;[4:0W5MՐZ8Z>5%G={wQ{fX}w 7C9۲eKaÆ.x`wqug}vw駟ޝtIQDX J`j_򗻯i/DK: @]@8qhh鷢M=8ڣѮtNMeMF lbA@ioy8YzVwimr=н}sۻ_rGM%5E ШqQ{3{?ڽ#v~?ڭ~]54Vn>){uK\sSl(.ts>>G'i$@ ۥwHd? >`USIMchL`/24R{}`mF{F#@jCq))_|{#oKѼҢ#@\ wxx]/79Koj*-j< 6Lq^IAo7G;lOhFLz{~csafЫbWq\Mӕ@%toŦ҅/}5{oncs1{۹=G?y |7jZ1 m|BtFOloZF >)W֐@p3]}wo'DKmߎQ9:~_g>;޽{KQS Ec @sS=~NoUohs_ɱ 7~NP{~vhiYߊFI z]g?KシOմ<'g @@l2@1x.1~C,y$r+P?ۂup8_I[v8SVex!_jGM$CP"@`*f림wplxߗ;qoմ <] .? 4|uwcǼ%@d.p~9>Xc1o~#@ërEߒ\g7մb9L`&n0yx?o옷Gw_){plgZ4c,VMKV+>| PB R;yucmL5QGm 7sG;rrN8 ;^wkfe7jZ  r+ӓ7#z펟sb'⸚V+Jo ^߻ E[/tB [n~ߡa{=%i%j @2܇/iL\ )8~hnzI|$>7VcoS|o䮚Jj@cwG; =. <?^zݍ7#-[on>IOos7w7tӞsy)  PB}x Ec PR1|Mg}{=.;;5x8L ^_$߼0hZhD;&x3w[o{ӛԥGەW^]vYŌ_nGqDwYg}}s=iOӞԧv_rvf  @@E B@awKhqvvށ]wb'Tj D[65D3!ppxQ8{YcKh6LDE/zQO}/|K!gs1ݎ;j7mw\ow |:o5-0p^(h- 5Z--7,Jyi%FX 7WMQW>?^ӏ @ۚ|+n}Rz|ߺ|',1bci1  @ S}x& *-}NZ9f /KR4I]c蟾b>^;?{5ov{b߿]^Nv{#̓/^tpइ~VH}t"@Wbr;==oGK\켱rM yÕ5^ .K̫@Bq݉'إ`sO~3CQGUqj*bkD`֭[So5R2  @4яwѾm>;ץn鯰 6ӀVJl!@y+Lm%[}RfojJd#0w},}\0)ϣ6bMM( @`^ F.ŚQf$@` lٲ_w^X50 @A\cOFFŚQKonF֠cn3Ci Z E @̒q1h5ra-2n77#kPo|csUXSsH "@X4x- Xzg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @A G @ @@fg @ @ PX@Yp @ @nq6  @ @.<ؾ}{yƫTX @pszgޕ&ړ̸;; @4' lnI&V% #= LS ;; @?)QIENDB`././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.8277397 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/moderator/0000755000077000000000000000000015060352601024533 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/moderator/moderator.png0000644000077000000000000005426714777236751027300 0ustar00rosbornPNG  IHDR7U /|sRGBeXIfMM*V^(if7U9sX pHYsgR iTXtXML:com.adobe.xmp 1 2 2 5 ώ@IDATx gg]/e7$ &@8(Sj; `[Z[J-jmdhPDƱAGp0M &!/l$˾,ܻ}'c= @ 'i^ @{hX̘ہ(p3Nm @OlL`m: @3:}ٕu:o#@ @`~ge @`A>~j?Nm @OlL,0s}zF @@~MHҋr+ Y쉓kJG @سkFuo @H?d5Jϥ0?fG P^xys= @ |Ķ1OO @'^< @xodf^F @@>,D,1Qdt]F @g7*|[`,cާst @܋n @`>?٧52} @܋ _^^ug#@ @`7n&<^ݒ " s6؝j @=F5hB @b ,JS`#@ @S 02^l$6 @ o|183f?c @G>kW gF>O @X{[dOfJ63qSIS;V؇?~!9{ߎK @h^NjgwExyk iS&@ 0œ QT @b <%ޛ\یp|߿ <8`&@.ʽxXz.A @`!zn@ֺ&YMq?1zk\m @h^(iQl @ l28݌G?iA 7ا7kq?mKIOy @h^8>6 @@D+y~6c;7:}0J?+[:gG @@Q{OOO @- o6u٬=q?Xįf L @ -cu4zB/@M6h+\8w 痟JX(=:|*9QGy|/D @()x!c@!v @Eot~ 'c58?S1 @,u1^vOkvĠ>q|i5&%oԲ @Y1h{ǿ>8vH @l UPXjH_o^X8ŰpKn@Jit/ @ 0 HZ{z=Y;#Pp0LVEy`/^;$@ @`6GPέtjJ'#0uO}wP< K @(M[&s0N38i! @ %HFOn@9O^;h蝃c @ @`.͹j 'kK/p&L @<^\hBťQ*s(+qN @ps'@@)fwO;E @ x,=;  c毎 +` @ PT'7r3(F?J=ǣ @ @@ff @9}Ss2! @'\K @ @@/ %  @ @psRe @ @^ž @ @I 7'\K @ @@/ %  @ @psRe @ @^ž @ @I 7'\K @ @@/ %  @ @psRe @ @^ž @ @I 7'\K @ @@/ %  @ @psRe @ @^ž @ @I 7'\K @ @@/ %  @ @psRe @ @^ž @ @I 7'\K @ @@/ %  @ @psRe @ @^ž @ @I 7'\K @ @@/ %  @ @psRe @ @^ž @ @I 7'\K @ @@/ %  @ @psRe @ @^ž @ @I 7'\K @ @@/ %  @ @psRe @ @^ž @ @I 7'\K @ @@/ %  @ @psRe @ @^ž @ @I 7'\K @ @@/ %  @ @psRe @ @^ž @ @I 7'\K @ @@/ %  @ @psRe @ @^ž @ @I 7'\K @ @@/ %  @ @psRe @ @^ž @ @I 7'\K @ @@/ %  @ @psRe @ @^ž @ @I 7'\K @ @@/ %  @ @psRe @ @^ž @ @I 7'\K @ @@/ %  @ @psRe @ @^ž @ @I 7'\K @ @@/ %  @ @psRe @ @΋ٽ.ʮgir-p*O^= C` (w1 @ 8Xli1j,f~!! @mj9]՝}Wy6Q஻>8p#FcSs}#;A@]C#X @X0-x 6wt-NH;V 7wzo'x{^Շ7y3&@ P_(T" @ @ @ @ @f` @ @n7S @ @ ,! @ @ 0^@9L  @ @*nV@ @ @xx35 @ @@@Y" @ @ @ @ @f` @ @n7S @ @ ,! @ @ 0^@9L  @ @*nV@ @ @xx35 @ @@@Y" @ @ @ @ @f` @ @n7S @ @ ,! @ @ 0^@9L  @ @*nV@ @ @xx35 @ @@@Y" @ @ @ @ @f` @ @n7S @ @ ,! @ @ 0^@9L  @ @*nV@ @ @xx35 @ @@@Y" @ @ @ @ @f` @ @n7S @ @ ,! @ @ 0^@9L  @ @*nV@ @ @xx35 @ @@@Y" @ @ @ @ @f` @ @n7S @ @ ,! @ @ 0^@9L  @ @*nV@ @ @xx35 @ @@@Y" @ @ @ @ @f` @ @n7S @ @ ,! @ @ 0^@9L  @ @*nV@ @ @xx35 @ @@@Y" @ @ @ @ @f` @ @n7S @ @ ,! @ @ 0^@9L  @ @*nV@ @ @xx35 @ @@@Y" @ @ @ @ @f` @ @n7S @ @ ,! @ @ 0^@9L  @ @*nV@ @ @xx35 @ @@@Y" @ @ @ @ @f` @ @n7S @ @ ,! @ @ 0^@9L  @ @*nV@ @ @xx35 @ @@@Y" @ @ @ @ @f` @ @n7S @ @ ,! @ @ 0^@9L  @ @*nV@ @ @xx35 @ @@@Y" @ @ @ @ @f` @ @n7S @ @ ,! @ @ 0^@9L  @ @*nV@ @ @xx35 @ @@@Y" @ @ @ @ @f` @ @n7S @ @ ,! @ @ 0^@9L  @ @*nV@ @ @xx35 @ @@@Y" @ @ @ @ @f` @ @n7S @ @ ,! @ @ 0^@9L  @ @*nV@ @ @xx35 @ @@@Y" @ @ @ @ @f` @ @n7S @ @ ,! @ @ 0^@9L  @ @*nV@ @ @xx35 @ @@@Y" @ @ @ @ @f` @ @n7S @ @ ,! @ @ 0^@9L  @ @*nV@ @ @xx35 @ @@@Y" @ @ @ @ @f` @ @n7S @ @ ,! @ @ 0^@9L  @ @*nV@ @ @xx35 @ @@@Y" @ @ @ @ @f` @ @n7S @ @ ,! @ @ 0^@9L  @ @*nV@ @ @x㫨A @8/y]]%lt_{N c77! @6R6fVBಘe*6*nV8F @}bs׮gugIO ,p]Sܱݹ @`ۿ4]_# @ @alֆ&.p+v=ӿ_[oW`ޫp ]g3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ дp59 @ @ 7][3#@ @ д@)!(?  @pMu h @1/GBߍrE @h'|*ʇ< PJFwEiQl @_eQDy^M @`2n_eOE̱D6 @ !tԞ(eg @`(DyEs @@zQ^% @(nz|TL @`;2 ~y;_: @@. P|tk 0|̘PNیgTDdO-,э> @.׵FC ޽W-M@]|O+~;ǯt@_O @ <6zol(tNǞ|?ؿZW1p$ʞ(/ڵ!sSѬ6  @^bh/ջFFFNLӋ3]3%09ikNX ޷T6;7''k!ei%3GS @i ^T~07rEȺ+Qsh' 7/~am$24^cS]9 8|xw}g<{_ߝrJْXuK%=Q^Q潥j{DH`gQe(D`氉NjTSb۸Qs}q{w: @LP Q~"(籥8G$@:CCcm\QzT%@ @`mqɇ*JD%= @ %0K9[zL@5]  @ ] =~mEyr7EL @`!rCE ˢ?ʡ(6 @'hQFyW @ #ݼ1ʓ oDz  @ lFkyl'@ PNhtu}=Qc믎Qy @`Rn<>pL @@zl(Ϗ[oQ>F@-kc2|1 @sHD'EyAߊb#@T-WqewxaLP& @@eo(sƹ;^0ӖKc6 ld6y8'@@>x nvFwvMwW\qw=_=zƔ[T{ @ |KՃqݿ1O Q~7J}U3ʶ4TMA`q0?c{Yg=;th#>{l[==Eݚ;-[vz~G[p~u~!Yݎ_;$c F l=|マ?ҧNl @@]_x(<hۢN'F(i{\]z1hӘI-'@`.{o_e÷r֭㮻81 @@Ÿ=[zaިD81f 7q}T/4"p=x ^j?x<߿?y`L95Ep/V ==|Jx}_<8yhL95E23E_rɠq?_r҉ ]mۮnˎ^3q{C>ʷS>K- @@^jx0q|JqW,qaM׹vƔKR;*哛2^%}F5_Fx>LI}GYE6|E }fc߱ٿ^ig0'agg;iLYMǾν?(: ^t/?ΰ 4,&P,fLKY-s?_7xq|CdHN9U˯9xWvoF#@U܋4*p;ǫ..1̀*f 7Mr{w_;xs8rćʷo?g>_s{׬ i]L."@qy Om^Gw˯9>Qy:\F`94D-q(S8C="pnٲ /ȑ741:&^|5  Sva=?lsy+aȹa[ tsF WyO"J/ێ8(/E(6[`˖?=|ut^Gk\bLky6*^|r 0Pu`y.:XcZ+/W8oH[/ph-l`xx˖?55 qSǦJ:cZBTrg2-;%*u{|ps1u5N @$'nܿ2yTǟ 0cOY6ҋ˗sؾ?vC[{c6iHU  @`58O@I}.veo /{k/mӆU$P@pbs==aN @`.v⯜X[1_siO>.cNA8!^#6WA W;\~gVp4jndL.qVfnЀClT`N>|o;iSpsӻSN^7i#j @:܋e]3RpJp32;Vhs7C- 7_o_{nCMଳxX۷ߞ~vݝwou7?y`L95E l,w/{=|W:8yhL95E291wEJ_\Kq(vHݩ^t[nnjor˛O|y}kw5w,/??`4õ ExF Q/[x/^{c?/cUx}tګomL;ػ޷\ ͈dx\uQΉQwG-.Ԋۮ8;/q1K #0c(  #p꩏L0ncoal[xY5 @@1T6NۭQrƔd#p 1 2 2 5 ώ@IDATx g},61qPG, )qccR(qQ4$4=iI{^1#.! pl}R0F$4`%ز%。,,ݻ޻3;{g~9ofwvL"@ @ @ @ @ @ @ @ @ @ @ @ @ @5 \% @X ދ]2G @`hˆ" @e x/^ @ZΈFN @^|rFj˲ Rfc3ӫD @fc('m$ @BǟF[xǠ uM @ 'xCXc )X"@ @zū76 0AX czM @ x/^ @ <9hLD @@uދWg m 0/3tK @T'xuz&@j3iN9 @N{lLLX`S ,{M% @^|S=X-|K'@`jfd]&@ @` %wNީ P@"$c\Co  @4L{m @ <':^S= @/RO @|(\s-Փ @(O{,D,plPN0qT/՗ @_{ @0uKc-K% @^||C= @S$1>{S4wS!@ _ɻg @!78qj' @ P\{vZXVH^Y  @ }O]]-GE+S;$  @@ iBLZ cMj/ @ 0⣛iA`hJE&0;fOsx  @X1g>n1ל 86E|:kj @^{$PH`MV @@QDã6^hڧ~x~6h t4DGo:]?CQ @@Mx/<a>mT'@\1"bm+]w?ʏ0sSPe @U4xr|a_VO @>3ba S/WG:75&se2 @@My/`n?>LEuH* f`P_]obb$՝ 2 @*^G _ő% @!b_ُ[N~Hzg.Qi @U s_wӿIw4NҜ @if_V9[Gz\ p:ް$ޖ3蓏Kt4 @^|9g=Dy&D4H;o]L"}8E @j&gvZL.y(ӯs @86P o꿎S1h~-O?]O_>C @U 4x[z=r|JdhtnUJ/I3;뽼C @h{_"w{G\J4KೱM]5}#ʫ&^>( @@ߋw,/ 5W% @gĚ7i: 1ȝum^OX8 @$^wu$ޟ;Ꚙq  @Z-όV.'k @b}G ˢ΋Ի&fҏ¤GHǠ7- 7^8W"?.O;D @`M~/s>I w3"g  b+bO_nIv}U|J9 @ZX}l5ttL ;sn<5 _& @ϕ  @O =9 ^*Z N7;;p̭(_;V$@ @`I  @"le @ @S@N}c @ @h@cC62 @ @) X  @ @4D@!i @ @hS @ @" ؐ  @ @u 4֩ol @ @ hlFZ @ @:76 @ @46d#- @ @@u @ @@CA @ @N:M @ @! H @ @ P@c&@ @ Ɔle @ @S@N}c @ @h@cC62 @ @) X  @ @4D@!i @ @hS @ @" ؐ  @ @u 4֩ol @ @ hlFZ @ @:76 @ @46d#- @ @@u @ @@CA @ @N:M @ @! H @ @ P@c&@ @ Ɔle @ @S@N}c @ @h@cC62 @ @) X  @ @4D@!i @ @hS @ @" ؐ  @ @u 4֩ol @ @ hlFZ @ @:76 @ @46d#- @ @@u @ @@CA @ @N:M @ @! H @ @ P@c&@ @ Ɔle @ @S@N}c @ @h@cC62 @ @) X  @ @4D@!i @ @hS @ @" ؐ  @ @u 4֩ol @ @ hlFZ @ @:76 @ @46d#- @ @@u @ @@CA @ @N:M @ @! H @ @ P@c&@ @ Ɔle @ @S@N}c @ @h@cC62 @ @) X  @ @4D@!i @ @hS @ @" ؐ  @ @u 4֩ol @ @ hlFZ @ @:76 @ @46d#- @ @@u @ @@CA @ @N:M @ @! H @ @ P@c&@ @ Ɔle @ @S@N}c @ @h@cC62 @ @) X  @ @4D@!i @ @hS @ @" ؐ  @ @u 4֩ol @ @ hlFZ @ @:76 @ @46d#- @ @@u @ @@CA @ @N:M @ @! H @ @ P@c&@ @ 5 YeWX"9G~LՑũ3#yᗝQK_5''࿝ѭD"'X(NjD @@_cωϊGoEMgŸ)K!࿝awtȟ_, @ lb pL%/|^ȝ4wϜtIueGydjo_wܹؑ3;SM6/),}l94mذ!;,qCU&保<=#پ}{f{ogϞiC͑F @X+tZ2:M_|BZ駟yyƍ3k׮M!n:hLA-[ BI @L@co^Mj;pi3vn|wgsssG)% @V@ ۰L7}k"5qi'xbvfx3fD+L a3Θ^xa-ܒm۶-.o{% @V@ ٨Mi#ǡ?FSqjL$4E y{^y`u]N`zG_ȷF @X+`Z4ş^ŹLgE+tOg7xcsN<O"K @L@oPK~͑y.c=%˷LHKStꪫn8~$橑'\d @)X52_NTIƙ>k^L=R {@{Bҽ"% @T'tcZ2d)YfxOOdI Z*{ы^mذ!}-Q/rm]#@ @hݨʕׯ^ 2_&^ޑ>( @ 0eS!-[b['_fzjn 0@G{EgDƷ^] @&# 8g*~]Tz\ZPG p@W{•tI @)hhT"NƖe @t@eH @L@lDK:yy>/|aKm P@w{H 鞒- @S 8Т)6#<8\ w^ @&! 8 v?ۭa P@s~ @R@zV 6nX& @`=&}OȾc0 @*hU OJY3k׮B*HtY|S@:%@ @`Yey\SN  @{gڮ @ P@c?~αW P@^JuJ @`@`#5 G׭[W-  @{n  @*PgG1pGv @Jr{O% @eqqLթUg6 0@ w 2 @UK @ @mhlێ[/ @ @ +@% @ @ 4mǭ @ @@ @ @@۶K @ @ PuI @ @mmq%@ @ P@c$@ @ 6ƶ @ @@@T] @ @h@cvz  @ @T X.  @ @M@m;n @ @*hU @ @& ض^ @ @4VK @ @mhlێ[/ @ @ +@% @ @ 4mǭ @ @@ @ @@۶K @ @ PuI @ @mmq%@ @ P@c$@ @ 6ƶ @ @@@T] @ @h@cvz  @ @T X.  @ @M@m;n @ @*hU @ @& ض^ @ @4VK @ @mhlێ[/ @ @ +@% @ @ 4mǭ @ @@ @ @@۶K @ @ PuI @ @mmq%@ @ P@c$@ @ 6ƶ @ @@@T] @ @h@cvz  @ @T X.  @ @M@m;n @ @*hU @ @& ض^ @ @4VK @ @mhlێ[/ @ @ +@% @ @ 4mǭ @ @@ @ @@۶K @ @ PuI @ @mmq%@ @ P@c$@ @ 6ƶ @ @@@T] @ @h@cvz  @ @T X.  @ @M@m;n @ @*hU @ @& ض^ @ @4VK @ @mhlێ[/ @ @ +@% @ @ 4mǭ @ @@ @ @@۶K @ @ PuI @ @mmq%@ @ P %TرcGu95 HɞԸ K k׮WyIL`=k u @c ̌݃,-p\ZeW @@=^uH4YX+,87S,!K8]^^|)d6m*C'>s̞XE۷gw> 6dgua睘v&]dE;׆ @7ς -[#)hO&F>@{hܸq~Vv-ES? @&`FR @ @>}P"@ @ @`4Ѽ&@ @ @@c @ @M@q4/  @ @# ) @ @FhKm @ @4Aq @ @GR @ @>}P"@ @ @`4Ѽ&@ @ @@c @ @M@q4/  @ @# ) @ @FhKm @ @4Aq @ @GR @ @>}P"@ @ @`4Ѽ&@ @ @@c @ @M@q4/  @ @# ) @ @FhKm @ @4Aq @ @GR @ @>}P"@ @ @`4Ѽ&@ @ @@c @ @M@q4/  @ @# ) @ @FhKm @ @4Aq @ @GR @ @>}P"@ @ @`4Ѽ&@ @ @@c @ @M@q4/  @ @# ) @ @FhKm @ @4Aq @ @GR @ @>}P"@ @ @`4Ѽ&@ @ @@c @ @M@q4/  @ @# ) @ @FhKm @ @4Aq @ @GR @ @>}P"@ @ @`4Ѽ&@ @ @@c @ @M@q4/  @ @# ) @ @FhKm @ @4Aq @ @GR @ @>}P"@ @ @`4Ѽ&@ @ @@c @ @M@q4/  @ @# ) @ @FhKm @ @4Aq @ @GR @ @>}P"@ @ @`4Ѽ&@ @ @@c @ @M@q4/  @ @#9 @ @` <>+ׯ%9 <}˖4]Q|Oh( @ @ )xib j8+OY"@`8 4 @V'7nܘ=IOZ)s6O l߾=۽{aoذ!;,q` ;]v3" @"[lir@e{hLz UƮlݺh_iZ @ @:76 @ @46d#- @ @@u @ @@CA @ @N:M @ @! H @ @ P@c&@ @ Ɔle @ @S@N}c @ @h@cC62 @ @) X  @ @4D@!i @ @hS @ @"0́Ƶaȯme @X 31gEt%L  @@?wDyk"K @T+pjt_/, @X3tj+ݿ,l#K @T/bKGNf @ 4G&lGs.1D @)󑏉, @# O, @ P@z4ȯ @TI=] @PI% @ *.cA @`4F6 P@FF9!@ 0@z:=)% @D 4z4zf0 @y6riF P8FFײe%@h@ &y6r 2@ @'h9tETfP@۳{hIvҞ-;~wu.pj,pFh:jC}xC7ֲ^WS`@cF7T)K+T`YًؓA3ٷoߠ* @@|4ؠMMi xϷB7δ   4z4zo /֭[;v>ڏJx4z amCFHob'g' @`J,)iF҇"_0Leu @S"[Db 6LϏTݸ$ @@|v9j:ҧvܙr)٦M꜊Q\s*NX)ߌtdh\);f4YOcq4yF$I}-<ׯYu~GcD q^Olڧm鑙hLA-[L':{E"b7-_ҳϋIqI"@I䗔ԟnF`@c8xBNܜHvwֆ 7I7y;Fҗۓ;ַ5ɹ׾ٱ;531 x|qS"Wz @`|/oy #0l1/AʯH{t 7rNSh@#%"FNN0"Vѱ>  @f cYG689"6F @ 0X`.|*+# t^"@&0N1?Σ(Ne  @.<$wF @(+Иxz"o|]G#K @T'͑OWE~0D@=ZݑJ @`rOE~edVOH @Uk( @@cK#F!@&0@cգy e @'ys"_(G@cgHx%@ 09ȳӣկD(,Pg1?iV5  @LF =Z}EgENVN䝑% @hO  @D =ZȧE #K @ ]s;VO~d# @h@K` @@iDcuhC @ @@5 @ @@SA @ @F M @ @)MI @ @ P@c&@ @ Ʀu @ @Q@F|C @ @h@cSv: @ @(fϋ;ijs'?;V$@ @`8ŇsR8ƿy/;4 |‰{^ @M{Ѽ&@& 0Σ^<sǩxTE#W @L  @bqij_y&wmQ~JW" @ދ@ӄN`@cٻ"_(kr׮cE @ x/^NK @d2iJ(9}nB'9 @Ok @$q~ &?=q o<:g"wQvNx%@瞛~aÆ좋.N>Nkbmָ5Y@{)S @O4&F~K\s @Ok @2i:%=#?s! @ x/^ @4HF/9 @r/So @e?>sxoS @/z @(3֘sy[.#c/ @'xyz"@ h \8~G\+ @ 0(A@bWE(ۅVX(7E~fX @ދӒ(YGs:ppFS/#~ܩQ~OX @L  @Bqgļ8~sML9wܱ" @ x/> @ 43xLns8| w]Qη]R$@ @`ŗqG`>oĶ73ވéN @ދ7vk-\q>ѸrWm @ @* X* @ @S@n @ @Jh,Sg @ @) }j8xm  @/0qs*Rҍlmҗ}c;ݛ=O8O}j<;ꨣ&oNOx>K.94M1 @@ψ/gE~l"o"#C'ij@cb O`߾};쪫عsg7ޘmݺ5{[ߚs9ԩ`9}_RST̩.*I 01Wߍo#~bIq.-_":rɜzco=%ٕW^yX#8d_ײWَ;9_Ł9UO @)xW#81=84*TI '|"Vg?k]\G 7ߜ_U͛?. f?c?84̩E @(r`x=:?5r'Oȫ;'*x5 PuIW@W1x{߻ Ƌ.(;իWgO~򓳷-۾}{|f 9~|8tsiq_RIDAT  @+QI?#_[_:#_w=sP9UK" h={[ouq-)&W^=^(i-u !PcLGS#pŎLGؾ9% @)?N}S5Z@ZͨWiT1 h,-`o{Th4~ @4L aoqFsj,gzwǒ1֯_:kϋ'{ {!g0AOsRS @i;}H9ʲ|K}SaF hl+P`Æ;s C9rs*Ħ @ؕYR:;8ysOS4.+F (|o~=<#N8aE.S5m @V|ɹ~|~<3ޜrh,[TLӟCqur?HJ狧z.^rsڷoiRNc2kN P=ÿ8xL0w3rEs*SS_h\%V/Y;/Υ={dwFG>򑩛0NxK H[cU_˭ Q^{~ʵX'vNچ9H:jq+S pE-7e{]< +bGm޼ySx ^wy~꧲~K#3o=G?4iXI+ @Yӧ8rzd9~:^;ިowwD!rc#IMSm.uH)_xv=h۶mY >̎;,-rl_g'8>!=4۷g_9tB @E?B_̅??^S{"?%r 4o_GPnۜFQ@yY)Xvmvee\rIo|c~v믿LlْPuɜ3 @<3yYk"o\I5~ ^U/T~ <:P$@yOyS}c^cSN;-Kx饗f333W3֭;R0s:䓧nN8-d  @'XrEwFܗ#?/򿊜zN.UZ&ϩ$0ih@ 0o|N?swgw7fzjvQG '?~'~b0W/RsZzujժ,R^.MjN8-7_ @Z'@C~\;#7K?gG+aՆ>9 "*7S'pI'e)I\1yL.+_Jww};999 @# |=\$Bk֝c~z4mNsL`8 XSK^2K9MI @4IWb1eaAM㜦4. X?C pܿ/VզJ8׬ @ v8}aJV?shG'@`(݌sN?YiH8ip1 @F |*VWE?%+9M i]@ ~M4i7 @@+^19M!)Qmuk&@ @ P@cɠ#@ @ F65 @ @(Y@dP @ @h@cwݚ  @ @, X2 @ @Q@n @ @Jh,Tw @ @( ]f @ @% 4 ; @ @mhl[3 @ @֔ܟ Pm*{Z:޺ukv 7dys-[L˴̃ @ ƁD* @ @ 0H@q @ @ hH @ @ N @ @@ƁD* @ @ 0H@q @ @ hH @ @ N @ @@ƁD* @ @ 0H@q @ @ hH @ @ N @ @@5k@tǎ֭[eii/R'ޑ=*K)v٣dm @%f.֏ߍ @5_0tm  @(M'KQ^|)d6ms٩I Oܹ3'~<{4$kڗIjGb=hE @ jt1lٲ\=&$aOF{2!أhhb_&<=nٕ @c04#@ @ @+ صP"@ @ @@cA8 @ @ 4v- @ @(( XN3 @ @] % @ @ 4ӌ @ @@cB @ @4#@ @ @+ صP"@ @ @@cA8 @ @ 4v- @ @(( XN3 @ @] % @ @ 4ӌ @ @@cB @ @4#@ @ @+ صP"@ @ @@cA8 @ @ 4v- @ @(( XN3 @ @] % @ @ 4ӌ @ @@cB @ @4#@ @ @+ صP"@ @ @@cA8 @ @ 4v- @ @(( XN3 @ @] % @ @ 4ӌ @ @@cB @ @4#@ @ @+ صP"@ @ @@cA8 @ @ 4v- @ @(( XN3 @ @] % @ @ 4ӌ @ @@cB @ @4#@ @ @+ صP"@ @ @@cA8 @ @ 4v- @ @(( XN3 @ @] % @ @ 4ӌ @ @@cB @ @4#@ @ @+ صP"@ @ @@cA8 @ @ 4v- @ @(( XN3 @ @] % @ @ 4ӌ @ @@cB @ @4#@ @ @+ صP"@ @ @@cA8 @ @ 4v- @ @(( XN3 @ @] % @ @ 4ӌ @ @@cB @ @4#@ @ @+ صP"@ @ @@cA8 @ @ 4v- @ @(( XN3 @ @] % @ @ 4ӌ @ @@cB @ @4J@u*D 5hG @@qvZx UyGT!{JS @ 4l(־}(*{ @i9X`Ow Rk=- @i5ڽ;\m @@AܽfS @C@q  @@BhD @@)0dOk.S% 0@3- @(C@ E},'pC\Y [=&;Ѐ @K_7r-KTqHt7GZ^"@ @ 21HTa۶mفu %)޲5 @L^@qm#ow}  @D|3YDvt @Q@F `zl߾}-Z @@^rwNt @Q@F Xwݛx-[ @@^)9c$ @jhyZ4?Zߘ8[tK%@2=$KLt @Y@ h#\uU[|%@qҽ#Cҽ$5rH @L@lB~rU۲~-Z @@^{m!)" @ 0S -BlO|>-r  @@gp yzlz6rH @L@lD˦'KӚ{e˷\U +=c]{D @ 4Nfl*裏μ]="+=#m! @S& 8eҢO2ݛmouvR  0@7{DWD|t|1 @)وNX?xg\s_n,y鞐 O2{FwH @L@nJ˦/<1~￿e KtHaҧ="+A"@ 0kub*7Gn7 s7o[UK ۷/S{G1>y6~  @ 4Nk~wF<믿>?]xٹ瞛^]VK8p ۶m[vue ŘF~kK$, @oR8uBZH$]]t 70APZHLQ+! ?G}ߋ$/,SRF#' $>!v48r|OO  /DQ[ʝrtlZ՚T*LV3OT\.P .0m0XӉ&*{MR]@@@ f1k6M{(v;3bт sͲϑZ߷rljuuN,_1Z,jHsk0_w=Mw0IU6{  @\fǵ;]r([  W5QyP|[B@@0јALy|]eG@YW9F D_KTB7z=  IfԾ?IENDB`././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/nxdlformat.xsl0000755000077000000000000002026514777236751025502 0ustar00rosborn : NX_CHAR [] , --> @ : ( base class application definition ) ././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.8285398 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/pinhole/0000755000077000000000000000000015060352601024175 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/pinhole/pinhole.png0000644000077000000000000006327514777236751026403 0ustar00rosbornPNG  IHDR7U /|sRGBeXIfMM*V^(if7U9sX pHYsgR iTXtXML:com.adobe.xmp 1 2 2 5 ώ@IDATx %U}(t 4S3b+2LENQO`+5x#/ƠE᪑!|b(% >yQf'U}S{װ-wڵjwծl @ @ @ @ @ @ @ @ @ @ @ @ @ U`G$@ @Le qĒ>m @T#:g @C._ߚXҧ @j\Wl}X!hg? @kX4usg @Y#+bIwnT @ Pr}N4wnFc8,peLu @ /W @\lT @ Pr}N WNlTOm @#:WDc0S8*5TOm @#:W @#$wĒkw&=GT  @&:4Z @$l;sQ0W @ v>:0 K/*+I[4&@ @`ço @ 'A>< @pGU-n8E>g#@ @? @`.vft @^ @xaX:t @\5x,1K!FT8S{:/o#@ @7iMh%5ҜX:P @<[ ]O# @i Ϟ(㩝 @bËiEKoXTpEN3 @C%l+8f @ lC[М. @ 0=r6 sK$@T8 -Km @LOuM*pi<:ѝS9 @y9 ,#cJssRԏ @  V4f8>)bycoBG_l2vw) @%0 XRv:ۃ @n))yG,ݑ9㩟_ۙqvO[&9 @)0,XS\OL} @+_T/@r^ꯎm8h6Ng2/ @}H^SumO7G ָ @p St/Dv~꯮8p;' "=>k @H~|ڶ$}vo+X @#AʊXRulfn 80 @2:|2;N 0wǓOֱm}" @T%רe~qҝٹc]@]ظ!?s} "3yct9y(΃8?#J8k>ٷK @ a'"~#yIOOU @|'[~:-mu;ޔ8LVƲM,6 @MN }-LǛmoc}+.e xP&@;FonzScz}qød; @&076X&\X8VA`$7GjM LHz. @KΈc}n 0r~ss܄  P@L,eFH2u @xwlzXyikvӵT][?#(F-` 0/Y @ P\ s{^ lNcC&DZ#  @jxq KTwnʫsn_o @ Лy*6ܹK 2}+o @]@r:$@ |kd%L @*Xz%!@P <'jXUK{zI N @(M@r4Z @`Rb.|(w @Uc}F^`UxO, @(]C+4?by^,ƒތ~J,Wb#@ @ HnNl qfٙ @4^c_" @ @ M@rc @ @4^@rK$@ @ @ HnvSq @ @ Hn6~H @ @@7n* @ @ x/  @ @& M1 @ @/ %  @ @$78F @ @@$7D$@ @ @f7 @ @hfH @ @t @ @l  @ @nT#@ @ @_" @ @ M@rc @ @4^@rK$@ @ @ HnvSq @ @ Hn6~H @ @@7n* @ @ x/  @ @& M1 @ @/ %  @ @$78F @ @@$7D$@ @ @f7 @ @hfH @ @t @ @l  @ @nT#@ @ @_" @ @ M@rc @ @4^@rK$@ @ @ HnvSq @ @ Hn6~H @ @@7n* @ @ x/  @ @& M1 @ @/ %  @ @$78F @ @@$7D$@ @ @f7 @ @hfH @ @t @ @l  @ @nT#@ @ @_" @ @ M@rc @ @4^@rK$@ @ @ HnvSq @ @ Hn6~H @ @@7n* @ @ x/  @ @& M1 @ @/ %  @ @$78F @ @@$7D$@ @ @f7 @ @hfH @ @t @ @l  @ @nT#@ @ @_" @ @ M@rc @ @4^`V#`ǎe~u.=㟟; _`E ᫱  []wݕ"dDC @' 9bkv؈t +&7,XXBQyNnM @@^(T @ @4!@ @ @~@ @ @,  @ @ Hnֿ" @ @ @f4M @ @_@r5 @ @$7 iB @ @@ @ @( YM @ @ܬ D@ @ @@h @ @ Pfk  @ @ Hn@ӄ @ @$7_ @ @ P@@r& @ @/ Y @ @4!@ @ @~@ @ @,  @ @ Hnֿ" @ @ @f4M @ @_@r5 @ @$7 iB @ @@ @ @( YM @ @ܬ D@ @ @@h @ @ Pfk  @ @ Hn@ӄ @ @$7_ @ @ P@@r& @ @/ Y @ @4!@ @ @~@ @ @,  @ @ Hnֿ" @ @ @f4M @ @_@r5 @ @$7 iB @ @@ @ @( YM @ @ܬ D@ @ @@h @ @ Pfk  @ @ Hn@ӄ @ @$7_ @ @ P@@r& @ @/ Y @ @4!@ @ @~@ @ @,  @ @ Hnֿ" @ @ @f4M @ @_@r5 @ @$7 iB @ @@ @ @( YM @ @ܬ D@ @ @@h @ @ Pfk  @ @ Hn@ӄ @ @$7_ @ @ P@@r& @ @/ Y @ @4!@ @ @~@ @ @,  @ @ Hnֿ" @ @ @f4M @ @_@r5 @ @$7 iB @ @@ @ @( YM @ @ܬ D@ @ @@h @ @ Pfk  @ @ Hn@ӄ @ @$7_ @ @ P@@r& @ @/ Y @ @4!@ @ @~@ @ @,  @ @ Hnֿ" @ @ @f4M @ @_@r5 @ @$7 iB @ @@ @ @( YM @ @ܬ D@ @ @@h @ @ Pfk  @ @ Hn@ӄ @ @$7_ @ @ P@@r& @ @/ Y @ @4!@ @ @~@ @ @,  @ @ Hnֿ" @ @ @f4M @ @_@r5 @ @$7 iB @ @@ @ @( YM @ @ܬ D@ @ @@h @ @ Pfk  @ @ Hn@ӄ @ @$7_ @ @ P@@r& @ @/ Y @ @4!@ @ @~@ @ @,  @ @ Hnֿ" @ @ @f4M @ @_@r5 @ @$7 iB @ @@ @ @( YM @ @ܬ D@ @ @@h @ @ Pfk  @ @ Hn@ӄ @ @$7_ @ @ P@@r& @ @/ Y @ @4!@ @ @~@ @ @,  @ @ Hnֿ" @ @ @f4M @ @_@r5 @ @$7 iB @ @@ @ @( YM @ @ܬ D@ @ @@h @ @ Pfk  @ @ Hn@ӄ @ @f @ @#n93@ .i @ @xgc H\ˉ,e:&c9(bI}mM,XF@ 5 @gzl,̌M@ϋçfkbaǗ{tt>탙ϔ|U,?g^`fF$@ @`tRbGgfJ;K/t̙!YfSN9%ۿ۳?󅧞z“O>9y}c+Wkvv[+T Y! @Y ,;"8_"Yя~4}o}+WoW6xۇO|K/ _O8V4|k^n P-oO7  @ @[oۆ3?Z˧Syd?|,} @ @`:Lw_{ٳ;PKnv@@rdC @ @  GSMrJmcOM @ @|ϪU*Wn0#* 9 o @ @`fΜRzkzoNwf_@%0 @([[rqʕe;ǿC@) @Z`ܹ!̙:̝ ;SܜS @ @ lFa//C Gwn!PF2 @ @da ~xkJ-# H@r"h @ @InVm0a @ @CP}Þ{YٴV^_/yXwu+@FY@rsW hO>npwvrK~C6p @Uny{™grvǪXFV@rsd [;^xa~|ɒ%N s {Gx6|7> @F YX{xoC=6tcv(G@rW @`Be˖;/\s5/묳N+9~pl'ݱbŊ-^~7~G|u @B:SO;/U@_(u_Dzwf#(p׆Oӭfz[[^]#{ի^VbC +W \rIg?:޵ @7brhohM|,=ݨйU9~FI?bra,XF򕯄7x`+o|#lKo\LIGK/ m])ɚLE`F;9bI,G27Zf?Kz;;OK]ˇc,F 9Ӛg>/}緞 87gy&~G3!@cGrY,XC#Purq]w={v?x ԑLbIKb @`#6#8"m{9K^֛o @P t>v8}r&E(Pur3]|>̙c@ g~Q,ݙF nL,PWrsuHLd83*}nk~:qB =v^_N֣5'ЃeYg5y/~1]Ο??Pmea@%7?7{ŲK,6X{҈)&˗(؜D ˢXF \uU/pvZ8ի[%yKNG[niu_%=n#@t1i %@ .n1?f&@~ Cm}f*6X[rs12a6%;ԝ7oޔ8)vs#(FHq5l˚:~>KzO`ڒ)b9u)FNxE8c4)9HoX>~]X-w ЫdlWJ*%-=X.S CzKm&,X`ȧjzHު>76lZA_pGLO~ֹ2  0(@OTb#@&Lʤ͓ L'ٞSq_Jz_Ē&})b|l0nS~ĵPZ [˯{O @8dKTWzc @)NQS%"P,6283ʕ/p%uC,Yh@WǘvӱG(m @5ź"V 9"[,b @`$c^smoۥ|l%P[mUc'~l1?X"^ [%Kaժоlٲ𶷽-Y&7om;%[ Ybi?~QgGO̚5+| 믿~Ho3?Z~裏sOxsw[} @ xl}Ԍ @1*mcYt xlfmGݚ駟=АlwqGg}_Ν>- և~M@ͬrzlX^ޱ#HoNO t'\JL?$W^<̰{믿>l&[l14 @H/ @;2V>ֳ* 'pB+!x^.3Ϭu+VsNxK_w^N(xakmK 0'5 \Y RX50N! @`/x I'~?яZe޼y/~[oJ> W]uUvt 7 кtAh`f#IDAT@ [$~X:Jh@Ycc  0mQx;9Vbꫯ?p8:Ҡ;tA~_sR$@>[CW @'fy33j|GJtw 7|sX|y<!%A7x0pg! @4J@rQ!FQ`ƌۙL @4BC[ @ @MCnDH`BwnNH  @ @GWGXƲI,r},˱<K6$7K= @A9qΟygNX*X籔laA_05`H @ @`X:OwEX^qP':%Ss8'@ @\{2sxtUK{[7|+%|T]hfVA  @ @`xNL婸_,߉XVru,oX^qJ b*U لU @qdOqL:XlosWL B,Lsx ] @&p>3G =}k cY{1vrn/_=m 4\X^qLkf,1~9 @ 3 V ;׷+|G/||sSQ9 @?Xoh;_HmNK;E~_Š] @ _b$0 2_kۮ2۾lb*̨!f LJ":>3Mc9Kq ] @p>M0 P6Q &:yd |/h~$7\IY`滳?ev  @(&:V'~b3) ySh3S4]1 ~%7Ӕw%n;gO @ /n%refs'j3>;W9/r,gx<'۾~&7jG͍ŲE,i{"cy,Ul @Eux_uB@p }v%:SbS4) @H 8'{KM&@ @`-ׂ+*mUf#霧':bOSMwr3sc7; @ ?wIN3HnzjIe$7ޡc;;: @ ?gfR9}nB}W>TQCwrs8sb٠t-r! @zpޛOLW 3vsD'p\L=iJNn'Gf_ϳc9VA @@\Q/.pWx^m7L/"I=+^L A"_gP9sl߸L. @ Ok+QVS9pYfbꧦ4L_Ό߽qoc쓩%@ @bnZ Pob׿tb]wEs~rl9>Qi:%0TddF {b}XEO9y @(.:'Oݙ38xv;(VXۻĝec%=t#Џ{#ǡofi?b9-sq] @':|z^&@:ơn gŒ~'cevlog+kL/P+ZLE!0&7wNbjo;ٿyiOq2Gfv  @99zþ+3oS/cIwmftTMLe@&71ƞn1ooGǝGڕ'c}Q,2ǿ3_%@ @`8L@c7_u PzqZ0uY=N2Kh:^ǜx%@ 0ÇqU͉ <tXI/%bm,e7,X xa֫421Um0 @Ę$$HnVljxp%5kXlYH媫 /GuTirQS$@ @Qh3L@sNO~̙3s>=ܓ;^FELe @FQL`Dnp嗏6=vw3,\0lᆭDE]Ժs3jժpg)84v @ @@P4U /m֬YcXx+_͛J^>>3~]wzwoQ @ @( Hn;!XbEgA[zcR]s5ݾ~:#@ @ArRo?<ӝ]w~?wOM} @ @ )ނomn6jnSO=5^׎% @ '0>=y hm??QS?A @K@r, 0DFw'<ܢ_v @ @fwG p+W` 6ߟhgyfS Sa:  @ @@Wͮ, 0Dbz#d[9>;G9/r,gx<'۾ @ @2&/2G7JXwu{ˁ֬Y3~~,XSA8 @ @8L` Zj|wq֬Yo+8 @$7> *lrr*ٙܜ9sf=wR @ @ Hn'0sZ-;vzܑl=T}HM  @ @?  o>>%KOyNDm{91M  @ @GY=לx_~_KbCJR.! 7|s.;,lƹc*VvxcӤ N @ @=sׇrHHC=z [neH;Sٞ|pqǵNҗ̙3f3l1M:a'";i0DS3 @!77bI@ԳoQN/n+:c\ @ Ћ{Ӗ~~5bM0 @ @6Qz袋ʕ+;>^[&Է @LAcS@r vi;}'̚Ռu61&R @ @@/*gl,8 *Ic*wz'@ @y= @ @Y(a @ @ { @ @ 0 P$@ @ @ / P#@ @ @`@$7dI @ @@^@r3F @ @HnB  @ @fC @ @& @ @yͼ @ @" 9 %L @ @y5 @ @D@rs@J @ @$7j @ @ ,0  @ @ Hn= @ @Y(a @ @ { @ @ 0 P$@ @ @ / P#@ @ @`@$7dI @ @@^@r3F @ @HnB  @ @fC @ @& @ @yͼ @ @" 9 %L @ @y5 @ @D@rs@J @ @$7j @ @ ,0  @ @ Hn= @ @Y(a @ @ { @ @ 0 P$@ @ @ / P#@ @ @`@$7dI @ @@^@r3F @ @HnB  @ @fC @ @& @ @yͼ @ @" 9 %L @ @y5 @ @D@rs@J @ @$7j @ @ ,0  @ @ Hn= @ @Y(a @ @ { @ @ 0 P$@ @ @ / P#@ @ @`@$7dI @ @@^@r3F @ @HnB  @ @fC @ @& @ @yͼ @ @" 9 %L @ @y5 @ @D@rs@J @ @$7j @ @ ,0  @ @ Hn= @ @Y(a @ @ { @ @ 0 P$@ @ @ / P#@ @ @`@$7dI @ @@^@r3F @ @HnB  @ @fC @ @& @ @yͼ @ @" 9 %L @ @y5 @ @D@rs@J @ @$7j @ @ ,0  @ @ Hn= @ @Y(a @ @ { @ @ 0 P$@ @ @ / P#@ @ @`@$7dI @ @@^@r3F @ @ػMDQR W=-Y$Io+qs(g @ @ Pf=$ @ @F#E9 @ @ 7! @ @ 0"`)ʙ @ @TY @ @HQ$@ @ @zH @ @7Gr& @ @0nC"@ @ @`D9R3  @ @q @ @#͑I @ @@ @ @0nL @ @*`ܬD @ @qs(g @ @ Pf=$ @ @F#E9 @ @ 7! @ @ 0"`)ʙ @ @TY @ @HQ$@ @ @zH @ @7Gr& @ @0nC"@ @ @`D9R3  @ @q @ @#͑I @ @@ @ @0nL @ @*`ܬD @ @qs(g @ @ Pf=$ @ @F#E9 @ @ 7! @ @ 0"`)ʙ @ @TY @ @HQ$@ @ @zH @ @7Gr& @ @0nC"@ @ @`D9R3  @ @q @ @#͑I @ @@ @ @0nL @ @*`ܬD @ @qs(g @ @ Pf=$ @ @F#E9 @ @ 7! @ @ 0"`)ʙ @ @TY @ @HQ$@ @ @zH @ @7Gr& @ @0nC"@ @ @`D9R3  @ @q @ @#͑I @ @@ @ @0nL @ @*`ܬD @ @qs(g @ @ Pf=$ @ @F#E9 @ @ 7! @ @ 0"`)ʙ @ @TY @ @HQ$@ @ @t:kz? w @0n>O>rp#@}g^ @ 7__w{&@)p6)  @ 1 2 2 5 ώ@IDATx eUy 4-GD; D30(8PqaHRdTʙQLM&`2$dJ+AH"eel,GbX⃤5>Z R$؍-}^ַVӽ6 @ @ @ @ @ @ @ @ @ @ @ @ @]`]# @I܋O @z, @@-kɴ8  @bNH^m @ND`M Wo(O`ctPj#@ @`vc*6 @`jCF7^S @D'br @`XrR1uұ @ л{bQ15c @܋76 @Wct @'^< )LX/5>t @'^<  @&Fn:u @'^<  @Y m @/^S#(^#ŧXˬqm @ظ] @`F[wG[蓩s}?QBLC P{jR-P @$K#Qtt @܋gi$ @n*K @OxF"@DewQtt]F @ŧ74j|'_8"pHץm @L/^|zC# @f.71RJ֙Є @p/^f^EE,m`:qg#@ @{vz ǀ#vq: @'kD@auh @@t!@%.QF @܋L|i !f q9? @X\^w @@}GGȻ>m5O @\V$@` uK-_1Sqxqv?qTн#{kgO% @(^Vs_\q9 @`*|*uOgbz,Zק~/\zo @!P½xrhI_jL @@nbIox&.sb~yEVž#6 @@܋'OEkߏO`$@@]Xgkx}>&oYDZѵ,s  @(^/Ӿ닢 @kJXWojOqWc1i{.;v3i @=swn߿NKq/v|W qDXN}S~w5cc=Fq"5}u!&@ 0@iKaX~>?( +]bQ,_Z`ƭI+) @J_8y_=? ] @`GwGMܘ9cK{! @ދ{-FG @֤/ƪG769^8 @@#]6N_8z+ @`- xMcQL;bׯKf @@#7<" fNonryVc;.&}((Kֹ/ϝB @`ߋ'˗G݋ ~+V߾ɵY=1(w-ssf^ @J p_3.x3HFN`ku7Ź-p~TT.IoxW>%?G;6#ўm{4 @Y |/.ډswDܱ @@GOy_})9Z [# @@G{k:?Xg?c & g#@ qkmik. @ 'laחDܱf 5fl T nwT=`. @ "tkAM^8#Pj @bG5ڟwZv  @NNIXGWn,,pi8$@ {VqnS(J'TJ` ?ܚӱֱ] @"5(oj$=ϟ @ @bTI@ S:o{Wu5&'@ @< ְ(\ईhEhm=vRQF @PP-."@LR1# @;E @i!Hj, @d $@@_6)h;g @ @@ ŦV`*e @ @``R, @ @a (3/VE @ @TK"@ @ @` ̋U @ @ 0@&Œ @ @0bU @ @ P@AuI$ @ @):̼X @ @PP`R, @ @a (3/VE @ @TK"@ @ @` ̋U @ @ 0@&Œ @ @0bU @ @ P@AuI$ @ @):̼X @ @PP`R, @ @a (3/VE @ @TK"@ @ @` ̋U @ @ 0@&Œ @ @0bU @ @ P@AuI$ @ @):̼X @ @PP`R, @ @a (3/VE @ @TK"@ @ @` ̋U @ @ 0@&Œ @ @0bU @ @ P@AuI$ @ @):̼X @ @PP`R, @ @a (3/VE @ @TK"@ @ @` ̋U @ @ 0@&Œ @ @0bU @ @ P@AuI$ @ @):̼X @ @PP`R, @ @a (3/VE @ @TK"@ @ @` ̋U @ @ 0@&Œ @ @0bU @ @ P@AuI$ @ @):̼X @ @PP`R, @ @a (3/VE @ @TK"@ @ @` ̋U @ @ 0@&Œ @ @0bU @ @ P@AuI$ @ @):̼X @ @PP`R, @ @a (3/VE @ @TK"@ @ @` ̋U @ @ 0@&Œ @ @0bU @ @ P@AuI$ @ @):̼X @ @PP`R, @ @a (3/VE @ @TK"@ @ @`놹,*Dю*$a)p",(+v߁ @ @?,xTL!@`gŵ\/u% @V&2/WL`'S7lМ~+j lٲپ}>䓛RO}nl۶-TĘC @PPh b_;N 0صkׂ X\`ӦMy @=T=  @ @:Tȳ(  @ @A@ADC @ @ Pjy% @ @=(h @ @PP#Ϣ$@ @ @ A @ @@ uY @ @ ! @ @C@A< @ @T{@4 @ @u(֑gQ @ @ Ѓj @ @ @:,J @ @zPP @ @!ZGEI @ @@ =  @ @:Tȳ(  @ @A@ADC @ @ Pjy% @ @=(h @ @PP#Ϣ$@ @ @ A @ @@ uY @ @ ! @ @C@A< @ @T{@4 @ @u(֑gQ @ @ Ѓj @ @ @:,J @ @zPP @ @!ZGEI @ @@ =  @ @:Tȳ(  @ @A@ADC @ @ Pjy% @ @=(h @ @PP#Ϣ$@ @ @ A @ @@ uY @ @ 1 2WF;jeU[4eo5k9 ׾+.}^2 @zPP räbU+ޥ @ťղ]]K$@ 0gb'SO8椓N3qǎΝ;g8 @v}iH @` TL=WiLyfP @R'@ @ @bR) @ @r (6> @ @(J @ @ [@A5  @ @(F@AT  @ @ O @ @@1 ŤR  @ @PP-l| @ @PP-&!@ @ @ jna @ @ Pj1 @ @Ts  @ @bTI@ @ @-[ @ @#ZL*B @ @@n'@ @ @bR) @ @r (6> @ @(J @ @ [@A5  @ @(F@AT  @ @ O @ @@1 ŤR  @ @PP-l| @ @PP-&!@ @ @ jna @ @ Pj1 @ @Ts  @ @bTI@ @ @-[ @ @#ZL*B @ @@n'@ @ @bR) @ @r (6> @ @(J @ @ [@A5  @ @(F@AT  @ @ O @ @@1 ŤR  @ @PP-l| @ @PP-&!@ @ @ jna @ @ Pj1 @ @Ts  @ @bTI@ @ @-[ @ @#ZL*B @ @@n'@ @ @bR) @ @r (6> @ @(J @ @ [@A5  @ @(F@AT  @ @ O @ @@1 ŤR  @ @PP-l| @ @PP-&!@ @ @ jna @ @ Pj1 @ @Ts  @ @bTI@ @ @-[ @ @#ZL*B @ @@n'@ @ @bR) @ @r (6> @ @(J @ @ [@A5  @ @(F@AT  @ @ O @ @@1 ŤR  @ @PP-l| @ @PP-&!@ @ @ jna @ @ Pj1 @ @Ts  @ @bTI@ @ @-[ @ @#ZL*B @ @@n'@ @ @bR) @ @r (6> @ @(J @ @ [@A5  @ @(F@AT  @ @ O @ @@1 ŤR  @ @PP-l| @ @PP-&!@ @ @ jna @ @ Pj1 @ @Ts  @ @bTI@ @ @-[ @ @#ZL*B @ @@n'@ @ @bR) @ @r (6> @ @(J @ @ [@A5  @ @(F@AT  @ @ O @ @@1 ŤR  @ @PP-l| @ @PP-&!@ @ @ jna @ @ Pj1 @ @Ts  @ @bTI@ @ @-[ @ @#ZL*B @ @@n'@ @ @bR) @ @r (6> @ @(J @ @ [@A5  @ @(F@AT  @ @ O @ @@1 ŤR  @ @PP-l| @ @PP-&!@ @ @ jna @ @ Pj1 @ @Ts  @ @bTI@ @ @-[ @ @#ZL*B @ @@n'@ @ @bR) @ @r (6> @ @(J @ @ [@A5  @ @(F@AT  @ @ O @ @@1 ŤR  @ @PP-l| @ @PP-&!@ @ @ jna @ @ Pj1 @ @Ts  @ @bTI@ @ @-[ @ @#ZL*B @ @@n'@ @ @bR) @ @r (6> @ @(J @ @ [@A5  @ @(F@AT  @ @ O @ @@1 ŤR  @ @PP-l| @ @PP-&!@ @ @ jna @ @ Pj1 @ @Ts  @ @bTI@ @ @-.'ufӦM XB`۶m gA'   @`WF;jM@bߐFj {a:#Y~SAhbQ.b&۷7L`odWR1b.\=Pյ536Ȟk;kms!(s 'МtICZT&{* ]L& Uh݇T6!л@5y 88Ú>{tl޼yTPM׭"&ⲅ StD;/S?tl#@`Sca lx{mx92TeXT @ @dPP̀jH @ @PP-3"@ @ @ jTC @ @ Pjy @ @T3 @ @2T̫ @ @ Ր @ @)Zf^EE @ @@ $@ @ @L2** @ @20!  @ 0H;v47oZ?ͣ>א!b|pعft0sYW:?'oom6%p7w\n]egeGZK @vܹs⬇@ElXtjӤf#sjN?w)Κ| @usx6lМ~3t֞-[۷?n'|rsY>nN֭[m۶)?c{J?nvR?f#@ @ A1E*x7nf33]=Vwyz嗯JN` ڵkj@-qU6m4*bVu13|-ҏ6E0 @O#?Gh+ @ c]/1E @ _1EhSө6 @%V:zcVs-Ky @@QhgF 0j1#$ql @H<+} @@YT=!9 @R#SNYPHc @<ҟ  @@9   @VM =ƟO @2UPH @21ZESө6 @T=ҟ11&@ @*^mcTL=2 @`F] ~ܰ~F4w+NzG|B cO]{Nu~6'p 5:v9p[B3k@!򑣣CnF <_?/jѾ?Z1sOb| HXw+Z 00I e6R{mY|%<]<9KI+yQA/cB-,/>hhǢmvyTȱm11  @kY)?JD{Mb<]  @X^`_\h~GKOt6 @TK}%dzo_` @W+E~0Uf#@$WAuvrˣ}0l @Nnh6 @rTG#  @f'hWDs7 P@΂jW5 @@+~ *], @2fUPmJ} @JLhF8ڻJ@ @V"|%H+ @ 싩n1ZJh鼍 @`,+  @F }%~,ZJߌvW4 @"C)7oi @,+~#ک.h6 @1ucC:}%d- @J}%-*> @@!TģzطouX`7|wygs6'x #."@ @'0Gמ @ @ Pji$ @ @}(h  @ @PP"͂$@ @ @>A @ @@ UY @ @!ڇ1 @ @B@A4  @ @>M1ȅwcďN~ul @܋O* @@T?y{gVugyxyg'̝B~en  @+p/2/W @zo*jn6*EK6 @V.^|fz @z^ZF;ubľG[ v  @tp/M @kk;)ž{{$͛.W`͙gval4p/>X P@ ΉtF-ZhRBTLJ8/֘ڊ;L_ mD %!nݖI"pg8 ܋$ @f WAXK-yDODm{bg}ktkOnذ9XE rBfA]zX{[nmm橈 {zs/r @`*~+m-cV"_~y% 4SO=A}ӦM G*B _ @~T8񹱓[c @:G}tp1[RbAF4z 0+}ۚP4jbhgޱ  P@|w~ͮ]>i#8Ȉg>}{_s%̿7Gyd\;Է 08K^ƒs'Ύ)hKwoQ @`P!@`N-oEѮvoIhX-}G^)! *0*N;)xmi{Fxs|Lzgv>կ~u~ѩ[nsǚ4)^|i(U ѷ?H8"N?=z?ܵ>5EJR|tL_"=;̽m~bֱ]!Ϗ+X4?GWج)1  0I Hַ_koj>wOMc 0UAkGW5Gz%ֱ]yk>ݩ\|{==ٳgkK8{Ă8%+Mm}oԷT.p5 q{7}c])-vvyX۷o_ӟ&=ڿg<〷xc4{Ċ?cphck?=5ufԑ?jן_/|O޺ߵC5.pGpw,_sΥ;txך:B!^|m* (pr+n['vǯ9i>Ec 0/0MAu~; 4{g83k91[hk˹-45 ] @ <5[_sbNqޚӕ (>tw3oݺCiWӴ/swcZn$@,b״/gcϷX״/t}s1[hk92 (f54u _=ݻ ~߾}\}Ot`M1 @?ozbkbVrޚVZղ% 5E@z83'=Iooƿ'u;_|xWSÚVZ @n뱿w[{o{||\;atr5i$.'@`i%@e]6fϞ=f׮]͛믿~G\r%ǣɟl.}nկ~u֊^K_ӊ0\L 0 w&IBhQ8xMDi:n\SK_Ѻl>tXױn //5|+'?٤\s1METԧ׾9o҃4 @ vhϘ 7G{ ڙRAj,K{N+دmM+q)+PP]  kyի^رc}C ˛(k۬)  @v}imx]Tc\/֔Kָ*I2y<@җ9SO=I߱zUW5t/3v9(yM4 @ |6?+[}ss_~1Z:^h=vr.[5-Xe \/g=96Iym5^zi>g#LFaÆiO{ZsO4m'>[ִ\le lڴ_#uegVt P#nh8vTewx'K[ Bw)x=}  0'ؤeT_]+21=Z @ p\`:*IENDB`././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.8293052 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/source/0000755000077000000000000000000015060352601024037 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/base_classes/source/source.png0000644000077000000000000005446514777236751026110 0ustar00rosbornPNG  IHDR7U /|sRGBeXIfMM*V^(if7U9sX pHYsgR iTXtXML:com.adobe.xmp 1 2 2 5 ώ@IDATxeW]d&7!!H$2.. `]RӢJ( (&Vj’vpԐF$ 8L&w3s笵9瞻޿ar{[F @ @ @ @ @ @ @ @ @ @ @ @ @$8A @@ 5AL}u. @@] @56 @ gm&N(6 @du @ PO`gL^ @ Htgٽv9 @ oviF EQh 6^ @{pufڧ6 @/^|f @&X`k\hp3Nm @OlL`~؉M@% p0gz @{k;Nm @OlLLyq]9>o#@ @{F$PUcUMFyv{N.?tD @@E:/"6 @`_2molv2j9pu @܋77# 0aӅۧ~6 @ /gi$ @`J>}P{/ @ PNx9K# @S(5yo.<>Km @.^|tC#hBpkbA \׽aמ6 @Fp/> @)˸}[s{M'@ PJx)I @S)p^\r)l @,_|@sKonIDb׹-s:#@ 0q˽^& @-bh3hsb*l @!^|h>B 8^,'>>o#@ @ _xOhZ^ 0;GQ??>N @`;G|Ϗ8 @VV`kL7Z-86 @.^|VzTPLelR8q~]8% [~-3 @()0 ў s_}gt'@|uqf9֜4JmW]=ы^Ho @$܋'OGǗ?2Pc @%=.w7K[;b~}YcO ,m @r/`*Z~|){:~ȷVj\L]^H_o @$݋?)"xOF @-pB|hQxiܕ~6&ERcZntW) @{΍鷢w::GFn2JӸiؾ3&_%sxn̷yK @{n^ѺD @F>R[}N^9=/  @{/?{/޴'@*p] hc_5kf I]ҷ0[{{Jf^ @{hک^q?7 @`|g08y=~Pz,|%Ť?6Nv8F @$ߋ{OG;s v}mG*pU}O燰Evu_;C(^ @S-pU\}w/ߧ-nu~#bj"PC F-U}~wc @&M? ˢ:ڎ Y S.cH7Xg8k @&H_Z{ORohJ@r(/*hq|! @ >ǷsnS[; x,}+~#9x$} @VP&c50N[{W|C! @ 5HFonGJ7 @ @7jPL@YbS'  @ @ҫ!𘸊DhύhqN @ps'@ `su9 @(.$@ +e{V @ @@Uܬm2Lm'Zh6 @ PE@Y$8+*D @XK @ @tNž @ @A 7\%@ @ @nv @ @ J@9R, @ @p'@ @ @`PA-b  @ @= @ @njK @ @@' $  @ @psP˥X @ @:f'aO @ @Z. @ @ 7; { @ @% r) @ @N@I @ @ 0(栖K @ @tNž @ @A 7\%@ @ @nv @ @ J@9R, @ @p'@ @ @`PA-b  @ @= @ @njK @ @@' $  @ @psP˥X @ @:f'aO @ @Z. @ @ 7; { @ @% r) @ @N@I @ @ 0(栖K @ @tNž @ @A 7\%@ @ @nv @ @ J@9R, @ @p'@ @ @`PA-b  @ @= @ @njK @ @@' $  @ @psP˥X @ @:f'aO @ @Z. @ @ 7; { @ @% r) @ @N@I @ @ 0(栖K @ @tNž @ @A 7\%@ @ @nv @ @ J@9R, @ @p'@ @ @`PA-b  @ @= @ @njK @ @@' $  @ @psP˥X @ @:f'aO @ @Z. @ @ 7; { @ @% r) @ @N@I @ @ 0(栖K @ @tNž @ @A 7\%@ @ @XO~*ږJG`,P~:9M@Fv_娂 @7cSTWI`.+JF@~*$@ 0YZυol~]O۸:9O 9|33gͭ`ջ6Ys^ Іg=x:%Q @ 7hSyE]3ER F]ܳ})|I'BM`- 7]/ @&B&A @ @ 7s'@ @ @ fˠ @ @rb @ @ ЄpeP @ @\1  @ @hB@2( @ @\f @ @4! lbA @ @@p3WL @ @n6 @ @ @ W@+? @ @M7XE @ @ + ӟ @ @&M," @ @nO @ @@&A @ @ 7s'@ @ @ fˠ @ @rb @ @ ЄpeP @ @\1  @ @hB@2( @ @\f @ @4! lbA @ @@p3WL @ @n6 @ @ @ W@+? @ @M7XE @ @ + ӟ @ @&M," @ @nO @ @@&A @ @ 7s'@ @ @ fˠ @ @rb @ @ ЄpeP @ @\1  @ @hB@2( @ @\f @ @4! lbA @ @@p3WL @ @n6 @ @ @ W@+? @ @M7XE @ @ + ӟ @ @&M," @ @nO @ @@&A @ @ 7s'@ @ @ fˠ @ @rb @ @ ЄpeP @ @\1  @ @hB@2( @ @\f @ @4! lbA @ @@p3WL @ @n6 @ @ @ W@+? @ @M7XE @ @ + ӟ @ @&M," @ @nO @ @@&A @ @ 7s'@ @ @ fˠ @ @rb @ @ ЄpeP @ @\1  @ @hB@2( @ @\f @ @4! lbA @ @@p3WL @ @n6 @ @ @ W@+? @ @M7XE @ @ + ӟ @ @&M," @ @nO @ @@&A @ @ 7s'@ @ @ fˠ @ @rb @ @ ЄpeP @ @\1  @ @hB@2( @ @\f @ @4! lbA @ @@p3WL @ @n6 @ @ @ W@+? @ @M7XE @ @ + ӟ @ @&M," @ @nO @ @@&A @ @ 7s'@ @ @ fˠ @ @rb @ @ ЄpeP @ @\1  @ @hB@2( @ @\f @ @4! lbA @ @@p3WL @ @n6 @ @ @ W@+? @ @M7XE @ @ + ӟ @ @&M," @ @nO @ @@&A @ @ 7s'@ @ @ fˠ @ @rb @ @ ЄpeP @ @\1  @ @hB@2( @ @\f @ @4! lbA @ @@p3WL @ @n6 @ @ @ W@+? @ @M7XE @ @ + ӟ @ @&M," @ @nO @ @@&A @ @ 7s'@ @ @ fˠ @ @rb @ @ ЄpeP @ @\1  @ @hB@2( @ @\f @ @4! lbA @ @@p3WL @ @n6 @ @ @ W@+? @ @M7XE @ @ + ӟ @ @&M," @ @nO @ @@&A @ @ 7s'@ @ @ fˠ @ @rb @ @ ЄpeP @ @\1  @ @hB@2( @ @\f @ @4! lbA @ @@p3WL @ @n6 @ @ @ W@+? @ @M7XE @ @ + ӟ @ @&M," @ @nO @ @@&A @ @ 7s'@ @ @ fˠ @ @rb @ @ ЄpeP @ @\1  @ @hB@2( @ @\f @ @4! lbA @ @@p3WL @ @n6 @ @ @ W@+? @ @M7XE @ @ + ӟ @ @&M," @ @nO @ @@&A @ @ 7s'@ @ @ fˠ @ @rb @ @ ЄpeP @ @\1  @ @hB@2( @ @\f @ @4! lbA @ @@p3WL @ @n6 @ @ @ W@+? @ @M7XE @ @ + ӟ @ @&M," @ @nO @ @@&A @ @ 7s'@ @ @ fˠ @ @rb @ @ ЄpeP @ @\1  @ @hB@2( @ @\f @ @4! lbA @ @@p3WL @ @n6 @ @ @ W@+? @ @M7XE @ @ + ӟ @ @&M," @ @nO @ @@&A @ @ 7s'@ @ @ fˠ @ @rb @ @ ЄpeP @ @\1  @ @hB@2( @ @\f @ @4! lbA @ @@p3WL @ @n6 @ @ @ W@+? @ @Mn R @Xhou @Z 7/wD'G]F @xÿ)Ѯvy4 @iTwf#vF{Z4 @S\mgEKڴ @#fz{팶#J @L@ 0Q;PMl @A D;eNf#@ @`G{Etl#@ ^V @(.  @ 3AO @5P @Rh;`o; 0 7k?vXsy]%i={Io#@1||c%)yz:TD-> &ps%;O7qF803s֝50>N@EG8 @=||kpi#@4+ppc.o:iVIG= (:  ТlqaD l>ȵ~zw?t!@1dj6Xꤓ](9mgo @`[֮85&4++*{Q40%Zzap߭ڸnon.LOM m^`y ztF.Y D{^?i *@spC8^/9}sf[ߖSbg ߖ~իw= PMБ#tډ'ݧg[&"@ҿmlhm1{ @!MQhWFxCu),5qsHxl1h |5kng_a| @`_1ڛ=?hEK1>-}a86& @ # =}1ƶhQ @.F{E ~mg+}2Z:o#@ J`%>  @H_c)ڗ @h%c}lS7 @ 00 дچ[oD @8OLܕ  @`Z!  @ @ 7˛ @ @  Ȧ @=CGn*5"!@@9ưІ$PK培Y<Lvz{yg?rdik.ظwl~I"@X!gǼ/hF;%}6ڍmojjҘwZ".^G}.fZ\t ڗzݻ "'80+P)  PV{?`;cc3>t负_߾qq @1߉zmc9u>1^<K5C՘VX`2+\  PNs3]#Ѻ8hkcثi $ЂpUPcx=8]oo~S7mzh '̼3K>[oݽc߽.WSiQ @4(^M8}-h7K} Z=+vt/ưWP If  Co㺁{7^afۯ}MG5{54 @@ӫ8;VhqC54F 7/k^{"s7 0+w:o}~v۶DO۴i36o\^M%5Ep/> Ь@zxSW㽏qC54֎POzwC0ϘŹG[?v(.p޽ogNK7N nmÇO'nos.7Ԕ+,&^|1! R`E >lmO?sR;54FCq=GK??!^|8Zl?(U i#@u:Ǭ[+=~޽o͛퟿aϞSK1 @`VhU/<{=-sN??e쏩e3 6F 7?^׻GWν-/~m}w! [];^h s޽G?grϫ)WLXD"@&@`E͚~b>Yx_M@C5L;w/㟚}=M  033G5kׯ_#GF(('^(#=F% 9IKLn5O`@%tvg-}n. @`,gfkV^QU׬9Ͼ#G TS)I @s@$@`Ef?;^pnLso}rǜ;||#05!~pqNPza#@֮^yjwCƪ#33ǼC'Ք ;,UR#@@rl^„ss0Ģ]Դ(+P PL_7-Q  /?"<[c<<_QΩi=%@E܋/m }*f\=/"Cj! "p? 1_x9$@Xߒ~6hj: xFp/>" PLKRz~|F;wI'{5* {`&@`E>5g2=;.y"И@pԸuc?7{!7{v1sz @`,?tn]}oჇ}dSn펻m=s=)[usPS PDxF PPczR P{Fo8>c;s8 5xK`@rzo|5W.PH_){<}M(qmYrc7u?v뭗ݹo1?+Onݶ3nn ?7vAkwN1MzM >@ U A f{Q_7{vFHuwx{|uG֟ؽ29t'09kG_qtx}ߌ=8~wf#@>p>~ߡCozW<nxS6nkk߾3o_ͲGWuhӦ=GO,pof&eM6m5eҗ4ړg'R~@==tȖ 6}޵} ]q4Uc @`*܋O岻h/4}Wqr67L_JD禦q n3ܹW}q~gý'e.?{no{{<~]{իV_OrM9 @HGa*s߄/+HKP/,t<5-txs\ /yԣ>yE]3 ,(~Ч3;p`ӷlE׭;&\w߿n׿9smקyF1 ۽yQ[~@+8'&L]hE\Ʃy-q Hqrjʸt] L?ssr$\ S!̭[Hm9Kw[K~'lIDATiI)] @uj~|Cw~Y L:i5-pNlkvuogW#3^r=>bMcLC @LO,{hFhAp ^?46|O~ZkjE  @%q5'ExlZe/f$@`o>/ڹ޼%~ { bM- @`dhZe/ ܬonF(g>Z+ŚZ3R @~+hD8 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(, , j8 @ @78 @ @ #@ @ @pY @ @(,xkX3{[v4\ @ҿ[Ub  @Lpsty0{Ǧ@  @ <'  @Xps9j̻gK2ULHfU  @I qIENDB`././@PaxHeader0000000000000000000000000000005400000000000010214 xustar0017 gid=660979062 27 mtime=1757533568.879118 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/0000755000077000000000000000000015060352601025025 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXaberration.nxdl.xml0000644000077000000000000000456414777236751031145 0ustar00rosborn Quantified aberration coefficient in an aberration_model. Confidence How was the uncertainty quantified e.g. via the 95% confidence interval. Time elapsed since the last measurement. For the CEOS definitions the C aberrations are radial-symmetric and have no angle entry, while the A, B, D, S, or R aberrations are n-fold symmetric and have an angle entry. For the NION definitions the coordinate system differs to the one used in CEOS and instead two aberration coefficients a and b are used. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXaberration_model.nxdl.xml0000644000077000000000000000714214777236751032320 0ustar00rosborn Models for aberrations of electro-magnetic lenses in electron microscopy. See `S. J. Pennycock and P. D. Nellist <https://doi.org/10.1007/978-1-4419-7200-2>`_ (page 44ff, and page 118ff) for different definitions available and further details. Table 7-2 of Ibid. publication (page 305ff) documents how to convert from the NION to the CEOS definitions. Defocus Two-fold astigmatism Two-fold astigmatism Second-order axial coma Second-order axial coma Threefold astigmatism Threefold astigmatism Spherical aberration Star aberration Star aberration Fourfold astigmatism Fourfold astigmatism Fifth-order spherical aberration ././@PaxHeader0000000000000000000000000000022700000000000010216 xustar00112 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXaberration_model_ceos.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXaberration_model_ceos.nxdl.x0000644000077000000000000001143114777236751032774 0ustar00rosborn CEOS definitions/model for aberrations of electro-magnetic lenses. See `S. J. Pennycock and P. D. Nellist <https://doi.org/10.1007/978-1-4419-7200-2>`_ (page 44ff, and page 118ff) for different definitions available and further details. Table 7-2 of Ibid. publication (page 305ff) documents how to convert from the NION to the CEOS definitions. ././@PaxHeader0000000000000000000000000000022700000000000010216 xustar00112 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXaberration_model_nion.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXaberration_model_nion.nxdl.x0000644000077000000000000000573414777236751033017 0ustar00rosborn NION definitions/model for aberrations of electro-magnetic lenses. See `S. J. Pennycock and P. D. Nellist <https://doi.org/10.1007/978-1-4419-7200-2>`_ (page 44ff, and page 118ff) for different definitions available and further details. Table 7-2 of Ibid. publication (page 305ff) documents how to convert from the NION to the CEOS definitions. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXadc.nxdl.xml0000644000077000000000000000313614777236751027540 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Analog-to-digital converter component/integrated circuit. TBD. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXaperture_em.nxdl.xml0000644000077000000000000000473714777236751031331 0ustar00rosborn Details of an individual aperture for beams in electron microscopy. Given name/alias of the aperture. Relevant value from the control software. This is not always just the diameter of (not even in the case) of a circular aperture. Usually it is a mode setting value which is selected in the control software. Which settings are behind the value should be defined for now in the description field, if these are known in more detail. Ideally, a (globally) unique persistent identifier, link, or text to a resource which gives further details. Alternatively a free-text field. Affine transformation which detail the arrangement in the microscope relative to the optical axis and beam path. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm.nxdl.xml0000644000077000000000000030145214777236751027570 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Total number of ions collected. Total number of independent wires in the delay-line detector. Number of support points for e.g. modeling peaks. Maximum number of allowed atoms per (molecular) ion (fragment). Needs to match maximum_number_of_atoms_per_molecular_ion. Number of mass-to-charge-state-ratio intervals of this ion type. Number of bins in the x direction. Number of bins in the y direction. Number of bins in the z direction. Number of bins. Total number of integers in the supplementary XDMF topology array. Application definition for atom probe and field ion microscopy experiments. This application definition provides a place to document data and metadata to an atom probe experiment. Primarily the measurement itself is documented. However, as most atom probe experiments are controlled with commercial software which does not allow to access the raw detector hits, this application definition also includes two key groups of processing steps (reconstruction and ranging). During tomographic reconstruction measured data are processed into a point cloud of reconstructed positions of certain ions. During ranging time-of-flight data are identified as representing specific ions to annotate each ion with a label. Commercial software used in atom probe research is designed as an integrated acquisition and instrument control software. For AMETEK/Cameca local electrode atom probe (LEAP) instruments the least processed (rawest) numerical results and metadata are stored in so-called STR, RRAW, RHIT, and HITS files, which are proprietary and their file format specifications not publicly documented. Supplementary metadata are kept in a database (formerly known as the ISDb) which is connected to the instrument control software and synced with the experiment while ions are detected. In effect, RHIT and HITS files store the (rawest) experiment data in a closed manner that is practically useless for users unless they have access to the commercial software. To arrive at a state that atom probe microscopy (APM) with LEAP instruments delivers a dataset with which users can study reconstructed atomic position and do e.g. composition analyses or other post-processing analysis tasks, these raw data have to be processed. Therefore, it is necessary that for an application definition to be useful, details about the physical acquisition of the raw data and all its processing steps have to be stored. With this a user can create derived quantities like ion hit positions (on the detector) and calibrated time-of-flight data. These derived quantities are also needed to obtain calibrated mass-to-charge-state ratios, and finally the tomographic reconstruction of the ion positions. In most cases, an APM dataset is useful only if it gets post-processed via so-called ranging. Ranging defines rules for mapping time-of-flight and mass-to-charge-state ratio values on ion species. This is post-processing even though in practice it is performed sometimes already (as preview) already while data are still being collected. The ion types decode molecular identities which can very often be mapped to elemental identities, and also be used to distinguish isotopes. All these steps are in most cases performed using commercial software. Frequently, though, ranging and post-processing is also performed with (open-source) research software. Therefore, there is strictly speaking not a single program used throughout an atom probe analysis not even for the early stage of data acquisition and processing stages to obtain a useful reconstructed and ranged dataset. This application definition documents not only the measurement but also the key post-processing steps which transform the proprietary data into a tomographic reconstruction with ranging definitions. Future guidance by the technology partners like AMETEK/Cameca could improve this description to cover a substantial larger number of eventually metadata that so far are neither publicly documented nor accessible. An at least as strong as SHA256 hashvalue of the file that specifies the application definition. NeXus NXDL schema to which this file conforms. Ideally, a (globally) unique persistent identifier for referring to this experiment. The identifier is usually defined/issued by the facility, laboratory, or the principle investigator. The identifier enables to link experiments to e.g. proposals. Free-text description about the experiment. Users are strongly advised to detail the sample history in the respective field and fill rather as completely as possible the fields of the application definition behind instead of filling in these details into the experiment_description free-text description field. Users are encouraged to add in this field eventual DOIs to papers which yield further details to the experiment. ISO 8601 time code with local time zone offset to UTC information included when the microscope session started. If the application demands that time codes in this section of the application definition should only be used for specifying when the experiment was performed - and the exact duration is not relevant - this start_time field should be used. Often though it is useful to specify a time interval with specifying both start_time and end_time to allow for more detailed bookkeeping and interpretation of the experiment. The user should be aware that even with having both dates specified, it may not be possible to infer how long the experiment took or for how long data were collected. More detailed timing data over the course of the experiment have to be collected to compute this event chain during the experiment. ISO 8601 time code with local time zone offset to UTC included when the microscope session ended. Neither the specimen_name nor the experiment_identifier but the identifier through which the experiment is referred to in the control software. For LEAP instruments it is recommended to use the IVAS/APSuite run_number. For other instruments, such as the one from Stuttgart or Oxcart from Erlangen, or the instruments at GPM in Rouen, use the identifier which is closest in meaning to the LEAP run number. The field does not have to be required if the information is recoverable in the dataset which for LEAP instruments is the case when RHIT or HITS files are also stored alongside a data artifact instance which is generated according to this NXapm application definition. As a destructive microscopy technique, a run can be performed only once. It is possible, however, to interrupt a run and restart data acquisition while still using the same specimen. In this case, each evaporation run needs to be distinguished with different run numbers. We follow this habit of most atom probe groups. This application definition does currently not allow storing the entire set of such interrupted runs. Not because of a technical limitation within NeXus but because we have not seen a covering use case based on which we could have designed and implemented this case. Atom probers are invited to contact the respective people in the FAIRmat team to fix this. Binary container for a file or a compressed collection of files which can be used to add further descriptions and details to the experiment. The container can hold a compressed archive. Required for operation_mode apt_fim or other to give further details. Users should not abuse this field to provide free-text information. Instead, these pieces of information should be mapped to respective groups and sections. A small image that is representative of the entry; this can be an image taken from the dataset like a thumbnail of a spectrum. A 640 x 480 pixel jpeg image is recommended. Adding a scale bar to that image is recommended but not required as the main purpose of the thumbnail is to provide e.g. thumbnail images for displaying them in data repositories. What type of atom probe microscopy experiment is performed. This field is primarily meant to inform materials database systems to qualitatively filter experiments: * apt are experiments where the analysis_chamber has no imaging gas. experiment with LEAP instruments are typically performed as apt. * fim are experiments where the analysis_chamber has an imaging gas, which should be specified with the atmosphere in the analysis_chamber group. * apt_fim should be used for combinations of the two imaging modes. * other should be used in combination with the user specifying details in the experiment_documentation field. Contact information and eventually details person(s) involved in the microscope session. This can be the principle investigator who performed this experiment. Adding multiple users if relevant is recommended. Given (first) name and surname of the user. Name of the affiliation of the user at the point in time when the experiment was performed. Postal address of the affiliation. Email address of the user at the point in time when the experiment was performed. Writing the most permanently used email is recommended. Globally unique identifier of the user as offered by services like ORCID or ResearcherID. If this field is field the specific service should also be written in orcid_platform Name of the OrcID or ResearcherID where the account under orcid is registered. (Business) (tele)phone number of the user at the point in time when the experiment was performed. Which role does the user have in the place and at the point in time when the experiment was performed? Technician operating the microscope. Student, postdoc, principle investigator, guest are common examples. Account name that is associated with the user in social media platforms. Name of the social media platform where the account under social_media_name is registered. Description of the sample from which the specimen was prepared or site-specifically cut out using e.g. a focused-ion beam instrument. The sample group is currently a place for storing suggestions from atom probers about other knowledge they have gained about the sample from which they cut the specimen which is field-evaporated during the experiment. Typically this is possible because the atom probe specimen is usually not heat treated as is but one assumes that one has the sample prepared as needed (i.e. with a specific grain diameter) and can thus just cut out the specimen from that material. There are cases though where the specimen is processed further, i.e. the specimen is machined further or exposed to external stimuli during the experiment. In this case, these details should not be stored in the sample group but atom probers should make suggestions how this application definition can be improved to find a better place and compromise how to improve this application definition. In the future also details like how the grain_diameter was characterized, how the sample was prepared, how the material was heat-treated etc., should be stored as using specific application definitions/schemas which are then arranged and documented with a description of the workflow so that actionable graphs become instantiatable. Qualitative information about the grain size, here specifically described as the equivalent spherical diameter of an assumed average grain size for the crystal ensemble. Users of this information should be aware that although the grain diameter or radius is often referred to as grain size and used in e.g. Hall-Petch-type materials models this is if at all an ensemble average whose reporting may be very informative or not if the specimen contains a few grains only. In atom probe the latter is often the case because grains are measured partially as their diameter can be in the order of magnitude of the physical diameter of the specimen. Reporting a grain size is useful though as it allows judging if specific features are expected to be found in the detector hit map. Magnitude of the standard deviation of the grain_diameter. The temperature of the last heat treatment step before quenching. Knowledge about this value can give an idea how the sample was heat treated, however if available a documentation of the annealing treatment should be delivered by adding additional files which are uploaded alongside an NXapm instance. In the future there should better be an own schema used for the heat treatment. Magnitude of the standard deviation of the heat_treatment_temperature. Rate of the last quenching step. Knowledge about this value can give an idea how the specimen was heat treated, however there are many situations where one can imagine that the scalar value for just the quenching rate, i.e. the first derivative of the measured time-temperature profile is itself time-dependant. An example is when the specimen was left in the furnace after the furnace was switched off. In this case the specimen cools down with a specific rate of how this furnace cools down in the lab. Processes which in practice are often not documented with measuring the time-temperature profile. This can be problematic because when the furnace door was left open or the ambient temperature in the lab changes, i.e. for a series of experiments where one is conducted on a hot summer day and the next during winter as might have an effect on the evolution of the microstructure. There are many cases where this has been reported to be an issue in industry, e.g. think about aging aluminium samples left on the factory parking lot on a hot summer day. Magnitude of the standard deviation of the heat_treatment_quenching_rate. The chemical composition of the sample. Typically it is assumed that this more macroscopic composition is representative for the material so that the composition of the typically substantially less voluminous specimen probes from the more voluminous sample. Reporting compositions as atom and weight percent yields both dimensionless quantities but their conceptual interpretation differs. A normalization based on atom_percent counts relative to the total number of atoms are of a particular type. By contrast, weight_percent normalization factorizes in the respective mass of the elements. Python libraries like pint are challenged by these differences as at.-% and wt.-% both yield fractional quantities. Human-readable name of the element/ion (e.g. Fe). Name has to be a symbol of an element from the periodic table. All symbols in the set of NXion instances inside the group chemical_composition need to be disjoint. Composition value for the element/ion referred to under name. The value is normalized based on normalization, i.e. composition is either an atom or weight percent quantity. Magnitude of the standard deviation of the composition (value). Descriptive name or ideally (globally) unique persistent identifier. The name distinguishes the specimen from all others and especially the predecessor/origin (see the sample group) from where this specimen was cut. In cases where the specimen was e.g. site-specifically cut from the sample referred to in the sample group or in cases of an instrument session during which multiple specimens are loaded, the name has to be descriptive enough to resolve which specimen on e.g. the microtip array was taken. The user is advised to store the details how a specimen was cut/prepared from a specific sample in the sample_history. The sample_history field must not be used for writing an alias of the specimen. Instead, use the field alias for this. As an example there may be a specimen/sample monitoring system in a lab with bar codes. The bar code is a good specimen/sample name. A shorter and more human readable alias like A0 can be an example for something to write in the alias field. In cases where multiple specimens have been loaded into the microscope the name has to be the specific one, whose results are stored by this NXentry, because a single NXentry is to be used for the characterization of a single specimen in a single continuous run. Details about the specimen preparation should be stored in the sample_history or if this is not possible in the sample group. Ideally, a reference to the location of or a (globally) unique persistent identifier of e.g. another file which should document ideally as many details as possible of the material, its microstructure, and its thermo-chemo-mechanical processing/ preparation history. In the case that such a detailed history of the sample/specimen is not available, use this field as a free-text description to specify a sub-set of the entire sample history, i.e. what you would consider as being the key steps and relevant information about the specimen, its material, microstructure, thermo-chemo-mechanical processing state and details of the preparation. ISO 8601 time code with local time zone offset to UTC information when the specimen was prepared. Ideally, report the end of the preparation, i.e. the last known time the measured specimen surface was actively prepared. Usually this should be a part of the sample history, i.e. the sample is imagined handed over for the analysis. At the point it enters the microscope the session starts. Knowing when the specimen was exposed to e.g. specific atmosphere is especially required for environmentally sensitive material such as hydrogen charged specimens or experiments including tracers with a short half time. Further time stamps prior to preparation_date should better be placed in resources which describe the sample_history. Short_name or abbreviation of the specimen name field. List of comma-separated elements from the periodic table that are contained in the sample. If the sample substance has multiple components, all elements from each component must be included in `atom_types`. The purpose of the field is to offer materials database systems an opportunity to parse the relevant elements without having to interpret these from the sample history or from other data sources. Discouraged free-text field in case properly designed records for the sample_history or sample section are not available. Report if the specimen is polycrystalline, in which case it contains a grain or phase boundary, or if the specimen is a single crystal. Hard link to a location in the hierarchy of the NeXus file where the data for default plotting are stored. Container to hold different coordinate systems conventions. For the specific idea and conventions to use with the NXcoordinate_system_set inspect the description of the NXcoordinate_system_set base class. Specific details for application in atom probe microscopy follow. In this research field scientists distinguish usually several Euclidean coordinate systems (CS): * World space; a CS specifying a local coordinate system of the planet earth which identifies into which direction gravity is pointing such that the laboratory space CS can be rotated into this world CS. * The laboratory space; a CS specifying the room where the instrument is located in or a physical landmark on the instrument, e.g. the direction of the transfer rod where positive is the direction how the rod has to be pushed during loading a specimen into the instrument. In summary, this CS is defined by the chassis of the instrument. * The specimen space; a CS affixed to either the base or the initial apex of the specimen, whose z axis points towards the detector. * The detector space; a CS affixed to the detector plane whose xy plane is usually in the detector and whose z axis points towards the specimen. This is a distorted space with respect to the reconstructed ion positions. * The reconstruction space; a CS in which the reconstructed ion positions are defined. The orientation depends on the analysis software used. * Eventually further coordinate systems attached to the flight path of individual ions might be defined. Coordinate systems should be right-handed ones. Clockwise rotations should be considered positive rotations. In atom probe microscopy a frequently used choice for the detector space (CS) is discussed with the so-called detector space image (stack). This is a stack of two-dimensional histograms of detected ions within a predefined evaporation ID interval. Typically, the set of ion evaporation sequence IDs is grouped into chunks. For each chunk a histogram of the ion hit positions on the detector is computed. This leaves the possibility for inconsistency between the so-called detector space and the e.g. specimen space. The transformation here resolves this ambiguity by specifying how the positive z-axes of either coordinate systems is oriented. Consult the work of A. J. Breen and B. Gault and team for further details. Metadata and numerical data of the atom probe and the lab in which it stands. An atom probe microscope (experiment) is different compared to a large- scale facility or electron accelerator experiments in at least two ways: * First, ionized atoms and molecular ion(s fragments) (in the case of atom probe tomography) and (primarily) imaging gas ions (in the case of field ion microscopy) are accelerated towards a position-sensitive and time-of-flight taking detector system. Hence, there is no real probe/beam. * Second, the specimen is the lens of the microscope. Given name of the atom probe at the hosting institution. This is an alias. Examples could be LEAP5000, Raptor, Oxcart, one atom at a time, etc. Location of the lab or place where the instrument is installed. Using GEOREF is preferred. The space inside the atom probe along which ions pass nominally when they leave the specimen and travel to the detector. THIS DOCSTRING NEEDS CLARIFICATION. The nominal diameter of the specimen ROI which is measured in the experiment. It is important to mention that the physical specimen cannot be measured completely because ions may launch but not be detected or hit elsewhere in the analysis_chamber. Is a reflectron installed and was it used? A local electrode guiding the ion flight path. Also called counter or extraction electrode. Identifier of the local_electrode in an e.g. database. Detector for taking raw time-of-flight and ion/hit impact positions data. Description of the detector type. Specify if the detector is not the usual type, i.e. not a delay-line detector. In the case the detector is a multi-channel plate/ delay line detector, use mcp_dld. In the case the detector is a phosphor CCD use phosphor_ccd. In other case specify the detector type via free-text. Given name/alias. Given brand or model name by the manufacturer. Given hardware name/serial number or hash identifier issued by the manufacturer. Given name of the manufacturer. Amplitude of the signal detected on the multi-channel plate (MCP). This field should be used for storing the signal amplitude quantity within ATO files. The ATO file format is used primarily by the atom probe groups of the GPM in Rouen, France. Atom probe microscopes use controlled laser, voltage, or a combination of pulsing strategies to trigger the excitation and eventual field evaporation/emission of an ion during an experiment. If pulse_mode is set to laser or laser_and_voltage (e.g. for LEAP6000-type instruments) having the group/section laser_gun is required and the following of its fields have to be filled: * name * wavelength * energy Average temperature at the specimen base, i.e. base_temperature during the measurement. The best estimate, at experiment time, for the temperature at the sample base (furthest point along sample apex and holding assembly that is removable from the sample stage). Average pressure in the analysis chamber. Average pressure in the buffer chamber. Average pressure in the load_lock_chamber. A possible place, which has to be discussed with the atom probe community more though, where quantitative details about the calibration of the counter electrode could be stored. Work in this direction was e.g. reported by the `Erlangen group <https://www.youtube.com/watch?v=99hNEkqdj78t=1876s>`_ (see `P. Felfer et al. <http://dx.doi.org/10.1016/j.ultramic.2016.07.008>`_ ) A place where details about the initial shape of the specimen can be stored. Ideally, here also data about the shape evolution of the specimen can be stored. There are currently very few techniques which can measure the shape evolution: * Correlative electron microscopy coupled with modeling but this usually takes an interrupted experiment in which the specimen is transferred, an image taken, and a new evaporation sequence initiated. Examples are `I. Mouton et al. <https://doi.org/10.1017/S1431927618016161>`_ and `C. Fletcher <https://doi.org/10.1088/1361-6463/abaaa6>`_. * Another method, which is less accurate though, is to monitor the specimen evolution via the in-built camera system (if available) in the instrument. * Another method is to use correlated scanning force microscopy methods like reported in `C. Fleischmann <https://doi.org/10.1016/j.ultramic.2018.08.010>`_. * A continuous monitoring of the specimen in a correlative electron microscopy/atom probe experiment is planned to be developed by `T. Kelly et al. <https://doi.org/10.1017/S1431927620022205>`_ Nothing can be said about the outcome of this research yet but here is where such spatio-temporally data could be stored. Ideally measured or best elaborated guess of the initial radius of the specimen. Ideally measured or best elaborated guess of the shank angle. This is a measure of the specimen taper. Define it in such a way that the base of the specimen is modelled as a conical frustrum so that the shank angle is the (shortest) angle between the specimen space z-axis and a vector on the lateral surface of the cone. Average detection rate over the course of the experiment. Estimated field at the apex along the evaporation sequence. The majority of atom probe microscopes come from a single commercial manufacturer `AMETEK (formerly Cameca) <https://www.atomprobe.com>`_. Their instruments are controlled via an(/a set) of integrated instrument control system(s) (APSuite/IVAS/DAVis). By contrast, instruments which were built by individual research groups such as of the French (GPM, Rouen, France), the Schmitz (Inspico, Stuttgart, Germany), the Felfer (Oxcart, Erlangen, Germany), the Northwestern (D. Isheim, Seidman group et al.), or the PNNL group (Pacific Northwest National Laborary, Portland, Oregon, U.S.) have other solutions to control the instrument. Some of which are modularized and open, some of which realize also integrated control units with portions of eventually undisclosed source code and (so far) lacking (support of)/open APIs. Currently, there is no accepted/implemented community-specific API for getting finely granularized access to such control settings. These considerations motivated the design of the NXapm application definition in that it stores quantities in NXcollection. groups to begin with. Holding heterogeneous, not yet standardized but relevant pieces of information is the purpose of this collection. Track time-dependent details over the course of the measurement about the buffer_chamber. Track time-dependent details over the course of the measurement about the load_lock_chamber. Track time-dependent details over the course of the measurement about the analysis_chamber. A statement whether the measurement was successful or failed prematurely. Details about where ions hit the ion_detector and data processing steps related to analog-to-digital conversion of detector signals into ion hit positions. For AMETEK LEAP instruments this processing takes place partly in the control unit of the detector partly in the software. The process is controlled by the acquisition/ instrument control software (IVAS/APSuite/DAVis). The exact details are not documented by AMETEK in an open manner. For instruments built by individual research groups, like the Oxcart instrument, individual timing data from the delay-line detector are openly accessible. Raw readings from the analog-to-digital-converter timing circuits of the detector wires. Evaluated ion impact coordinates at the detector (either as computed from the arrival time data or as reported by the control software). If the acquisition software enables it one can also store in this field the hit_positions, as measured by the detector, without any corrections. This could be a place where currently the publicly undocumented algorithmic steps are stored how detected hits are judged for their quality. In CamecaRoot this there is something mentioned like golden and partial hits, here is where this could be documented. Data post-processing step which is, like the impact position analyses, usually executed in the integrated control software. This processing yields how many ions were detected with each pulse. It is possible that multiple ions evaporate and hit the same or different pixels of the detector on the same pulse. These data form the basis to analyses of the so-called (hit) multiplicity of an ion. Multiplicity must not be confused with how many atoms f the same element or isotope, respectively, a molecular ion contains (which is instead encoded with the isotope_vector field of each NXion instance). Number of pulses since the last detected ion pulse. For multi-hit records, after the first record, this is zero. Number of pulses since the start of the atom probe run/evaporation sequence. Hit multiplicity. Like impact position and hit multiplicity computations, ion filtering is a data post-processing step with which users identify which of the detected ions should be included in the voltage-and-bowl correction. This post-processing is usually performed via GUI interaction in the reconstruction pipeline of IVAS/APSuite. Bitmask which is set to true if the ion is considered and false otherwise. Data post-processing step to correct for ion impact position flight path differences, detector biases, and nonlinearities. This step is usually performed with commercial software. Raw time-of-flight data as read out from the acquisition software if these data are available and accessible. Calibrated time-of-flight. The key idea and algorithm of the voltage-and-bowl correction is qualitatively similar for instruments of different manufacturers or research groups. Specific differences exists though in the form of different calibration models. For now we do not wish to resolve or generalize these differences. Rather the purpose of this collection is to provide a container where model-specific parameters and calibration models can be stored if users know these for sure. For AMETEK LEAP instruments this should be the place for storing initial calibration values. These values are accessible normally only by AMETEK service engineers. They use these for calibrating the detector and instrument. Users can also use this NXcollection for storing the iteratively identified calibrations which scientists will see displayed in e.g. APSuite while they execute the voltage-and-bowl correction as a part of the reconstruction pipeline in APSuite. Data post-processing step in which calibrated time-of-flight data (ToF) are interpreted into mass-to-charge-state ratios. Store vendor-specific calibration models here (if available). Mass-to-charge-state ratio values. Data post-processing step to create a tomographic reconstruction of the specimen based on selected calibrated ion hit positions, the evaporation sequence, and voltage curve data. Very often scientists use own software scripts according to published procedures, so-called reconstruction protocols, i.e. numerical recipes how to compute x, y, z atomic positions from the input data. Qualitative statement about which reconstruction protocol was used. Different reconstruction protocols exist. Although these approaches are qualitatively similar, each protocol uses different parameters (and interprets these differently). The source code to IVAS/APSuite is not open. For now users should store reconstruction parameter in a collection. Different strategies for crystallographic calibration of the reconstruction are possible. The field is required and details should be specified in free-text at least. If the not crystallographic calibration was performed the field should be filled with the n/a, meaning not applied. Three-dimensional reconstructed positions of the ions. Interleaved array of x, y, z positions in the specimen space. An array of triplets of integers which can serve as a supplementary array for Paraview to display the reconstructed dataset. The XDMF primitive type is here 1, the number of primitives 1 per triplet, the last integer in each triplet is the identifier of each point starting from zero. Six equally formatted sextets chained together. For each sextett the first entry is an XDMF primitive topology key (here 5 for polygon), the second entry the XDMF primitive count value (here 4 because each face is a quad). The remaining four values are the vertex indices. To get a first overview of the reconstructed dataset, the format conversion computes a simple 3d histogram of the ion density using one nanometer cubic bins without applying smoothening algorithms on this histogram. A default three-dimensional histogram of the total number of ions in each bin obtained via using a rectangular transfer function. Array of counts for each bin. Bin center of mass position along the z axis. Bin center of mass position along the y axis. Bin center of mass position along the x axis. Data post-processing step in which elemental, isotopic, and/or molecular identities are assigned to the ions. The documentation of these steps is based on ideas described in the literature: * `M. K. Miller <https://doi.org/10.1002/sia.1719>`_ * `D. Haley et al. <https://doi.org/10.1017/S1431927620024290>`_ * `M. Kühbach et al. <https://doi.org/10.1017/S1431927621012241>`_ How many ion types are distinguished. If no ranging was performed each ion is of the special unknown type. The iontype ID of this unknown type is 0 which is a reserve value. Consequently, iontypes start counting from 1. Assumed maximum value that suffices to store all relevant molecular ions, even the most complicated ones. Currently a value of 32 is used. Specifies the computation of the mass-to-charge histogram. Usually mass-to-charge values are studied as an ensemble quantity, specifically these values are binned. This (NXprocess) stores the settings of this binning. Smallest and largest mass-to-charge-state ratio value. Binning width of the mass-to-charge-state ratio values. A default histogram aka mass spectrum of the mass-to-charge-state ratio values. Array of counts for each bin. Right boundary of each mass-to-charge-state ratio value bin. Details of the background model which was used to correct the total counts per bin into counts. How where peaks in the background-corrected in the histogram of mass-to-charge-state ratio values identified? THIS DOCSTRING NEEDS CLARIFICATION. Details about how peaks, with taking into account error models, were interpreted as ion types or not. ././@PaxHeader0000000000000000000000000000023700000000000010217 xustar00120 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_composition_space_results.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_composition_space_result0000644000077000000000000005622214777236751033223 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Number of voxel of discretized domain for analyzed part of the dataset. The dimensionality of the grid. The cardinality or total number of cells/grid points. Number of terms in the composition clustering dictionary Number of terms in the position clustering dictionary Results of a run with Alaukik Saxena's composition space tool. This is an initial draft application definition for the common NFDI-MatWerk, FAIRmat infrastructure use case IUC09 how to improve the organization and results storage of the composition space tool and make these data at the same time directly understandable for NOMAD. This draft does no contain yet the annotations for how to also store in the HDF5 file a default visualization whereby the composition grid could directly be explored using H5Web. I am happy to add this ones the data have been mapped on this schema, i.e. more discussion needed. Also iso-surfaces can be described, for paraprobe, this is a solved problem, check the respective group in the NXapm_paraprobe_results_nanochem data schema/application definition. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. TBD, maybe how to link between pyiron state tracking and app state tracking Disencouraged place for free-text for e.g. comments. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file was started, i.e. when composition space tool was started as a process. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file were completed and composition space tool exited as a process. The path and name of the config file for this analysis. TBD, this can be e.g. Alaukik's YAML file for composition space. At least SHA256 strong hash of the specific config_file for tracking provenance. The path and name of the file (technology partner or community format) from which reconstructed ion positions were loaded. The path and name of the file (technology partner or community format from which ranging definitions, i.e. how to map mass-to- charge-state ratios on iontypes were loaded. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. A statement whether the executable managed to process the analysis or failed prematurely. This status is written to the results file after the end_time at which point the executable must not compute any analysis. Only when this status message is present and shows `success`, the user should consider the results. In all other cases it might be that the executable has terminated prematurely or another error occurred. If used, contact information and eventually details of at least the person who performed this analysis. Details about the coordinate system conventions used. The individual coordinate systems which should be used. Some suggestions follow, e.g. that field names should be prefixed with the following controlled terms indicating which individual coordinate system is described: * world * composition_space * lab * specimen * laser * leap * detector * recon Reference to or definition of a coordinate system with which the positions and directions are interpretable. Position of each cell in Euclidean space. For each ion, the identifier of the voxel in which the ion is located. In Alaukik's tool the GMM step. The keywords of the dictionary of distinguished compositionally- defined cluster, e.g. the phases. Examples for keywords could be phase1, phase2, and so one and so forth. Resolves for each keyword in cluster_dict which integer is used to label something that it belongs or is assumed to represent this cluster. For example if the voxel grid is used to report that there are voxels which are assumed to represent volume of either phase1 or phase2, the cluster_dict_keyword would be a list with two names phase1 and phase2, respectively. The cluster_dict_value would be a list of e.g. integers 1 and 2. These could be used to build an array with as many entries as there are voxel and store in this array the respective value to encode which phase is assumed for each voxel. In Alaukik's tool the DBScan step after the GMM step. The keywords of the dictionary of distinguished spatially-contiguous clusters. Examples for keywords could be precipitate1, precipitate2, and so one and so forth. Resolves for each keyword in cluster_dict which integer is used to label something that it belongs or is assumed to represent this cluster. For example if the voxel grid is used to report that there are voxels which are assumed to represent volume of certain precipitates, say we found ten precipitates and consider the rest as matrix. We could make a list of say matrix, precipitate1, precipitate2, ..., precipitate10. With cluster_dict_value then running from 0 to 10, i.e. matrix is flagged special as 0 and the remaining particles are indexed conveniently as 1, 2, ..., 10 like end users expect. Specify if it was different from the number_of_processes in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_input_ranging.nxdl.xml0000644000077000000000000000611214777236751032507 0ustar00rosborn Metadata to ranging definitions made for a dataset in atom probe microscopy. Ranging is the process of labeling time-of-flight data with so-called iontypes which ideally specify the most likely ion/molecular ion evaporated within a given mass-to-charge-state-ratio value interval. The paraprobe-toolbox uses the convention that the so-called UNKNOWNTYPE iontype (or unranged ions) represents the default iontype. The ID of this special iontype is always reserved as 0. Each ion is assigned to the UNKNOWNTYPE by default. Iontypes are assigned by checking if the mass-to-charge-state-ratio values of an ion matches to any of the defined mass-to-charge-state-ratio intervals. Path and name of the NeXus/HDF5 file which stores ranging definitions. Version identifier of the file (representing an at least SHA256 strong) hash. Such hashes serve reproducibility as they can be used for tracking provenance metadata in a workflow. Name of the group (prefix to the individual ranging definitions) inside the file referred to by filename which points to the specific ranging definition to use. An HDF5 file can store multiple ranging definitions. Using an ID is the mechanism to distinguish which specific ranging (version) will be processed. Reconstruction and ranging IDs can differ. They specify different IDs. ././@PaxHeader0000000000000000000000000000023200000000000010212 xustar00115 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_input_reconstruction.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_input_reconstruction.nxd0000644000077000000000000000532314777236751033173 0ustar00rosborn Metadata of a dataset (tomographic reconstruction) in atom probe microscopy. Name of the (NeXus)/HDF5 file which stores reconstructed ion position and mass-to-charge-state ratios. Such an HDF5 file can store multiple reconstructions. Using the information within the dataset_name fields is the mechanism whereby paraprobe decides which reconstruction to process. With this design it is possible that the same HDF5 file can store multiple versions of a reconstruction. Version identifier of the file (representing an at least SHA256 strong) hash. Such hashes serve reproducibility as they can be used for tracking provenance metadata in a workflow. Name of the dataset inside the HDF5 file which refers to the specific reconstructed ion positions to use for this analysis. Name of the dataset inside the HDF5 file which refers to the specific mass-to-charge-state-ratio values to use for this analysis. ././@PaxHeader0000000000000000000000000000024000000000000010211 xustar00121 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_clusterer.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_cluster0000644000077000000000000006007714777236751033153 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Maximum number of atoms per molecular ion. Should be 32 for paraprobe. Number of clustering algorithms used. Number of different iontypes to distinguish during clustering. Configuration of a paraprobe-clusterer tool run in atom probe microscopy. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ever persistent resources where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable in the same deterministic manner. ISO 8601 formatted time code with local time zone offset to UTC information included when this configuration file was created. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. How many tasks to perform? This process maps results from cluster analyses performed with IVAS/APSuite into an interoperable representation. Specifically in this process paraprobe-clusterer takes results from clustering methods from other tools of the APM community, like IVAS/APSuite. These results are usually reported in two ways. Either as an explicit list of reconstructed ion positions. In the case of IVAS these positions are reported through a text file with a cluster label for each position. Alternatively, the list of positions is reported, as it is the case for AMETEK (IVAS/AP Suite) but the cluster labels are specified implicitly only in the following way: The mass-to-charge-state ratio column of a what is effectively a file formatted like POS is used to assign a hypothetical mass-to-charge value which resolves a floating point representation of the cluster ID. Another case can occur where all disjoint floating point values, i.e. here cluster labels, are reported and then a dictionary is created how each value matches to a cluster ID. In general the cluster ID zero is reserved for marking the dataset as to not be assigned to any cluster. Therefore, indices of disjoint clusters start at 1. AMETEK/Cameca results of cluster analyses, like with the maximum- separation (MS) method clustering algorithm `J. Hyde et al. <https://doi.org/10.1557/PROC-650-R6.6>`_ are stored as an improper POS file: This is a matrix of floating point quadruplets, one for each ion and as many quadruplets as ions were investigated. The first three values encode the position of the ion. The fourth value is an improper mass-to-charge-state-ratio value which encodes the integer identifier of the cluster as a floating point number. Specifies if the tool should try to recover for each position the closest matching position from dataset/dataset_name_reconstruction (within floating point accuracy). This can be useful for instance when users wish to recover the original evaporation ID, which IVAS/AP Suite drops for instance when writing their *.indexed.* cluster results POS files. This process performs a cluster analysis on a reconstructed dataset or a portion of the reconstruction. The tool enables to inject precomputed distance information for each point/ion which can be used for further post-processing and analysis. Name of an HDF5 file which contains the ion distances. Version identifier of the file such as a secure hash which documents the binary state of the file to add an additional layer of reproducibility from which file specifically contains these data. Absolute HDF5 path to the dataset with distance values for each ion. How should iontypes be interpreted/considered during the cluster analysis. Different options exist how iontypes are interpreted (if considered at all) given an iontype represents in general a (molecular) ion with different isotopes that have individually different multiplicity. The value resolve_all will set an ion active in the analysis regardless of which iontype it is. The value resolve_unknown will set an ion active when it is of the UNKNOWNTYPE. The value resolve_ion will set an ion active if it is of the specific iontype, irregardless of its elemental or isotopic details. The value resolve_element will set an ion active, and most importantly, account as many times for it, as the (molecular) ion contains atoms of elements in the whitelist ion_query_isotope_vector. The value resolve_isotope will set an ion active, and most importantly, account as many times for it, as the (molecular) ion contains isotopes in the whitelist ion_query_isotope_vector. In effect, ion_query_isotope_vector acts as a whitelist to filter which ions are considered as source ions of the correlation statistics and how the multiplicity of each ion will be factorized. This is relevant as in atom probe we have the situation that a ion of a molecular ion with more than one nuclid, say Ti O for example is counted such that although there is a single TiO molecular ion at a position that the cluster has two members. This multiplicity affects the size of the feature and chemical composition. Matrix of isotope vectors, as many as rows as different candidates for iontypes should be distinguished as possible source iontypes. In the simplest case, the matrix contains only the proton number of the element in the row, all other values set to zero. Combined with ion_query_type_source set to resolve_element this will recover usual spatial correlation statistics like the 1NN C-C spatial statistics. Settings for DBScan clustering algorithm. For original details about the algorithms and (performance-relevant) details consider: * `M. Ester et al. <https://dx.doi.org/10.5555/3001460.3001507>`_ * `M. Götz et al. <https://dx.doi.org/10.1145/2834892.2834894>`_ For details about how the DBScan algorithms is the key behind the specific modification known as the maximum-separation method in the atom probe community consider `E. Jägle et al. <https://dx.doi.org/10.1017/S1431927614013294>`_ Strategy how runs are performed with different parameter: * For tuple as many runs are performed as parameter values. * For combinatorics individual parameter arrays are looped over. As an example we may define eps with ten entries and min_pts with three entries. If high_throughput_method is tuple the analysis is invalid as we have an insufficient number of min_pts for the ten eps values. By contrast, for combinatorics paraprobe-clusterer will run three individual min_pts runs for each eps value, resulting in a total of 30 analyses. As an example the DBScan analysis reported in `M. Kühbach et al. <https://dx.doi.org/10.1038/s41524-020-00486-1>`_ would have defined an array of values np.linspace(0.2, 5.0, nums=241, endpoint=True) eps values, min_pts one, and high_throughput_method set to combinatorics. Array of epsilon (eps) parameter values. Array of minimum points (min_pts) parameter values. Settings for the OPTICS clustering algorithm. * `M. Ankerest et al. <https://dx.doi.org/10.1145/304181.304187>`_ Strategy how runs are performed with different parameter: * For tuple as many runs are performed as parameter values. * For combinatorics individual parameter arrays are looped over. See the explanation for the corresponding parameter for dbscan processes above-mentioned for further details. Array of minimum points (min_pts) parameter values. Array of maximum epsilon (eps) parameter values. Settings for the HPDBScan clustering algorithm. * L. McInnes et al. <https://dx.doi.org/10.21105/joss.00205>`_ * scikit-learn hdbscan library `<https://hdbscan.readthedocs.io/en/latest/how_hdbscan_works.html>`_ See also this documentation for details about the parameter. Here we use the terminology of the hdbscan documentation. Strategy how runs are performed with different parameter: * For tuple as many runs are performed as parameter values. * For combinatorics individual parameter arrays are looped over. See the explanation for the corresponding parameter for dbscan processes above-mentioned for further details. Array of min_cluster_size parameter values. Array of min_samples parameter values. Array of cluster_selection parameter values. Array of alpha parameter values. ././@PaxHeader0000000000000000000000000000024000000000000010211 xustar00121 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_distancer.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_distanc0000644000077000000000000003226114777236751033111 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Configuration/settings of a paraprobe-distancer software tool run. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ever persistent resources where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable in the same deterministic manner. ISO 8601 formatted time code with local time zone offset to UTC information included when this configuration file was created. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. How many individual analyses should the tool execute. Compute for all filtered points, e.g. ions of the point set the shortest Euclidean distance to the closest triangle of the set of triangles. The triangles can formed a closed surface mesh. Distances are not simple distances based on normal projections but giving an exact solution. Paraprobe-distancer enables the computation of the Euclidean shortest distance for each member of a set of points against a set of triangles. In contrast to comparable methods used in atom probe the here computed distance is not simply the projected distance to one of the triangles but the more costly but robust computation of the distance between a point and a triangle. The triangles can represent for instance the facets of a triangulated surface mesh of a model for the edge of the dataset. Such a model can be computed with paraprobe-surfacer. Alternatively, the triangles can be those from the set of all facets for a set of convex hulls, alpha-shapes, or alpha wrappings about three-dimensional objects like precipitates (computed with e.g. paraprobe-nanochem). Currently, the tool does not check if the respectively specified triangle sets are consistent, what their topology is, or whether or not they are consistently oriented. Each dataset that is referred to in the list_of _dataset_names_vertices should be an (Nvertices, 3) array of NX_FLOAT. Each dataset referred to in the list_of_dataset_names_facet_indices should be an (Nfacets, 3) array of NX_UINT. Facet indices refer to vertex indices. These need to start at zero and must not exceed Nvertices - 1, i.e. the identifier_offset is 0 and vertices are indexed thus implicitly. Facet normal vectors have to be also an array of shape (Nfacets, 3) of NX_FLOAT. How many triangle sets to consider. List of triangle sets. This design allows users to combine multiple triangle sets. Name of the HDF5 file(s) which contain(s) vertex coordinates and facet indices to describe the desired set of triangles. Version identifier of the file such as a secure hash which documents the binary state of the file to add an additional layer of reproducibility. Absolute HDF5 path to the dataset which specifies the array of vertex positions. Absolute HDF5 path to the dataset which specifies the array of facet indices. Absolute HDF5 path to the dataset which specifies the array of facet normal vectors. Specifies for which ions/points the tool will compute distances. The purpose of this setting is to avoid unnecessary computations when the user requests to only compute distances of ions within a threshold distance to the triangle soup. By default the distances are computed for all ions; however the setting skin enables to compute distances only for those ions which are not farther away located to a triangle than threshold_distance. Maximum distance for which distances are computed when method is skin. ././@PaxHeader0000000000000000000000000000024200000000000010213 xustar00123 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_intersector.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_interse0000644000077000000000000004625714777236751033147 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Configuration of a paraprobe-intersector tool run in atom probe microscopy. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ever persistent resources where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable in the same deterministic manner. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. ISO 8601 formatted time code with local time zone offset to UTC information included when this configuration file was created. For now a support field for the tool to identify how many individual analyses the tool should execute as part of the analysis. Tracking volume_volume_spatial_correlation is the process of building logical relations between volumetric features based on meshes, their proximity and eventual intersections. Volumetric overlap and proximity of volumetric features is identified for members of sets of features to members of other sets of volumetric features. Specifically, for each time step k pairs of sets are compared: Members of a so-called current_set to members of a so-called next_set. Members can be different types of volumetric features. In the analysis of M. Kuehbach et al. specifically features can be so-called objects (closed non-degnerated polyhedra representing watertight parts of an e.g. iso-surface) and/or proxies. Proxies are computed doppelganger/replacement meshes for parts of an iso-surface which initially were not resulting in watertight meshes because objects at the edge of the dataset or incompletely measured or truncated objects. Specifies the method whereby to decide if two objects intersect volumetrically. For reasons which are detailed in the supplementary material of `M. Kühbach et al. <https://arxiv.org/abs/2205.13510>`_, the tool by default assumes that two objects intersect if they share at least one ion with the same evaporation ID (shared_ion). Alternatively, with specifying tetrahedra_intersections, the tool can perform an intersection analysis which attempts to tetrahedralize first each polyhedron. If successful, the tool then checks for at least one pair of intersecting tetrahedra to identify if two objects intersect or not. However, we found that these geometrical analyses can result in corner cases which the currently used library (TetGen) was not unable to tetrahedralize successfully. These cases were virtually always associated with complicated non-convex polyhedra which had portions of the mesh that were connected by almost point like tubes of triangles. Finding more robust methods for computing intersections between not necessarily convex polyhedra might improve the situation in the future. Specifies if the tool evaluates if for each pair the two objects (and proxies if used) intersect volumetrically. Specifies if the tool evaluates if for each pair the two objects (and proxies if used) lie closer to one another than the threshold_proximity. Specifies if the tool evaluates, ones all tracking tasks were successfully completed, how intersecting or proximity related objects build sub-graphs. This is the feature which enabled M. Kühbach et al. 2022 the high-throughput analyses of how many objects are coprecipitates in the sense that they are single, duplet, triplet, or high-order. For these analyses to work has_object_volume needs to be activated. The maximum Euclidean distance between two objects below which both objects are still considered within proximity. Specifies if the tool stores the so-called forward relations between nodes representing members of the current_set to nodes representing members of the next_set. Specifies if the tool stores the so-called backward relations between nodes representing members of the next_set to nodes representing members of the current_set. Current set stores a set of members, meshes of volumetric features, which will be checked for proximity and/or volumetric intersection, to members of the current_set. The meshes were generated as a result of some other meshing process. This identifier can be used to label the current set. The label effectively represents (can be interpreted as) the time/iteration step when the current set was taken. As it is detailed in `M. Kühbach et al. 2022 <https://arxiv.org/abs/2205.13510>`_, this identifier takes the role of the time variable :math:`k`. The total number of distinguished feature sets FEATURE. It is assumed that the members within all these FEATURE sets are representing a set together. As an example this set might represent all volumetric_features. However, users might have formed a subset of this set where individuals were regrouped. For paraprobe-nanochem this is the case for objects and proxies. Specifically, objects are distinguished further into those far from and those close to the edge of the dataset. Similarly, proxies are distinguished further into those far from and those close to the edge of the dataset. So while these four sub-sets contain different so-called types of features key is that they were all generated for one set, here the current_set. Descriptive category explaining what these features are. Name of the (NeXus)/HDF5 file which contains triangulated surface meshes of the members of the set as instances of NXcg_polyhedron_set. Version identifier of the file such as a secure hash which documents the binary state of the file to add an additional layer of reproducibility from which file specifically contains these data. String whereby the path to the geometry data can be interferred automatically. Currently groupname_geometry_prefix/object<ID>/polyhedron. Array of identifier whereby the path to the geometry data can be interferred automatically. Next set stores a set of members, meshes of volumetric features, which will be checked for proximity and/or volumetric intersection, to members of the next_set. The meshes were generated as a result of some other meshing process. This identifier can be used to label the next_set. The label effectively represents (can be interpreted as) the time/iteration step when the current set was taken. As it is detailed in `M. Kühbach et al. 2022 <https://arxiv.org/abs/2205.13510>`_, this identifier takes the role of the time variable :math:`k + 1`. The total number of distinguished feature sets FEATURE. It is assumed that the members within all these FEATURE sets are representing a set together. As an example this set might represent all volumetric_features. However, users might have formed a subset of this set where individuals were regrouped. For paraprobe-nanochem this is the case for objects and proxies. Specifically, objects are distinguished further into those far from and those close to the edge of the dataset. Similarly, proxies are distinguished further into those far from and those close to the edge of the dataset. So while these four sub-sets contain different so-called types of features key is that they were all generated for one set, here the next_set. Descriptive category explaining what these features are. Name of the (NeXus)/HDF5 file which contains triangulated surface meshes of the members of the set as instances of NXcg_polyhedron_set. Version identifier of the file such as a secure hash which documents the binary state of the file to add an additional layer of reproducibility from which file specifically contains these data. String whereby the path to the geometry data can be interferred automatically. Currently groupname_geometry_prefix/object<ID>/polyhedron. Array of identifier whereby the path to the geometry data can be interferred automatically. ././@PaxHeader0000000000000000000000000000023700000000000010217 xustar00120 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_nanochem.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_nanoche0000644000077000000000000021150414777236751033076 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. How many iontypes does the delocalization filter specify. How many disjoint control points are defined. How many iontypes does the interface meshing iontype filter specify. How many DCOM iterations. Maximum number of atoms per molecular ion. Configuration of a paraprobe-nanochem tool run in atom probe microscopy. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ever persistent resources where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable in the same deterministic manner. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. ISO 8601 formatted time code with local time zone offset to UTC information included when this configuration file was created. How many individual analyses should the tool execute as part of the analysis. The tool enables to inject a previously computed triangle soup or triangulated surface mesh representing a model (of the surface) of the edge of the dataset. This model can be used to detect and control various sources of bias in the analyses. Name of the HDF5 file which contains vertex coordinates and facet indices to describe the desired set of triangles which represents the edge of the dataset. Version identifier of the file such as a secure hash which documents the binary state of the file to add an additional layer of reproducibility from which file specifically contains these data. Absolute path to the HDF5 dataset in the respectively specified HDF5 file under filename which details the array of vertex positions. Absolute path to the HDF5 dataset in the respective specified HDF5 file under filename which details the array of facet indices. The tool enables to inject precomputed distance information for each point/ion which can be used for further post-processing and analysis. Name of an HDF5 file which contains the ion distances. Version identifier of the file such as a secure hash which documents the binary state of the file to add an additional layer of reproducibility from which file specifically contains these data. Absolute HDF5 path to the dataset with distance values for each ion. Discretization of the ion point cloud on a three-dimensional grid. Delocalization in the field of atom probe microscopy is the process of discretizing a point cloud. By default the tool computes a full kernel density estimation of decomposed ions to create one discretized field for each element. Although, this uses an efficient multithreaded algorithm, the computation is costly. Therefore, it can be advantageous for users to load an already computed delocalization. This can be achieved with the load_existent option. When using this option the user is responsible to assure that the settings which were used for computing this already existent delocalization are specified in the same manner as they were. Matrix of isotope vectors representing iontypes. The filter specifies a matrix of isotope_vectors which is the most general approach to define if and how many times an ion is counted. Currently, paraprobe_nanochem performs a so-called atomic decomposition of all iontypes. Specifically, the tool interprets of how many elements/atoms a molecular ion is composed; and thus determines the atoms multiplicity with respect to the iontype. Let's take the hydroxonium H3O+ molecular ion as an example: It contains hydrogen and oxygen as atoms. The multiplicity of hydrogen is three whereas that of oxygen is one. Therefore in an atomic decomposition computation of the iso-surface each H3O+ ion adds three hydrogen counts. This is a practical solution which accepts the situation that during an atom probe experiment not each bond of each ion/a group of neighboring atoms is broken but molecular ions get detected. The exact ab-initio details depend on the local field conditions and thus also the detailed spatial arrangement of the atoms and their own electronic state and that of the neighbors before and upon launch. Being able to measure the information for such sites only as molecular ions causes an inherent information loss with respect to the detailed spatial arrangement. This information loss is more relevant for local electrode atom probe than for field ion microscopy setting how precisely the atomic positions can be reconstructed. Accounting for multiplicities assures that at least the compositional information is analyzed. List of individual grid resolutions to analyse. Paraprobe discretizes on a cuboidal 3D grid with cubic cells, with an edge length of values in gridresolutions. Half the width of a :math:`{(2 \cdot n + 1)}^3` cubic kernel of voxel beyond which the Gaussian Ansatz function will be truncated. Intensity beyond the kernel is refactored into the kernel via a normalization procedure. Variance of the Gaussian Ansatz kernel :math:`\sigma_x = \sigma_y = 2 \cdot \sigma_z`. How should the results of the kernel-density estimation be computed into quantities. By default the tool computes the total number (intensity) of ions or elements. Alternatively the tool can compute the total intensity, the composition, or the concentration of the ions/elements specified by the white list of elements in each voxel. Specifies if the tool should report the delocalization 3D field values. Optional computation of iso-surfaces after each computed delocalization to identify for instance objects in the microstructure (line features, interfaces, precipitates). As it is detailed in M. Kühbach et al. 2022 npj Comp. Mat., the handling of triangles at the edge of the dataset requires special attention. Especially for composition-normalized delocalization it is possible that the composition increases towards the edge of the dataset because the quotient of two numbers which are both smaller than one is larger instead of smaller than the counter. By default, the tool uses a modified marching cubes algorithm of Lewiner et al. which detects if voxels face such a situation. In this case, no triangles are generated for such voxels. Alternatively, (via setting keep_edge_triangles) the user can instruct the tool to not remove these triangles at the cost of bias. Specifically, in this case the user should understand that all objects/microstructural features in contact with the edge of the dataset get usually artificial enlarged and their surface mesh often closed during the marching. This closure however is artificial! It can result in biased shape analyses for those objects. The reason why this should in general be avoided is a similar argument as when one analyzes grain shapes in orientation microscopy via e.g. SEM/EBSD. Namely, these grains, here the objects at the edge of the dataset, were not fully captured during e.g. limited field of view. Therefore, it is questionable if one would like to make substantiated quantitative statements about them. Thanks to collaboration with the V. V. Rielli and S. Primig, though, paraprobe-nanochem implements a complete pipeline to process even these objects at the edge of the dataset. Specifically, the objects are replaced by so-called proxies, i.e. replacement objects whose holes on the surface mesh have been closed if possible via iterative mesh and hole-filling procedures with fairing operations. In the results of each paraprobe-nanochem run, these proxy objects are listed separately to allow users to quantify and analyze in detail the differences when accounting for these objects or not. Especially this is relevant in atom probe microscopy as objects can contain a few dozen atoms only. Users should be aware that results from fairing operations should be compared to results from analyses where all objects at the edge of the dataset have been removed. Also users should be careful with overestimating the statistical significance of their dataset especially when using atom probe to compare multiple descriptors: Even though a dataset may give statistically significant results for compositions, this does not necessarily mean it will yield also statistically significant and unbiased results for three-dimensional object analyses. Being able to quantify these effects and making atom probers aware of these subtleties was one of the main reasons why the paraprobe-nanochem tool was implemented. The ion-to-edge-distance that is used in the analyses of objects (and proxies) to identify whether these are inside the dataset or close to the edge of the dataset. If an object has at least one ion with an ion-to-edge-distance below this threshold, the object is considered as one which lies close to the edge of the dataset. This implements essentially a distance-based approach to solve the in general complicated and involved treatment of computing volumetric intersections between not-necessarily convex closed 2-manifolds. In fact, such computational geometry analyses can face numerical robustness issues as a consequence of which a mesh can be detected as lying completely inside a dataset although in reality it is epsilon-close only, i.e. almost touching only the edge (e.g. from inside). Practically, humans would state in such case that the object is close to the edge of the dataset; however mathematically the object is indeed completely inside. In short, a distance-based approach is rigorous and more flexible. Array of iso-contour values. For each value the tool computes an iso-surface and performs subsequent analyses. The unit depends on the choice for the normalization of the accumulated ion intensity values per voxel: * total, total number of ions, irrespective their iontype * candidates, total number of ions with type in the isotope_whitelist. * composition, candidates but normalized by composition, i.e. at.-% * concentration, candidates but normalized by voxel volume, i.e. ions/nm^3 Specifies if the tool should report the triangle soup which represents each triangle of the iso-surface complex. Each triangle is reported with an ID specifying to which triangle cluster (with IDs starting at zero) the triangle belongs. The clustering is performed with a modified DBScan algorithm. Specifies if the tool should analyze for each cluster of triangles how they can be combinatorially processed to describe a closed polyhedron. Such a closed polyhedron (not-necessarily convex!) can be used to describe objects with relevance in the microstructure. Users should be aware that the resulting mesh does not necessarily represent the original precipitate. In fact, inaccuracies in the reconstructed positions cause inaccuracies in all downstream processing operations. Especially the effect on one-dimensional spatial statistics like nearest neighbor correlation functions these effects were discussed in the literature `B. Gault et al. <https://doi.org/10.1017/S1431927621012952>`_ In continuation of these thoughts this applies also to reconstructed objects. A well-known example is the discussion of shape deviations of Al3Sc precipitates in aluminium alloys which in reconstructions can appear as ellipsoids although they should be almost spherical, depending on their size. Specifies if the tool should report a triangulated surface mesh for each identified closed polyhedron. It is common that a marching cubes algorithm creates iso-surfaces with a fraction of very small sub-complexes (e.g. small isolated tetrahedra). These can be for instance be small tetrahedra/polyhedra about the center of a voxel of the support grid on which marching cubes operates. When these objects are small, it is possible that they contain no ion; especially when considering that delocalization procedures smoothen the positions of the ions. Although these small objects are interesting from a numerical point of view, scientists may argue they are not worth to be reported: Physically a microstructural feature should contain at least a few atoms to become relevant. Therefore, paraprobe-nanochem by default does not report closed objects which bound not at least one ion. Specifies if the tool should report properties of each closed polyhedron, such as volume and other details. Specifies if the tool should report for each closed polyhedron an approximately optimal bounding box fitted to all triangles of the surface mesh of the object and ion positions inside or on the surface of the mesh. This bounding box informs about the closed object's shape (aspect ratios). Specifies if the tool should report for each closed polyhedron all evaporation IDs of those ions which lie inside or on the boundary of the polyhedron. This information can be used e.g. in the paraprobe-intersector tool to infer if two objects share common ions, which can be interpreted as an argument to assume that the two objects intersect. Users should be aware that two arbitrarily closed polyhedra in three-dimensional space can intersect but not share a common ion. In fact, the volume bounded by the polyhedron has sharp edges. When taking two objects, an edge of one object may for instance pierce into the surface of another object. In this case the objects partially overlap / intersect volumetrically; however this piercing might be so small or happening in the volume between two ion positions and thus sharing ions is a sufficient but not a necessary condition for object intersections. Paraprobe-intersector implements a rigorous alternative to handle such intersections using a tetrahedralization of closed objects. However, in many practical cases, we found through examples that there are polyhedra (especially when they are non-convex and have almost point-like) connected channels, where tetrahedralization libraries have challenges dealing with. In this case checking intersections via shared_ions is a more practical alternative. Specifies if the tool should report if a (closed) object has contact with the edge of the dataset. For this the tool currently inspects if the shortest distance between the set of triangles of the surface mesh and the triangles of the edge model is larger than the edge_threshold. If this is the case, the object is assumed to be deeply embedded in the interior of the dataset. Otherwise, the object is considered to have an edge contact, i.e. it is likely affected by the fact that the dataset is finite. Specifies if the tool should analyze a doppelganger/proxy mesh for each cluster of triangles whose combinatorial analysis according to has_object showed that the object is not a closed polyhedron. Such proxies are closed via iterative hole-filling, mesh refinement, and fairing operations. Users should be aware that the resulting mesh does not necessarily represent the original precipitate. In most cases objects, like precipitates in atom probe end up as open objects because they have been clipped by the edge of the dataset. Using a proxy is then a strategy to still be able to account for these objects. Nevertheless users should make themselves familiar with the potential consequences and biases which this can introduce into the analysis. Like has_object_geometry but for the proxies. Like has_object_properties but for the proxies. Like has_object_obb but for the proxies. Like has_object_ions but for the proxies. Like has_object_edge_contact but for the proxies. Specifies if the tool should report for each closed object a (cylindrical) region of interest placed, centered, and align with the local normal for each triangle of the object. Specifies if the tool should report for each ROI that was placed at a triangle of each object if this ROI intersects the edge of the dataset. Currently paraprobe-nanochem supports cylindrical ROIs. A possible intersection of these with the edge of the dataset, i.e. the triangulated surface mesh model for the edge is performed. This test checks if the cylinder intersects with a triangle of the surface mesh. If this is the case, the ROI is assumed to make edge contact, else, the ROI is assumed to have no edge contact. This approach does not work if the ROI would be completely outside the dataset. Also in this case there would be no intersection. For atom probe this case is practically irrelevant because for such a ROI there would also be no ion laying inside the ROI. Clearly it has thus to be assumed that the edge model culls the entire dataset. Instead, if one would cut a portion of the dataset, compute an edge model for this point cloud, it might make sense to place a ROI but in this case the edge contact detection is not expected to work properly. Analyses of interfacial excess. Interfacial excess computations are performed for local regions-of-interests (ROIs) at selected facets or interface patch. For instance many scientist compute the interfacial excess for selected triangle facets of a created iso-surface. In this case, computed iso-surfaces of paraprobe could be used. An example are triangle facet sets about closed polyhedra, for instance to compute interfacial excess related to phase boundaries of second-phase precipitates. Another example are free-standing triangle patches of the iso- surfaces which paraprobe creates. These could be characterized for interfacial excess. The sub-routines during iso-surface computations already include a procedure to automatically align local triangle normals based on the gradients of e.g. composition fields. In this case, these triangulated surface patches could also be used as a source for computing interfacial excess. Often scientists face situations, though, in which there is no immediately evident composition gradient across the interface (grain or phase boundary) and orientation information about the adjoining crystal is neither available nor reliable enough. In this case `P. Felfer et al. <https://doi.org/10.1016/j.ultramic.2015.06.002>`_ proposed a method to manually place control points and run an automated tessellation-based algorithm to create a triangulated surface patch, i.e. a model of the location of the interface. In a post-processing step this triangle set can then be used to compute again interfacial excess in an automated manner by placing ROIs and aligning them with consistently precomputed triangle normals. A similar use case is conceptually the one proposed by `X. Zhou et al. <https://doi.org/10.1016/j.actamat.2022.117633>`_ They used first a deep-learning method to locate planar triangulated grain boundary patches. These are eventually processed further with manual editing of the mesh via tools like Blender. Once the user is satisfied with the mesh, the computations of interfacial excess reduce again to an automated placing of ROIs, computations of the distributing of ions to respective ROIs and reporting the findings via plotting. Yet another approach for constructing an triangulated surface patch of an interface is to use point cloud processing methods which have been proposed in the laser-scanning, geoinformatics, and CAD community. Different computational geometry methods are available for fitting a parameterized surface to a set of points, using e.g. non-uniform rational B-splines (NURBS) and triangulating these according to prescribed mesh quality demands. The advantage of these methods is that they can be automated and pick up curved interface segments. The disadvantage is their often strong sensitivity to parameterization. As a result also such methods can be post-processed to yield a triangulated surface patch, and thus enable to run again automated ROI placement methods. For example like these which were explored for the use case of iso-surfaces with closed objects and free-standing surface patches that delineate regions of the dataset with a pronounced composition gradient normal to the interface. This summary of the situations which atom probers can face when requesting for interfacial excess computations, substantiates there exists a common set of settings which can describe all of these methods and, specifically, as here exemplified, the automated placing and alignment functionalities for ROIs that is an important step all these workflows. Specifically, paraprobe-nanochem operates on an already existent triangle set. The interface model is the result of a previous (set of) processing steps as a result of which the user has created a triangulated surface mesh (or a set of, eventually connected such meshes). These interface models are useful, if not required, in cases when there is no other independent approach to locate an interface. These are cases when insufficient crystallographic latent information is available and also no consistent concentration gradient detectable across the interface. It is then the users' responsibility to deliver a triangle mesh of the interface model. Filename to HDF5 file which contain vertex coordinates, facet indices, facet unit normals. The user is responsible for the triangle and winding order to be consistent. Input is expected as a matrix of the coordinates for all disjoint vertices, a (Nvertices, 3)-shaped array of NX_FLOAT. Input is expected to include also a matrix of facet indices referring to these disjoint vertices. This matrix should be a (Nfacets, 3)-shaped array of NX_UINT. Further required input is a (Nfacets, 3)-shaped array of NX_FLOAT signed facet unit normals and a (Nvertices, 3)-shaped array of NX_FLOAT signed vertex unit normals. Vertex indices need to start at zero and must not exceed Nvertices - 1, i.e. the identifier_offset is 0 and facet indices are indexed implicitly, i.e. [0, Nvertices-1]. Version identifier of the file such as a secure hash which documents the binary state of the file to add an additional layer of reproducibility from which file specifically contains these data. Absolute HDF5 path to the dataset which specifies the array of vertex positions. Absolute HDF5 path to the dataset which specifies the array of facet indices. Absolute HDF5 path to the dataset which specifies the array of facet signed unit normals. Absolute HDF5 path to the dataset which specifies the array of vertex signed unit normals. Users should be aware that triangulated surface meshes are only approximations to a given complex, eventually curved shape. Consequently, computations of normals show differences between the vertex and facet normals. Vertex normals have to be interpolated from normals of neighboring facets. Consequently, these normals are affected by the underlying parameterization and curvature estimation algorithms, irrespective of how contributions from neighboring facets are weighted. By contrast, facet normals are clearly defined by the associated triangle. Their disadvantage is that they the normal field has discontinuities at the edges. In general the coarser an object is triangulated the more significant the difference becomes between computations based on facet or vertex normals. Paraprobe-nanochem works with facet normals as it can use parts of the numerical performance gained by using cutting edge libraries to work rather with finer meshes. Create a simple principle component analysis (PCA) to mesh a free-standing interface patch through a point cloud of decorating solutes. These models can be useful for quantification of Gibbsian interfacial excess for interfaces where iso-surface based methods may fail or closed objects from iso-surfaces are not desired or when e.g. there are no substantial or consistently oriented concentration gradients across the interface patch. The interface_meshing functionality of paraprobe-nanochem can be useful when there is also insufficient latent crystallographic information available that could otherwise support modelling the interface, via e.g. ion density traces in field-desorption maps, as were used and discussed by `Y. Wei et al. <https://doi.org/10.1371/journal.pone.0225041>`_ or are discussed by `A. Breen et al. <https://github.com/breen-aj/detector>`_ It is noteworthy that the method here used is conceptually very similar in implementation to the work by `Z. Peng et al. <https://doi.org/10.1017/S1431927618016112>`_ Noteworthy, her team uses the DCOM approach originally proposed by P. Felfer et al. However, both of these previous works neither discuss in detail nor implement inspection functionalities which enable a detection of potential geometric inconsistencies or self-interactions of the resulting DCOM mesh. This is what paraprobe-nanochem implements via the Computational Geometry Algorithms Library. Method how to initialize the PCA: * default, means based on segregated solutes in the ROI * control_point_file, means based on reading an external list of control points, currently coming from the Leoben APT_Analyzer. The control_point_file is currently expected with a specific format. The Leoben group lead by L. Romaner has developed a GUI tool `A. Reichmann et al. <https://github.com/areichm/APT_analyzer>`_ to create a control_point_file which can be parsed by paraprobe-parmsetup to match the here required formatting in control_points. The name of the control point file to use. Version identifier of the file such as a secure hash which documents the binary state of the file to add an additional layer of reproducibility from which file specifically contains these data. X, Y, Z coordinates of disjoint control point read from an HDF5 file named according to control_point_file. Method used for identifying and refining the location of the interface. Currently, paraprobe-nanochem implements a PCA followed by an iterative loop of isotropic mesh refinement and DCOM step(s), paired with self-intersection detection in a more robust implementation. Specify the types of those ions which decorate the interface and can thus be assumed as markers for locating the interface and refining its local curvature. Array of iontypes to filter. The list is interpreted as a whitelist, i.e. ions of these types are considered the decorating species (solutes). How many times should the DCOM and mesh refinement be applied? Array of decreasing positive not smaller than one nanometer real values which specify how the initial triangles of the mesh should be iteratively refined by edge splitting and related mesh refinement operations. Array of decreasing positive not smaller than one nanometer real values which specify the radius of the spherical region of interest within which the DCOM algorithm decides for each vertex how the vertex will be eventually relocated. The larger the DCOM radius is relative to the target_edge_length the more likely it is that vertices will be relocated so substantially that eventually triangle self-intersections can occur. If the code detects these it warns and stops in a controlled manner so that the user can repeat the analyses with a smaller value. Array of integers which specify for each DCOM step how many times the mesh should be iteratively smoothened. Users should be aware the three array target_edge_length, target_dcom_radius, and target_smoothing_step are interpreted in the same sequence, i.e. the zeroth entry of each array specifies the values to be used in the first DCOM iteration. The first entry of each array those for the second DCOM iteration and so on and so forth. Functionalities for placing regions-of-interest (ROIs) in the dataset or at specific microstructural features to characterize composition profiles and cumulated profiles for quantification of interfacial excess. Paraprobe-nanochem currently places cylindrical ROIs. ROIs are probed across the triangulated surface of a user-defined mesh. ROIs are placed at the barycenter of the triangular facet. The tool can be instructed to orient the profile for each ROIs with the positive normal of the triangle facet normals. Profiles are computed for each ROI and facet triangle. The code will test which ROIs are completely embedded in the dataset. Specifically, in this test the tool evaluates if the ROI cuts at least one triangle of the triangulated surface mesh of the edge of the dataset. If this is the case the ROI will be considered close to the edge (of the dataset) and not analyzed further; else the ROI will be processed further. Users should be aware that the latter intersection analysis is strictly speaking not a volumetric intersection analysis as such one is much more involved because the edge model can be a closed non-convex polyhedron in which case one would have to test robustly if the cylinder pierces or is laying completely inside the polyhedron. For this the polyhedron has to be tessellated into convex polyhedra as otherwise tests like the Gilbert-Johnson-Keerthi algorithm would not be applicable. Specifically, the tool computes atomically decomposed profiles. This means molecular ions are split into atoms/isotopes with respective multiplicity. As an example an H3O+ molecular ion contains three hydrogen and one oxygen atom respectively. The tool then evaluates how many ions are located inside the ROI or on the surface of the ROI respectively. All atom types and the unranged ions are distinguished. As a result, the analyses yield for each ROI a set of sorted lists of signed distance values. Currently, the distance is the projected distance of the ion position to the barycenter of the triangle and triangle plane. This will return a one-dimensional profile. Post-processing the set of atom-type-specific profiles into cumulated profiles enable the classical Krakauer/Seidman-style interfacial excess analyses. Furthermore, the tool can be instructed to compute for each (or a selected sub-set of facet) a set of differently oriented profiles. The feature mesh enables the injection of previously computed triangle soup or mesh data. Such a mesh can be the model for a grain- or phase boundary patch (from e.g. interface_meshing) jobs. Name of the HDF5 file which contains vertex coordinates and facet indices to describe the desired set of triangles which represents the feature. Version identifier of the file such as a secure hash which documents the binary state of the file to add an additional layer of reproducibility from which file specifically contains these data. Absolute path to the HDF5 dataset in the respectively specified HDF5 file under filename which details the array of vertex positions. Absolute path to the HDF5 dataset in the respective specified HDF5 file under filename which details the array of facet indices. Absolute path to the HDF5 dataset in the respective specified HDF5 file under filename which details consistently oriented facet normals of the facets. The tool enables to inject precomputed distance information for each point which can be used for further post-processing and analysis. Name of an HDF5 file which contains ion distances. Version identifier of the file such as a secure hash which documents the binary state of the file to add an additional layer of reproducibility from which file specifically contains these data. Absolute HDF5 path to the dataset with distance values for each ion. Which type of distance should be reported for the profile. In which directions should the tool probe for each ROI. For each ROI, how high (projected on the cylinder axis) should the cylindrical ROI be. For each ROI, how wide (radius) should the cylindrical ROI be. ././@PaxHeader0000000000000000000000000000023500000000000010215 xustar00118 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_ranger.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_ranger.0000644000077000000000000003653714777236751033032 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The number of isotopes to consider as building blocks for searching molecular ions. The number of compositions to consider for molecular ion search tasks. Configuration of a paraprobe-ranger tool run in atom probe microscopy. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ever persistent resources where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable in the same deterministic manner. ISO 8601 formatted time code with local time zone offset to UTC information included when this configuration file was created. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. How many task to perform? A list of pairs of number of protons and either the value 0 (per row) or the mass number for all those isotopes which are assumed present in a virtual specimen. The purpose of this field is to compute also composition-weighted products to yield a simple estimation which could potentially help scientists to judge if certain molecular ions are to be expected. The corresponding setting store_composition_weighted_product should be activated. A list of pairs of number of protons and mass number for all isotopes to consider that can be composed into (molecular) ions, during the recursive molecular_ion_search. The mass-to-charge-state ratio interval in which all molecular ions are searched. The maximum charge that a molecular ion should have. The maximum number of isotopes of which the molecular ion should be composed. Currently this must not be larger than 32. Users should be warned that the larger the maximum_charge and especially the larger the maximum_number_of_isotopes is chosen, the eventually orders of magnitude more costly the search becomes. This is because paraprobe-ranger computes really all (at least) theoretically possible combinations that would have likely a mass-to-charge-state ratio in the specified mass_to_charge_interval. It is the challenge in atom probe to judge which of these (molecular) ions are feasible and also practically possible. This tool does not answer this question. Namely, which specific molecular ion will evaporate, remain stable during flight and becomes detected is a complicated and in many cases not yet in detail understood phenomenon. The ab-initio conditions before and during launch, the local environment, arrangement and field as well as the flight phase in an evacuated but not analysis chamber with a complex electrical field, eventual laser pulsing in place, temperature and remaining atoms or molecules all can have an effect which iontypes are really physically evaporating and detected. Report the accumulated atomic mass from each isotope building the ion. Accounts for each identified ion. Relatistic effects are not accounted for. Report the product of the natural abundances from each isotope building the ion. Accounts for each identified ion. The value zero indicates it is not possible to build such molecular ion from nuclids which are all observationally stable. Very small values can give an idea/about how likely such a molecular ion is expected to form assuming equal probabilities. However in atom probe experiments this product has to be modified by the (spatially-correlated) local composition in the region from which the ions launch because the formation of a molecular ion depends as summarized under maximum_number_of_isotopes on the specific quantum-mechanical configuration and field state upon launch or/and (early state) of flight respectively. We are aware that this modified product can have a substantially different value than the natural_abundance_product. Natural abundancies folded with the estimated compositions of the specimen can differ by orders of magnitude. Report the charge state of the ions. Report if identified ions should be characterized wrt to their number of disjoint isotopes. ././@PaxHeader0000000000000000000000000000023700000000000010217 xustar00120 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_selector.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_selecto0000644000077000000000000001501714777236751033122 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Configuration of a paraprobe-selector tool run in atom probe microscopy. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ever persistent resources where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable in the same deterministic manner. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. ISO 8601 formatted time code with local time zone offset to UTC information included when this configuration file was created. How many roi_selection processes should the tool execute. This process identifies which of the points/ions in the datasets are inside or on the surface of geometric primitives and meet optionally specific other filtering constraints. A typical use case of a roi_selection is to restrict analyses to specific regions of the dataset, eventually regions with a complicated shape. ././@PaxHeader0000000000000000000000000000023700000000000010217 xustar00120 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_spatstat.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_spatsta0000644000077000000000000004761414777236751033153 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Maximum number of atoms per molecular ion. Should be 32 for paraprobe. Number of different sources iontypes to distinguish. Number of different target iontypes to distinguish. Configuration of a paraprobe-spatstat tool run in atom probe microscopy. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ever persistent resources where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable in the same deterministic manner. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. ISO 8601 formatted time code with local time zone offset to UTC information included when this configuration file was created. How many range_with_existent_iontypes processes should the tool execute as part of the analysis. The tool enables to inject precomputed distances of each ion to a representation of the edge of the dataset which can be used to control and substantially reduce edge effects when computing spatial statistics. Name of an HDF5 file which contains ion-to-edge distances. Absolute HDF5 path to the dataset with the ion-to-edge distance values for each ion. The shape of the distance values has to match the length of the ion positions array in dataset/dataset_name_reconstruction and dataset_name_mass_to_charge respectively. Threshold to define how large an ion has to lay at least far away from the edge of the dataset so that the ion can act as a source, i.e. that an ROI is placed at the location of the ion and its neighbors are analyzed how they contribute to the computed statistics. The ion_to_edge_distances threshold can be combined with a threshold for the ion_to_feature_distances. Specifically, if ion_to_feature_distances are loaded an ion only acts as a source if both threshold criteria are met. The threshold is useful to process the dataset such that ROIs do not protrude out of the dataset as this would add bias. In addition to spatial filtering, and considering how far ions lie to the edge of the dataset, it is possible to restrict the analyses to a sub-set of ions within a distance not farther away to a feature than a threshold value. Name of an HDF5 file which contains ion-to-feature distances. Absolute HDF5 path to the dataset with the ion-to-feature distance values for each ion. Threshold to define how close an ion has to lay to a feature so that the ion can at all qualify as a source, i.e. that an ROI is placed at the location of the ion and its neighbors are then analyzed how they contribute to the computed statistics. Recall that the ion_to_feature_distances threshold is combined with the ion_to_edge_distances threshold. Specifies if the iontypes are randomized for the point cloud or not. Internally paraprobe uses a sequentially executed deterministic MT19987 (MersenneTwister) pseudo-random number generator to shuffle the iontype labels randomly across the entire set of ions. How should the iontype be interpreted on the source-side, i.e. all these ion positions where a regions-of-interest (ROI) around so-called source ions will be placed. Different options exist how iontypes are interpreted given an iontype represents in general a (molecular) ion with different isotopes that have individually different multiplicity. The value resolve_all will set an ion active in the analysis regardless of which iontype it is. Each active ion is accounted for once. The value resolve_unknown will set an ion active when the ion is of the UNKNOWNTYPE type. Each active ion is accounted for once. The value resolve_ion will set an ion active if it is of the specific iontype, irregardless of its elemental or isotopic details. Each active ion is counted once. The value resolve_element will set an ion active, and most importantly, account for each as many times as the (molecular) ion contains atoms of elements in the whitelist ion_query_isotope_vector. The value resolve_isotope will set an ion active, and most importantly, account for each as many times as the (molecular) ion contains isotopes in the whitelist ion_query_isotope_vector. In effect, ion_query_isotope_vector acts as a whitelist to filter which ions are considered as source ions of the correlation statistics and how the multiplicity of each ion will be factorized, i.e. how often it is accounted for. Matrix of isotope vectors, as many as rows as different candidates for iontypes should be distinguished as possible source iontypes. In the simplest case, the matrix contains only the proton number of the element in the row, all other values set to zero. Combined with ion_query_type_source set to resolve_element this will recover usual spatial correlation statistics like the 1NN C-C spatial statistics. Similarly as ion_query_type_source how should iontypes be interpreted on the target-side, i.e. how many counts will be bookkept for ions which are neighbors of source ions within or on the surface of each inspection/ROI about each source ion. Source ion in the center of the ROI are not accounted for during counting the summary statistics. For details about the resolve values consider the explanations in ion_query_type_source. These account for ion_query_type_target as well. Matrix of isotope vectors, as many as rows as different candidates for iontypes to distinguish as possible targets. See additional comments under ion_query_isotope_vector_source. Specifies which spatial statistics to compute. Compute k-th nearest neighbour statistics. Order k. Minimum value, increment, and maximum value of the histogram binning. Compute radial distribution function. Minimum value, increment, and maximum value of the histogram binning. ././@PaxHeader0000000000000000000000000000023700000000000010217 xustar00120 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_surfacer.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_surface0000644000077000000000000003476514777236751033127 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Number of alpha values (and offset values) to probe. How many different match values does the filter specify. Configuration of a paraprobe-surfacer tool run in atom probe microscopy. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ever persistent resources where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable in the same deterministic manner. ISO 8601 formatted time code with local time zone offset to UTC information included when this configuration file was created. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. For now a support field for the tool to identify how many individual analyses the tool should executed as part of the analysis. Specifies the method that is used to preprocess the point cloud. The main purpose of this setting is to specify whether the point cloud should be segmented or not during the preprocessing to identify which points are more likely lying close to the edge of the point cloud. These points could be more relevant than the interior points for certain alpha-shape constructions. By default no such filtering is used during pre-processing. By contrast, the option kuehbach activates a preprocessing during which a Hoshen-Kopelman percolation analysis is used to identify which points are closer to the edge of the dataset. This can reduce the number of points in the alpha-shape computation and thus improve performance substantially. Details about the methods are reported in `M. Kühbach et al. <https://doi.org/10.1038/s41524-020-00486-1>`_. When using the kuehbach preprocessing, this is the width of the kernel for identifying which ions are in voxels close to the edge of the point cloud. Specifies which method to use to define the alpha value. The value convex_hull_naive is the default. This instructs the tool to use a fast specialized algorithm for computing only the convex hull. The resulting triangles can be skinny. The value convex_hull_refine computes first also a convex_hull_naive but refines the mesh by triangle flipping and splitting to improve the quality of the mesh. The value smallest_solid instructs the CGAL library to choose a value which realizes an alpha-shape that is the smallest solid. The value cgal_optimal instructs the library to choose a value which the library considers as an optimal value. Details are define in the respective section of the CGAL library on 3D alpha shapes. The value set_of_values instructs to compute a list of alpha-shapes for the specified alpha-values. The value set_of_alpha_wrappings instructs the library to generate a set of so-called alpha wrappings. These are a method which is similar to alpha shapes but provide additional guarantees though such as watertightness and proximity constraints on the resulting wrapping. Array of alpha values to use when alpha_value_choice is set_of_values or when alpha_value_choice is set_of_alpha_wrappings. Array of offset values to use when alpha_value_choice is set_of_alpha_wrappings. The array of alpha_values and offset_values define a sequence of (alpha and offset value). Specifies if the tool should compute the set of exterior triangle facets for each alpha complex (for convex hull, alpha shapes, and wrappings) Specifies if the tool should check if the alpha complex of exterior triangular facets is a closed polyhedron. Specifies if the tool should compute all interior tetrahedra of the alpha complex (currently only for alpha shapes). ././@PaxHeader0000000000000000000000000000024200000000000010213 xustar00123 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_tessellator.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_tessell0000644000077000000000000003042214777236751033134 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Configuration of a paraprobe-tessellator tool run in atom probe microscopy. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ever persistent resources where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable in the same deterministic manner. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. ISO 8601 formatted time code with local time zone offset to UTC information included when this configuration file was created. How many individual analyses should the tool execute. The tool enables to inject precomputed distance information for each point which can be used for further post-processing and analysis. Name of an HDF5 file which contains the ion distances. Users are responsible this file and referred to dataset under dataset_name have an ion_distance value for each ion. Version identifier of the file such as a secure hash which documents the binary state of the file to add an additional layer of reproducibility. Absolute HDF5 path to the dataset with distance values for each ion. Specifies for which points the tool will compute the tessellation. By default, a Voronoi tessellation is computed for all ions in the filtered point cloud. Specifies if the tool should report the volume of each cell. Specifies if the tool should report the first-order neighbors of each cell. Specifies if the tool should report the facets and vertices of each cell. Specifies if the tool should report if the cell makes contact with the tight axis-aligned bounding box about the point cloud. This can be used to identify if the shape of the cell is affected by the edge of the dataset or if cells are deeply enough embedded into the point cloud so that the shape of their cells are not affected by the presence of the boundary. ././@PaxHeader0000000000000000000000000000024100000000000010212 xustar00122 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_transcoder.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_transco0000644000077000000000000001253114777236751033133 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Configurations of a paraprobe-transcoder tool run in atom probe microscopy. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ideally an ever persistent resource where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable deterministically. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. ISO 8601 formatted time code with local time zone offset to UTC information included when this configuration file was created. The path and name of the file (technology partner or community format) from which to read the reconstructed ion positions. Currently, POS, ePOS, APT files from APSuite, and NXS, i.e. NeXus/HDF5 files are supported. The path and name of the file (technology partner or community format from which to read the ranging definitions, i.e. how to map mass-to- charge-state ratios on iontypes. Currently, RRNG, RNG, and NXS, i.e. NeXus/HDF5 files are supported. ././@PaxHeader0000000000000000000000000000024100000000000010212 xustar00122 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_clusterer.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_cluste0000644000077000000000000006103314777236751033216 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The total number of ions in the reconstruction. The total number of entries in the restricted_identifier dictionary. Results of a paraprobe-clusterer tool run. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ever persistent resources where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable in the same deterministic manner. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file was started, i.e. the paraprobe-tool executable started as a process. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file were completed and the paraprobe-tool executable exited as a process. The absolute path and name of the config file for this analysis. At least SHA256 strong hash of the specific config_file for tracking provenance. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. A statement whether the paraprobe-tool executable managed to process the analysis or failed prematurely. This status is written to the results file after the end_time at which point the executable must no longer compute analyses. Only when this status message is present and shows `success`, the user should consider the results. In all other cases, it might be that the executable has terminated prematurely or another error occurred. If used, contact information and eventually details of at least the person who performed this analysis. Details about the coordinate system conventions used. If nothing else is specified we assume that there has to be at least one set of NXtransformations named paraprobe defined, which specifies the coordinate system. In which all positions are defined. The individual coordinate systems which should be used. Field names should be prefixed with the following controlled terms indicating which individual coordinate system is described: * paraprobe * lab * specimen * laser * leap * detector * recon A bitmask which identifies which of the ions in the dataset were analyzed during this process. Number of ions covered by the mask. The mask value for most may be 0. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The unsigned integer array representing the content of the mask. If padding is used, padded bits are set to 0. The mask is for convenience always as large as the entire dataset as it will be stored compressed anyway. The convenience feature with this is that then the mask can be decoded with numpy and mirrored against the evaporation_id array and one immediately can filter out all points that were used by the paraprobe-toolbox executable. The length of the array adds to the next unsigned integer if the number of ions in the dataset is not an integer multiple of the bitdepth (padding). The result of a cluster analyses. These include typically the label for each ion/point documenting to which feature (if any) an ion is assigned. Typically, each analysis/run yields only a single cluster. In cases of fuzzy clustering it can be possible that an ion is assigned to multiple cluster (eventually with different) weight/probability. Results of a DBScan clustering analysis. The epsilon (eps) parameter. The minimum points (min_pts) parameter. Number of members in the set which is partitioned into features. Specifically, this is the total number of targets filtered from the dataset. Cardinality here is not the total number of ions in the dataset. Which identifier is the first to be used to label a cluster. The value should be chosen in such a way that special values can be resolved: * identifier_offset-1 indicates an object belongs to no cluster. * identifier_offset-2 indicates an object belongs to the noise category. Setting for instance identifier_offset to 1 recovers the commonly used case that objects of the noise category get values to -1 and unassigned points to 0. Numerical identifier have to be strictly increasing. The evaporation sequence identifier to figure out which ions from the reconstruction were considered targets. The raw labels from the DBScan clustering backend process. The raw array of core sample indices which specify which of the targets are core points. Matrix of numerical label for each member in the set. For classical clustering algorithms this can for instance encode the cluster_identifier. The array of weight which specifies how surely/likely the cluster is associated/assigned to a specific identifier as is specified in the cluster_identifier array. For the DBScan and atom probe tomography the multiplicity of each ion with respect to the cluster. That is how many times should the position of the ion be accounted for because the ion is e.g. a molecular ion with several elements or isotope of requested type. Optional bitmask encoding if members of the set are assigned to as noise or not. Optional bitmask encoding if member of the set are a core point. For details to which feature/cluster an ion/point is a core point consider numerical_label. In addition to the detailed storage which members was grouped to which feature/group summary statistics are stored under this group. Total number of members in the set which are categorized as noise. Total number of members in the set which are categorized as a core point. Total number of clusters (excluding noise and unassigned). Array of numerical identifier of each feature (cluster). Array of number of members for each feature. Specify if it was different from the number_of_processes in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. ././@PaxHeader0000000000000000000000000000024100000000000010212 xustar00122 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_distancer.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_distan0000644000077000000000000004630514777236751033206 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The total number of ions in the reconstruction. The total number of triangles in the set. Results of a paraprobe-distancer tool run. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ever persistent resources where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable in the same deterministic manner. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file was started, i.e. the paraprobe-tool executable started as a process. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file were completed and the paraprobe-tool executable exited as a process. The absolute path and name of the config file for this analysis. At least SHA256 strong hash of the specific config_file for tracking provenance. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. A statement whether the paraprobe-tool executable managed to process the analysis or failed prematurely. This status is written to the results file after the end_time at which point the executable must not compute any analysis. Only when this status message is present and shows `success`, the user should consider the results. In all other cases it might be that the executable has terminated prematurely or another error occurred. If used, contact information and eventually details of at least the person who performed this analysis. Details about the coordinate system conventions used. The individual coordinate systems which should be used. Field names should be prefixed with the following controlled terms indicating which individual coordinate system is described: * paraprobe * lab * specimen * laser * leap * detector * recon The tool can be used to compute the analytical distance of each ion to a set of triangles. A bitmask which identifies which of the ions in the dataset were analyzed. Number of ions covered by the mask. The mask value for most may be 0. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The unsigned integer array representing the content of the mask. If padding is used the padded bits are set to 0. The mask is for convenience always as large as the entire dataset as it will be stored compressed anyway. The convenience feature with this is that then the mask can be decoded with numpy and mirrored against the evaporation_id array and one immediately can filter out all points that were used by the paraprobe. The length of the array adds to the next unsigned integer if the number of ions in the dataset is not an integer multiple of the bitdepth. A bitmask which identifies which of the triangles in the set were considered. Usually these are all but sometimes users may wish to filter certain portions of the triangles out. If window_triangles is not provided it means that all triangles were taken. Number of triangles covered by the mask. The mask value for most may be 0. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The unsigned integer array representing the content of the mask. If padding is used the padded bits are set to 0. The mask is for convenience always as large as the entire dataset as it will be stored compressed anyway. The convenience feature with this is that then the mask can be decoded with numpy and mirrored against the evaporation_id array and one immediately can filter out all points that were used by the paraprobe. The length of the array adds to the next unsigned integer if the number of ions in the dataset is not an integer multiple of the bitdepth. The closest analytical distance of the ions to their respectively closest triangle from the triangle set. A bitmask which identifies which of the distance values can be assumed to have a consistent sign because the closest triangle had a consistent outer unit normal defined. For points whose bit is set 0 the distance is correct but the sign is not reliable. Number of triangles covered by the mask. The mask value for most may be 0. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The unsigned integer array representing the content of the mask. If padding is used the padded bits are set to 0. The identifier of the triangle that is closest for each ion. A support field to visualize each ion and with this the distance informations using XDMF and e.g. Paraview. Specify if it was different from the number_of_processes in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. ././@PaxHeader0000000000000000000000000000024300000000000010214 xustar00124 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_intersector.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_inters0000644000077000000000000004767114777236751033237 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The total number of links pointing from current to next. The total number of links pointing from next to current. The total number of members in the current_set. The total number of members in the next_set. The total number of cluster found for coprecipitation analysis. The number of rows in the table/matrix for coprecipitation stats. Results of a paraprobe-intersector tool run. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ever persistent resources where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable in the same deterministic manner. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file was started, i.e. the paraprobe-tool executable started as a process. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file were completed and the paraprobe-tool executable exited as a process. The absolute path and name of the config file for this analysis. At least SHA256 strong hash of the specific config_file for tracking provenance. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. If used, contact information and eventually details of at least the person who performed this analysis. Details about the coordinate system conventions used. The individual coordinate systems which should be used. Field names should be prefixed with the following controlled terms indicating which individual coordinate system is described: * paraprobe * lab * specimen * laser * leap * detector * recon The results of an overlap/intersection analysis. A matrix of feature_identifier which specifies which named features from the current set have directed link(s) pointing to which named feature(s) from the next set. For each link/pair in current_to_next a characterization whether the link is due to a volumetric overlap (0x00 == 0), proximity (0x01 == 1), or something else unknown (0xFF == 255). A matrix of feature_identifier which specifies which named feature(s) from the next set have directed link(s) pointing to which named feature(s) from the current set. Only if the mapping whereby the links is symmetric next_to_current maps the links in current_to_next in the opposite direction. For each link/pair in next_to_current a characterization whether the link is due to a volumetric overlap (0x00 == 0), proximity (0x01 == 1), or something else unknown (0xFF == 255). For each pair of links in current_to_next the volume of the intersection, i.e. how much volume do the two features share. If features do not intersect the volume is zero. During coprecipitation analysis the current and next set are analyzed for links in a special way. Three set comparisons are made. Members of the set in each comparison are analyzed for overlap and proximity: The first comparison is the current_set against the current_set. The second comparison is the next_set against the next_set. The third comparison is the current_set against the next_set. Once the (forward) links for these comparisons are ready the pair relations are analyzed with respect to which feature identifier cluster in identifier space. Thereby a logical connection (link) is established between the features in the current_set and next_set. Recall that these two set typically represent different features within an observed system for otherwise the same parameterization. Examples include two sets of e.g. precipitates with differing chemical composition that were characterized in the same material volume representing a snapshot of an e.g. microstructure at the same point in time. Researchers may have performed two analyses, one to characterize precipitates A and another one to characterize percipitates B. Coprecipitation analysis now logically connects these independent characterization results to establish spatial correlations of e.g. precipitates spatial arrangement. Matrix of feature_identifier and cluster_identifier pairs which encodes the cluster to which each feature_identifier was assigned. Here for features of the current_set. Matrix of feature_identifier and cluster_identifier pairs which encodes the cluster to which each feature_identifier was assigned. Here for features of the next_set. The identifier (names) of the cluster. Pivot table as a matrix. The first column encodes how many members from the current_set are in each cluster, one row per cluster. The second column encodes how many members from the next_set are in each cluster, in the same row per cluster respectively. The last column encodes the total number of members in the cluster. Pivot table as a matrix. The first column encodes the different types of clusters based on their number of members in the sub-graph. The second column encodes how many clusters with as many members exist. Specify if it was different from the number_of_processes in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. ././@PaxHeader0000000000000000000000000000024000000000000010211 xustar00121 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_nanochem.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_nanoch0000644000077000000000000036160414777236751033174 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The total number of ions in the reconstruction. The total number of atoms in the atomic_decomposition match filter. The total number of isotopes in the isotopic_decomposition match filter. The dimensionality of the delocalization grid. The cardinality/total number of cells/grid points in the delocalization grid. The total number of XDMF values to represent all faces of triangles via XDMF. The total number of entries in a feature dictionary. The total number of member distinguished when reporting composition. Results of a paraprobe-nanochem tool run. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ever persistent resources where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable in the same deterministic manner. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file was started, i.e. the paraprobe-tool executable started as a process. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file were completed and the paraprobe-tool executable exited as a process. The absolute path and name of the config file for this analysis. At least SHA256 strong hash of the specific config_file for tracking provenance. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. A statement whether the paraprobe-tool executable managed to process the analysis or failed prematurely. This status is written to the results file after the end_time at which point the executable must no longer compute analyses. Only when this status message is present and shows `success`, the user should consider the results. In all other cases, it might be that the executable has terminated prematurely or another error occurred. If used, contact information and eventually details of at least the person who performed this analysis. Details about the coordinate system conventions used. If nothing else is specified we assume that there has to be at least one set of NXtransformations named paraprobe defined, which specifies the coordinate system. In which all positions are defined. The individual coordinate systems which should be used. Field names should be prefixed with the following controlled terms indicating which individual coordinate system is described: * paraprobe * lab * specimen * laser * leap * detector * recon A bitmask which identifies which of the ions in the dataset were analyzed during this process. Number of ions covered by the mask. The mask value for most may be 0. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The unsigned integer array representing the content of the mask. If padding is used, padded bits are set to 0. The mask is for convenience always as large as the entire dataset as it will be stored compressed anyway. The convenience feature with this is that then the mask can be decoded with numpy and mirrored against the evaporation_id array and one immediately can filter out all points that were used by the paraprobe-toolbox executable. The length of the array adds to the next unsigned integer if the number of ions in the dataset is not an integer multiple of the bitdepth (padding). The weighting model specifies how mark data are mapped to a weight per point/ion. For atom probe microscopy (APM) mark data are e.g. which iontype an ion has. As an example, different models are used which account differently for the multiplicity of a point/ion during delocalization: * unity, all points/ions get the same weight 1. * atomic_decomposition, points get as much weight as they have atoms of a type in atomic_decomposition_rule, * isotope_decomposition, points get as much weight as they have isotopes of a type in isotopic_decomposition_rule. A list of elements (via proton number) to consider for the atomic_decomposition weighting model. Elements must exist in the periodic table of elements and be specified by their number of protons. Values in match are isotope hash values using the following hashing rule $H = Z + 256*N$ with $Z$ the number of protons and $N$ the number of neutrons of the isotope. In the case of elements this hashing rule has the advantage that for elements the proton number is their hash value because N is zero. Meaning of the filter: Whitelist specifies which entries with said value to include. Entries with all other values will be filtered out. Blacklist specifies which entries with said value to exclude. Entries with all other values will be included. Array of values to filter according to method. For example, if the filter specifies [1, 5, 6] and method is whitelist, only entries with values matching 1, 5 or 6 will be processed. All other entries will be filtered out/not considered. A list of isotopes (via proton and neutron number) to consider for the isotopic_decomposition weighting model. Isotopes must exist in the nuclid table. Values in match are isotope hash values using the following hashing rule $H = Z + 256*N$ with $Z$ the number of protons and $N$ the number of neutrons of the isotope. Meaning of the filter: Whitelist specifies which entries with said value to include. Entries with all other values will be filtered out. Blacklist specifies which entries with said value to exclude. Entries with all other values will be included. Array of values to filter according to method. For example, if the filter specifies [1, 5, 6] and method is whitelist, only entries with values matching 1, 5 or 6 will be processed. All other entries will be filtered out/not considered. How results of the kernel-density estimation were computed into quantities. By default the tool computes the total number (intensity) of ions or elements. Alternatively the tool can compute the total intensity, the composition, or the concentration of the ions/elements specified by the white list of elements in each voxel. Weighting factor, in atom probe, often termed multiplicity. The weighting factor is the multiplier with which the integrated intensity contribution from the point/ion gets multiplied. The delocalization computes the integrated intensity for each grid cell. Effectively, this is an explicitly evaluated kernel method where each specific position of an ion is replaced by a smoothing kernel. For atom probe weights are positive and integer specifically the multiplicity of the ion, in accordance with the respective rulesets as defined by weighting_model. The discretized domain/grid on which the delocalization is applied. The total number of cells/voxels of the grid. The symmetry of the lattice defining the shape of the unit cell. The unit cell dimensions according to the coordinate system defined under coordinate_system. Number of unit cells along each of the d unit vectors. The total number of cells, or grid points has to be the cardinality. If the grid has an irregular number of grid positions in each direction, as it could be for instance the case of a grid where all grid points outside some masking primitive are removed, this extent field should not be used. Instead use the coordinate field. Reference to or definition of a coordinate system with which the positions and directions are interpretable. If the coordinate system is not specified the paraprobe coordinate system is used. Integer which specifies the first index to be used for distinguishing identifiers for cells. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. A tight axis-aligned bounding box about the grid. For atom probe should be set to true. Integer which specifies the first index to be used for distinguishing hexahedra. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. Integer which specifies the first index to be used for distinguishing identifiers for vertices. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. Integer which specifies the first index to be used for distinguishing identifiers for faces. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. Positions of the vertices. Users are encouraged to reduce the vertices to unique set of positions and vertices as this supports a more efficient storage of the geometry data. It is also possible though to store the vertex positions naively in which case vertices_are_unique is likely False. Naively here means that one for example stores each vertex of a triangle mesh even though many vertices are shared between triangles and thus the positions of these vertices do not have to be duplicated. Array of identifiers from vertices which describe each face. The first entry is the identifier of the start vertex of the first face, followed by the second vertex of the first face, until the last vertex of the first face. Thereafter, the start vertex of the second face, the second vertex of the second face, and so on and so forth. Therefore, summating over the number_of_vertices, allows to extract the vertex identifiers for the i-th face on the following index interval of the faces array: [$\sum_i = 0}^{i = n-1}$, $\sum_{i=0}^{i = n}$]. Six equally formatted sextets chained together. For each sextett the first entry is an XDMF primitive topology key (here 5 for polygon), the second entry the XDMF primitive count value (here 4 because each face is a quad). The remaining four values are the vertex indices. How many distinct boundaries are distinguished? Most grids discretize a cubic or cuboidal region. In this case six sides can be distinguished, each making an own boundary. Name of the boundaries. E.g. left, right, front, back, bottom, top, The field must have as many entries as there are number_of_boundaries. The boundary conditions for each boundary: 0 - undefined 1 - open 2 - periodic 3 - mirror 4 - von Neumann 5 - Dirichlet The result of the delocalization based on which subsequent iso-surfaces will be computed. In commercial software so far there is not a possibility to export such grid. Cell center of mass positions along x. Cell center of mass positions along y. Cell center of mass positions along z. Intensity of the field at given point Center of mass positions of each voxel for rendering the scalar field via XDMF in e.g. Paraview. XDMF topology for rendering in combination with xdmf_xyz the scalar field via XDFM in e.g. Paraview. The three-dimensional gradient nabla operator applied to scalar_field_magnitude. Cell center of mass positions along x. Cell center of mass positions along y. Cell center of mass positions along z. The gradient vector. Center of mass positions of each voxel for rendering the scalar field via XDMF in e.g. Paraview. XDMF topology for rendering in combination with xdmf_xyz the scalar field via XDFM in e.g. Paraview. Halfwidth of the kernel about the central voxel. The shape of the kernel is that of a cuboid of extent 2*kernel_extent[i] + 1 in each dimension i. Sigma of the kernel in each dimension in the paraprobe coordinate_system with i = 0 is x, i = 1 is y, i = 2 is z. Expectation value of the kernel in each dimension in the paraprobe coordinate_system with i = 0 is x, i = 1 is y, i = 2 is z. An iso-surface is the boundary between two regions across which the magnitude of a scalar field falls below/exceeds a threshold magnitude phi. For applications in atom probe microscopy the location and shape of such a boundary (set) is typically approximated by discretization. This yields a complex of not necessarily connected geometric primitives. Paraprobe-nanochem approximates this complex with a soup of triangles. The threshold or iso-contour value. Details about the specific marching cubes algorithm which was taken to compute the iso-surface. The grid is the delocalization grid. Reference to the specific implementation of marching cubes used. The value placed here should be a DOI. If there are no specific DOI or details write not_further_specified, or give at least a free-text description. The program and version used is the specific paraprobe-nanochem. The resulting triangle soup computed via marching cubes. Integer which specifies the first index to be used for distinguishing triangles. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. Number of vertices. Number of faces. Integer which specifies the first index to be used for distinguishing identifiers for vertices. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. Integer which specifies the first index to be used for distinguishing identifiers for faces. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. Positions of the vertices. Users are encouraged to reduce the vertices to unique set of positions and vertices as this supports a more efficient storage of the geometry data. It is also possible though to store the vertex positions naively in which case vertices_are_unique is likely False. Naively here means that one for example stores each vertex of a triangle mesh even though many vertices are shared between triangles and thus the positions of these vertices do not have to be duplicated. Array of identifiers from vertices which describe each face. The first entry is the identifier of the start vertex of the first face, followed by the second vertex of the first face, until the last vertex of the first face. Thereafter, the start vertex of the second face, the second vertex of the second face, and so on and so forth. Therefore, summating over the number_of_vertices, allows to extract the vertex identifiers for the i-th face on the following index interval of the faces array: [$\sum_i = 0}^{i = n-1}$, $\sum_{i=0}^{i = n}$]. A list of as many tuples of XDMF topology key, XDMF number of vertices and a triple of vertex indices specifying each triangle. The total number of entries is n_f_tri * (1+1+3). Direction of each normal. Qualifier how which specifically oriented normal to its primitive each normal represents. * 0 - undefined * 1 - outer * 2 - inner Direction of each normal. Qualifier how which specifically oriented normal to its primitive each normal represents. * 0 - undefined * 1 - outer * 2 - inner Triangle normals are oriented in the direction of the gradient vector of the local delocalized scalar field. :math:`\sum_{x, y, z} {\nabla{c}_i}^2`. Triangle normals are oriented in the direction of the gradient vector of the local delocalized scalar field. The projection variable here describes the cosine of the angle between the gradient direction and the normal direction vector. This is a descriptor of how parallel the projection is that is especially useful to document those triangles for whose projection is almost perpendicular. Array of edge length values. For each triangle the edge length is reported for the edges traversed according to the sequence in which vertices are indexed in triangles. Array of interior angle values. For each triangle the angle is reported for the angle opposite to the edges which are traversed according to the sequence in which vertices are indexed in triangles. The center of mass of each triangle. Iso-surfaces of arbitrary scalar three-dimensional fields can show a complicated topology. Paraprobe-nanochem can run a DBScan-like clustering algorithm which performs a connectivity analysis on the triangle soup. This yields a set of connected features with their surfaces discretized by triangles. Currently, the tool distinguishes at most three types of features: 1. So-called objects, i.e. necessarily watertight features represented polyhedra. 2. So-called proxies, i.e. features that were replaced by a proxy mesh and made watertight. 3. Remaining triangle surface meshes of arbitrary shape and cardinality. These features can be interpreted as microstructural features. Some of them may be precipitates, some of them may be poles, some of them may be segments of dislocation lines or other crystal defects which are decorated (or not) with solutes. The identifier which the triangle_soup connectivity analysis returned, which constitutes the first step of the volumetric_feature identification process. The array of keywords of feature_type dictionary. The array of values for each keyword of the feature_type dictionary. The array of controlled keywords, need to be from feature_type_dict_keyword, which specify which type each feature triangle cluster belongs to. Keep in mind that not each feature is an object or proxy. The explicit identifier of features. Details for features which are (closed) objects. Identifier have to exist in feature_identifier. An oriented bounding box (OBB) to each object. Edge length of the oriented bounding box from largest to smallest value. Oriented bounding box aspect ratio. YX versus ZY. Position of the geometric center, which often is but not necessarily has to be the center_of_mass of the hexahedrally-shaped sample/sample part. A simple approach to describe the entire set of hexahedra when the main intention is to store the shape of the hexahedra for visualization. Details for all those objects close to edge, i.e. those which have at least one ion which lays closer to a modelled edge of the dataset than threshold. Total (count) relevant for normalization. Count or weight which, when divided by total, yields the composition of this element, isotope, molecule or ion. Array of evaporation_identifier / ion_identifier which specify ions laying inside or on the surface of the feature. Details for all those objects far from edge, i.e. those whose ions lay all at least threshold distant from a modelled edge of the dataset. Total (count) relevant for normalization. Count or weight which, when divided by total yields the composition of this element, isotope, molecule or ion. Array of evaporation_identifier / ion_identifier which specify ions laying inside or on the surface of the feature. Details for features which are so-called proxies, i.e. objects which have been reconstructed and combinatorially closed with processing their partial triangulated_surface_mesh (hole filling, refinement). Identifier have to exist in feature_identifier. Details for those proxies close to edge, i.e. those which have at least one ion which lays closer to a modelled edge of the dataset than threshold. Identifier have to exist in feature_identifier. Total (count) relevant for normalization. Count or weight which, when divided by total yields the composition of this element, isotope, molecule or ion. Array of evaporation_identifier / ion_identifier which specify ions laying inside or on the surface of the feature. Details for those proxies far from edge, i.e. those whose ions lay all at least threshold distant from a modelled edge of the dataset. Total (count) relevant for normalization. Count or weight which, when divided by total yields the composition of this element, isotope, molecule or ion. Array of evaporation_identifier / ion_identifier which specify ions laying inside or on the surface of the feature. The multiplicity whereby the ion position is accounted for irrespective whether the ion is considered as a decorator of the interface or not. As an example, with atom probe it is typically not possible to resolve the positions of the atoms which arrive at the detector as molecular ions. Therefore, an exemplar molecular ion of two carbon atoms can be considered to have a multiplicity of two to account that this molecular ion contributes two carbon atoms at the reconstructed location considering that the spatial resolution of atom probe experiments is limited. The multiplicity whereby the ion position is accounted for when the ion is considered one which is a decorator of the interface. The equation of the plane that is fitted initially. The four parameter :math:`ax + by + cz + d = 0` which define the plane. The triangle surface mesh representing the interface model. Exported at some iteration before the next DCOM step. Direction of each normal Qualifier how which specifically oriented normal to its primitive each normal represents. * 0 - undefined * 1 - outer * 2 - inner Direction of each normal Qualifier how which specifically oriented normal to its primitive each normal represents. * 0 - undefined * 1 - outer * 2 - inner Array of edge length values. For each triangle the edge length is reported for the edges traversed according to the sequence in which vertices are indexed in triangles. Array of interior angle values. For each triangle the angle is reported for the angle opposite to the edges which are traversed according to the sequence in which vertices are indexed in triangles. The triangle surface mesh representing the interface model. Exported at some iteration after the next DCOM step. Direction of each normal Qualifier how which specifically oriented normal to its primitive each normal represents. * 0 - undefined * 1 - outer * 2 - inner Direction of each normal Qualifier how which specifically oriented normal to its primitive each normal represents. * 0 - undefined * 1 - outer * 2 - inner Array of edge length values. For each triangle the edge length is reported for the edges traversed according to the sequence in which vertices are indexed in triangles. Array of interior angle values. For each triangle the angle is reported for the angle opposite to the edges which are traversed according to the sequence in which vertices are indexed in triangles. The ROIs are defined as cylinders for the computations. To visualize these though we discretize them into regular n-gons. Using for instance a 360-gon, i.e. a regular n-gon with 360 edges resolves the lateral surface of each cylinder very finely so that they are rendered smoothly in visualization software. Position of the geometric center, which often is but not necessarily has to be the center_of_mass of the polyhedra. Integer which specifies the first index to be used for distinguishing ROI cylinder. Identifiers are defined explicitly. The number of atoms in each ROI. The number of ions in each ROI. The orientation of the ROI defined via a vector which points along the cylinder axis and whose length is the height of the cylinder. In the direction of the ROI. Hashvalue Specify if it was different from the number_of_processes in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. ././@PaxHeader0000000000000000000000000000023600000000000010216 xustar00119 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_ranger.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_ranger0000644000077000000000000005221314777236751033175 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The total number of ions in the reconstruction. Maximum number of allowed atoms per (molecular) ion (fragment). Needs to match maximum_number_of_atoms_per_molecular_ion. Results of a paraprobe-ranger tool run. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ever persistent resources where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable in the same deterministic manner. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file was started, i.e. the paraprobe-tool executable started as a process. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file were completed and the paraprobe-tool executable exited as a process. The path and name of the config file for this analysis. At least SHA256 strong hash of the specific config_file for tracking provenance. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. A statement whether the paraprobe-tool executable managed to process the analysis or failed prematurely. This status is written to the results file after the end_time at which point the executable must not compute any analysis. Only when this status message is present and shows `success`, the user should consider the results. In all other cases it might be that the executable has terminated prematurely or another error occurred. If used, contact information and eventually details of at least the person who performed this analysis. Details about the coordinate system conventions used. The individual coordinate systems which should be used. Field names should be prefixed with the following controlled terms indicating which individual coordinate system is described: * paraprobe * lab * specimen * laser * leap * detector * recon Paraprobe-ranger loads the iontypes and evaluates for each ion on which iontype it matches. If it matches on none, the ion is considered of the default unknown type with a 0 as its respective value in the iontypes array. The length of the isotope_vector used to describe molecular ions. The iontype ID for each ion that was best matching, stored in the order of the evaporation sequence ID. The here computed iontypes do not take into account the charge state of the ion which is equivalent to interpreting a RNG and RRNG range files for each ion in such a way that only the elements of which a (molecular) ion is build are considered. By contrast, charged_iontypes takes into account also the charge state. A bitmask which identifies exactly all those ions ranged irrespective the type they ended up with. Number of ions covered by the mask. The mask value for most may be 0. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The unsigned integer array representing the content of the mask. If padding is used the padded bits are set to 0. The mask is for convenience always as large as the entire dataset as it will be stored compressed anyway. The convenience feature with this is that then the mask can be decoded with numpy and mirrored against the evaporation_id array and one immediately can filter out all points that were used by the paraprobe. The length of the array adds to the next unsigned integer if the number of ions in the dataset is not an integer multiple of the bitdepth. Paraprobe-ranger performs a combinatorial search over all possible or a reduced set of nuclids to identify into which ions these can be composed. The main result is the list of molecular ions, here formatted according to the definitions of a set of isotope_vectors as detailed in :ref:`NXion`. The mass-to-charge-state ratio of each molecular ion without considering relativistic or quantum effects. The mass of each molecular ion without considering relativistic or quantum effects. The charge_state of each molecular ion. The product of the natural abundance of the isotopes building each molecular ion. Further details are available in :ref:`NXapm_paraprobe_config_ranger`. The product of the natural abundance of the isotopes building each molecular ion. Further details are available in :ref:`NXapm_paraprobe_config_ranger`. The number of disjoint nuclids for each molecular ion. The number of nuclids for each molecular ion. Paraprobe-ranger loads iontypes and evaluates for each ion on which iontype it matches. If it matches on none, the ion is considered of the default unknown type with a 0 as its respective value in the iontypes array. In contrast to use_existent_ranging this process does neither needs measured ion position nor mass-to-charge-state ratio values. The length of the isotope_vector used to describe molecular ions. Specify if it was different from the number_of_processes in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. ././@PaxHeader0000000000000000000000000000024000000000000010211 xustar00121 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_selector.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_select0000644000077000000000000003220314777236751033173 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The total number of ions in the reconstruction. Results of a paraprobe-selector tool run. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ever persistent resources where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable in the same deterministic manner. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file was started, i.e. the paraprobe-tool executable started as a process. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file were completed and the paraprobe-tool executable exited as a process. The absolute path and name of the config file for this analysis. At least SHA256 strong hash of the specific config_file for tracking provenance. A statement whether the paraprobe-tool executable managed to process the analysis or failed prematurely. This status is written to the results file after the end_time at which point the executable must not compute any analysis. Only when this status message is present and shows `success`, the user should consider the results. In all other cases it might be that the executable has terminated prematurely or another error occurred. If used, contact information and eventually details of at least the person who performed this analysis. Details about the coordinate system conventions used. The individual coordinate systems which should be used. Field names should be prefixed with the following controlled terms indicating which individual coordinate system is described: * paraprobe * lab * specimen * laser * leap * detector * recon A bitmask which identifies which of the ions in the dataset were selected to become included in the region-of-interest (ROI). Number of ions covered by the mask. The mask value for most may be 0. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The unsigned integer array representing the content of the mask. If padding is used the padded bits are set to 0. The mask is for convenience always as large as the entire dataset as it will be stored compressed anyway. The convenience feature with this is that then the mask can be decoded with numpy and mirrored against the evaporation_id array and one immediately can filter out all points that were used by the paraprobe. The length of the array adds to the next unsigned integer if the number of ions in the dataset is not an integer multiple of the bitdepth. Specify if it was different from the number_of_processes in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. ././@PaxHeader0000000000000000000000000000024000000000000010211 xustar00121 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_spatstat.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_spatst0000644000077000000000000004204614777236751033240 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The total number of ions in the reconstruction. Results of a paraprobe-spatstat tool run. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ever persistent resources where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable in the same deterministic manner. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file was started, i.e. the paraprobe-tool executable started as a process. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file were completed and the paraprobe-tool executable exited as a process. The absolute path and name of the config file for this analysis. At least SHA256 strong hash of the specific config_file for tracking provenance. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. A statement whether the paraprobe-tool executable managed to process the analysis or failed prematurely. This status is written to the results file after the end_time at which point the executable must not compute any analysis. Only when this status message is present and shows `success`, the user should consider the results. In all other cases it might be that the executable has terminated prematurely or another error occurred. If used, contact information and eventually details of at least the person who performed this analysis. Details about the coordinate system conventions used. The individual coordinate systems which should be used. Field names should be prefixed with the following controlled terms indicating which individual coordinate system is described: * paraprobe * lab * specimen * laser * leap * detector * recon A bitmask which identifies which of the ions in the dataset were analyzed. Number of ions covered by the mask. The mask value for most may be 0. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The unsigned integer array representing the content of the mask. If padding is used the padded bits are set to 0. The mask is for convenience always as large as the entire dataset as it will be stored compressed anyway. The convenience feature with this is that then the mask can be decoded with numpy and mirrored against the evaporation_id array and one immediately can filter out all points that were used by the paraprobe. The length of the array adds to the next unsigned integer if the number of ions in the dataset is not an integer multiple of the bitdepth. The iontype ID for each ion that was assigned to each ion during the randomization of the ionlabels. Iontype labels are just permuted but the total number of values for each iontype stay the same. The order matches the iontypes array from a given ranging results as is specified in the configuration settings inside the specific config_filename that was used for this spatstat analysis. K-nearest neighbor statistics. Right boundary of the binning. Cumulated Cumulated and normalized by total counts Radial distribution statistics. Right boundary of the binning. Cumulated Cumulated and normalized by total counts Specify if it was different from the number_of_processes in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. ././@PaxHeader0000000000000000000000000000024000000000000010211 xustar00121 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_surfacer.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_surfac0000644000077000000000000006463314777236751033213 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The total number of ions in the reconstruction. The number of vertices of the alpha complex. The number of faces of the alpha complex. The total number of XDMF values to represent all faces of triangles via XDMF. The total number of XDMF values to represent all faces of tetrahedra via XDMF. Results of a paraprobe-surfacer tool run. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ever persistent resources where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable in the same deterministic manner. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file was started, i.e. the paraprobe-tool executable started as a process. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file were completed and the paraprobe-tool executable exited as a process. The absolute path and name of the config file for this analysis. At least SHA256 strong hash of the specific config_file for tracking provenance. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. A statement whether the paraprobe-tool executable managed to process the analysis or failed prematurely. This status is written to the results file after the end_time at which point the executable must not compute any analysis. Only when this status message is present and shows `success`, the user should consider the results. In all other cases it might be that the executable has terminated prematurely or another error occurred. If used, contact information and eventually details of at least the person who performed this analysis. Details about the coordinate system conventions used. The individual coordinate systems which should be used. Field names should be prefixed with the following controlled terms indicating which individual coordinate system is described: * paraprobe * lab * specimen * laser * leap * detector * recon A bitmask which identifies which of the ions in the dataset were analyzed. Computations of alpha complexes may have filtered this ion set further but this process is deterministic. Number of ions covered by the mask. The mask may be 0 for most. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The unsigned integer array representing the content of the mask. If padding is used the padded bits are set to 0. The mask is for convenience always as large as the entire dataset as it will be stored compressed anyway. The convenience feature with this is that then the mask can be decoded with numpy and mirrored against the evaporation_id array and one immediately can filter out all points that were used by the paraprobe. The length of the array adds to the next unsigned integer if the number of ions in the dataset is not an integer multiple of the bitdepth. Paraprobe-surfacer can be used to load a ROI that is the entire or a sub-set of the ion point cloud. In the point_cloud_wrapping process the tool computes a triangulated surface mesh which encloses the ROI/point cloud. This mesh can be seen as a model for the edge of the dataset. Different algorithms can be used with paraprobe-surfacer to create this mesh such as convex hulls, alpha-shapes as their generalization, or alpha wrappings. Ideally, the resulting mesh should be a watertight polyhedron. This polyhedron is not necessarily convex. For some algorithms there is no guarantee that the resulting mesh yields a watertight mesh. A bitmask which identifies exactly all those ions whose positions were considered when defining the filtered point set from which the alpha complex was then in fact computed. This window can be different to the entire window as irrelevant ions might have been filtered out to reduce the computational costs of the alpha complex analysis. Number of ions covered by the mask. The mask value for most may be 0. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The unsigned integer array representing the content of the mask. If padding is used the padded bits are set to 0. The mask is for convenience always as large as the entire dataset as it will be stored compressed anyway. The convenience feature with this is that then the mask can be decoded with numpy and mirrored against the evaporation_id array and one immediately can filter out all points that were used by the paraprobe. The length of the array adds to the next unsigned integer if the number of ions in the dataset is not an integer multiple of the bitdepth. The set of triangles in the coordinate system paraprobe which discretizes the exterior surface of the alpha complex. Integer which specifies the first index to be used for distinguishing triangles. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. Number of vertices. Number of faces. A list of as many tuples of XDMF topology key, XDMF number of vertices and a triple of vertex indices specifying each triangle. The total number of entries is n_f_tri * (1+1+3). Do the triangles define a triangulated surface mesh which is watertight? The volume which the triangulated surface mesh encloses provided that the mesh is watertight. The set of tetrahedra which represent the interior volume of the complex if that is a closed 2-manifold. Integer which specifies the first index to be used for distin- guishing tetrahedra. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The accumulated volume of all interior tetrahedra. Number of vertices. Number of faces. A list of as many tuples of XDMF topology key, XDMF number of vertices and a triple of vertex indices specifying each triangle. The total number of entries is n_f_tet * (1+1+4). In the future we may want to wrap other primitives like triangles or polylines. Specify if it was different from the number_of_processes in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. ././@PaxHeader0000000000000000000000000000024300000000000010214 xustar00124 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_tessellator.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_tessel0000644000077000000000000011135614777236751033222 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The total number of ions in the reconstruction. The total number of facets/polygons defining the tessellation. Results of a paraprobe-tessellator tool run. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ever persistent resources where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable in the same deterministic manner. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file was started, i.e. the paraprobe-tool executable started as a process. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file were completed and the paraprobe-tool executable exited as a process. The absolute path and name of the config file for this analysis. At least SHA256 strong hash of the specific config_file for tracking provenance. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. A statement whether the paraprobe-tool executable managed to process the analysis or failed prematurely. This status is written to the results file after the end_time at which point the executable must not compute any analysis. Only when this status message is present and shows `success`, the user should consider the results. In all other cases it might be that the executable has terminated prematurely or another error occurred. If used, contact information and eventually details of at least the person who performed this analysis. Details about the coordinate system conventions used. The individual coordinate systems which should be used. Field names should be prefixed with the following controlled terms indicating which individual coordinate system is described: * paraprobe * lab * specimen * laser * leap * detector * recon The tool can be used to compute a Voronoi tessellation the entire or a sub-set of the reconstruction. The point cloud in the ROI is wrapped into a tight axis-aligned bounding box. The tool detects if Voronoi cells make contact with the walls of this bounding box. The tessellation is computed without periodic boundary conditions. A bitmask which identifies which of the ions in the dataset were analyzed. Number of ions covered by the mask. The mask value for most may be 0. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The unsigned integer array representing the content of the mask. If padding is used the padded bits are set to 0. The mask is for convenience always as large as the entire dataset as it will be stored compressed anyway. The convenience feature with this is that then the mask can be decoded with numpy and mirrored against the evaporation_id array and one immediately can filter out all points that were used by the paraprobe. The length of the array adds to the next unsigned integer if the number of ions in the dataset is not an integer multiple of the bitdepth. A bitmask which identifies which of points have Voronoi cells that are truncated by the global axis-aligned bounding box, i.e. boundaries of the threads are ignored. Number of points covered by the mask. The mask value for most may be 0. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The unsigned integer array representing the content of the mask. If padding is used the padded bits are set to 0. The mask is for convenience always as large as the entire dataset as it will be stored compressed anyway. The convenience feature with this is that then the mask can be decoded with numpy and mirrored against the evaporation_id array and one immediately can filter out all points that were used by the paraprobe. The length of the array adds to the next unsigned integer if the number of ions in the dataset is not an integer multiple of the bitdepth. A bitmask which identifies which of points have Voronoi cells that are truncated by a specific wall of the axis-aligned bounding box. The left wall has the negative x axis of the paraprobe coordinate system as the outer unit normal. Number of points covered by the mask. The mask value for most may be 0. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The unsigned integer array representing the content of the mask. If padding is used the padded bits are set to 0. The mask is for convenience always as large as the entire dataset as it will be stored compressed anyway. The convenience feature with this is that then the mask can be decoded with numpy and mirrored against the evaporation_id array and one immediately can filter out all points that were used by the paraprobe. The length of the array adds to the next unsigned integer if the number of ions in the dataset is not an integer multiple of the bitdepth. A bitmask which identifies which of points have Voronoi cells that are truncated by a specific wall of the axis-aligned bounding box. The right wall has the positive x axis of the paraprobe coordinate system as the outer unit normal. Number of points covered by the mask. The mask value for most may be 0. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The unsigned integer array representing the content of the mask. If padding is used the padded bits are set to 0. The mask is for convenience always as large as the entire dataset as it will be stored compressed anyway. The convenience feature with this is that then the mask can be decoded with numpy and mirrored against the evaporation_id array and one immediately can filter out all points that were used by the paraprobe. The length of the array adds to the next unsigned integer if the number of ions in the dataset is not an integer multiple of the bitdepth. A bitmask which identifies which of points have Voronoi cells that are truncated by a specific wall of the axis-aligned bounding box. The front wall has the negative y axis of the paraprobe coordinate system as the outer unit normal. Number of points covered by the mask. The mask value for most may be 0. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The unsigned integer array representing the content of the mask. If padding is used the padded bits are set to 0. The mask is for convenience always as large as the entire dataset as it will be stored compressed anyway. The convenience feature with this is that then the mask can be decoded with numpy and mirrored against the evaporation_id array and one immediately can filter out all points that were used by the paraprobe. The length of the array adds to the next unsigned integer if the number of ions in the dataset is not an integer multiple of the bitdepth. A bitmask which identifies which of points have Voronoi cells that are truncated by a specific wall of the axis-aligned bounding box. The rear wall has the positive y axis of the paraprobe coordinate system as the outer unit normal. Number of points covered by the mask. The mask value for most may be 0. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The unsigned integer array representing the content of the mask. If padding is used the padded bits are set to 0. The mask is for convenience always as large as the entire dataset as it will be stored compressed anyway. The convenience feature with this is that then the mask can be decoded with numpy and mirrored against the evaporation_id array and one immediately can filter out all points that were used by the paraprobe. The length of the array adds to the next unsigned integer if the number of ions in the dataset is not an integer multiple of the bitdepth. A bitmask which identifies which of points have Voronoi cells that are truncated by a specific wall of the axis-aligned bounding box. The left wall has the negative z axis of the paraprobe coordinate system as the outer unit normal. Number of points covered by the mask. The mask value for most may be 0. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The unsigned integer array representing the content of the mask. If padding is used the padded bits are set to 0. The mask is for convenience always as large as the entire dataset as it will be stored compressed anyway. The convenience feature with this is that then the mask can be decoded with numpy and mirrored against the evaporation_id array and one immediately can filter out all points that were used by the paraprobe. The length of the array adds to the next unsigned integer if the number of ions in the dataset is not an integer multiple of the bitdepth. A bitmask which identifies which of points have Voronoi cells that are truncated by a specific wall of the axis-aligned bounding box. The left wall has the positive z axis of the paraprobe coordinate system as the outer unit normal. Number of points covered by the mask. The mask value for most may be 0. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The unsigned integer array representing the content of the mask. If padding is used the padded bits are set to 0. The mask is for convenience always as large as the entire dataset as it will be stored compressed anyway. The convenience feature with this is that then the mask can be decoded with numpy and mirrored against the evaporation_id array and one immediately can filter out all points that were used by the paraprobe. The length of the array adds to the next unsigned integer if the number of ions in the dataset is not an integer multiple of the bitdepth. Interior volume By which MPI process was the Voronoi cell computed. By which OpenMP thread was the Voronoi cell computed. The number of faces for each polyhedron. Faces of adjoining polyhedra are counted for each polyhedron. This field can be used to interpret the array/field with the individual area values for each face. Integer which specifies the first index to be used for distinguishing polyhedra. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. Integer used to distinguish polyhedra for explicit indexing. A simple approach to describe the entire set of polyhedra when the main intention is to store the shape of the polyhedra for visualization. Number of vertices. Number of faces. A sequence of always first an XDMF topology type key, followed by the XDMF number of vertices of the polygon, followed by the vertex identifier which define the facet polygon. First we store the polygon of the first facet of the first cell, then the second facet of the first cell, until the last facet of the first cell, followed by the first facet of the second cell, and so on and so forth. A sequence of cell identifier so that each facet is associated with its cell because of which it is then possible to segment out cells three-dimensionally based on cell i.e. evaporation_id. Specify if it was different from the number_of_processes in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. ././@PaxHeader0000000000000000000000000000024200000000000010213 xustar00123 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_transcoder.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_transc0000644000077000000000000007515514777236751033223 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The total number of ions in the reconstruction. Maximum number of allowed atoms per (molecular) ion (fragment). Needs to match maximum_number_of_atoms_per_molecular_ion. Number of mass-to-charge-state-ratio intervals mapped on this ion type. Total number of integers in the supplementary XDMF topology array. Number of ions probed in the combinatorial analysis of the charge states Results of a paraprobe-transcoder tool run. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Given name of the program/software/tool with which this NeXus (configuration) file was generated. Ideally program version plus build number, or commit hash or description of ever persistent resources where the source code of the program and build instructions can be found so that the program can be configured ideally in such a manner that the result of this computational process is recreatable in the same deterministic manner. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file was started, i.e. the paraprobe-tool executable started as a process. ISO 8601 formatted time code with local time zone offset to UTC information included when the analysis behind this results file were completed and the paraprobe-tool executable exited as a process. The absolute path and name of the config file for this analysis. At least SHA256 strong hash of the specific config_file for tracking provenance. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. A statement whether the paraprobe-tool executable managed to process the analysis or failed prematurely. This status is written to the results file after the end_time at which point the executable must not compute any analysis. Only when this status message is present and shows `success`, the user should consider the results. In all other cases it might be that the executable has terminated prematurely or another error occurred. If used, contact information and eventually details of at least the person who performed this analysis. Details about the coordinate system conventions used. The individual coordinate systems which should be used. Field names should be prefixed with the following controlled terms indicating which individual coordinate system is described: * paraprobe * lab * specimen * laser * leap * detector * recon An array of triplets of integers which can serve as a supplementary array for Paraview to display the reconstruction. The XDMF datatype is here 1, the number of primitives 1 per triplet, the last integer in each triplet is the identifier of each point starting from zero. On a mid term perspective we would like to evolve the paraprobe-toolbox to an implementation stage where it works exclusively with completely provenance-tracked formats for both the configuration of the workflow step and/or analysis with each tool and also for the output of these analyses in the form of so-called tool-specific results files. Currently the Hierarchical Data Format 5 (HDF5) is used to store such data. Different file formats can be used to inject reconstructed datasets and ranging definitions into the toolbox. Traditionally, these are the POS, ePOS, and APT files with the tomographic reconstruction and other metadata and RNG and RRNG file formats for the ranging definitions how mass-to-charge state-ratio values map on (molecular) ion types. Such input should be injected via specific NeXus/HDF5 files which are documented in compliance with the NXapm application definition. So far the paraprobe-toolbox was used as a standalone tool. Therefore, it was not relevant during the development to focus on interoperability. Essentially paraprobe-transcoder was used as a parser to transcode data in the above-mentioned file formats into a paraprobe-specific representation. This transcoding should become deprecated. Here we describe steps we have taken into this direction. With the work in the FAIRmat project and the desire to make the paraprobe- toolbox also accessible as a cloud-computing capable service in the Nomad Remote Tools Hub (NORTH) the topic of interoperability became more important and eventually the NXapm application definition was proposed. NORTH is a GUI and related service in a NOMAD OASIS instance which allows to spawn preconfigured docker containers via JupyterHub. Currently, NORTH includes the so-called apm container. A container with tools specific for analyzing data from atom probe microscopy as well as processing of point cloud and mesh data. The NXapm application definition and related implementation work within NOMAD OASIS enabled users to parse content of POS, ePOS, APT, RNG, and RRNG files, surplus key metadata from vendor-agnostic electronic lab notebook solutions directly into NOMAD OASIS via the uploads section. The process is automated and yields an NXapm-compliant NeXus/HDF5 file inside the uploads section in return. With these improvements made there is no longer a need for - at least the users of a NOMAD OASIS and NORTH instance to use the deprecated PARAPROBE.Transcoder.Results.*.h5 files. Ideally, paraprobe should automatically detect that the input can now be an NXapm-compliant NeXus/HDF5 file and in response work with this file directly. To remain compliant with users however who do not have or do not wish to use a NOMAD OASIS or NXapm or NeXus at all right now, the solution is as follows: Calling the configuration stage of paraprobe-transcoder is always mandatory. It is always the first step of working with the toolbox. In this process the user defines the input files. These can either be nxs i.e. the NXapm/NeXus/ HDF5 file from e.g. the upload section, or such a file that was obtained from a colleague with a NOMAD OASIS instance. In all other cases, users can pass the reconstruction and ranging definitions using the traditional POS, ePOS, or APT and RNG or RRNG file formats respectively. Based on which input the user delivers, the parmsetup-transcoder tool then creates a configuration file PARAPROBE.Transcoder.Config.SimID.*.nxs and informs the user whether the input was NeXus (and thus if all relevant input is already available) or whether the paraprobe-transcoder tool needs to be executed to convert the content of the vendor files first into a format which paraprobe can provenance track and understand. In the latter case, the PARAPROBE.Transcoder.Config.SimID.*.nxs file is used to communicate to all subsequently used tools from which files the tools can expect to find the reconstruction and ranging definitions. All subsequent analysis steps start also with a tool-specific configuration. This configuration step reads in (among others) the PARAPROBE.Transcoder.Config.SimID.*.nxs file from which the configuration tool identifies automatically whether to read the reconstruction and ranging data from PARAPROBE.Transcoder.Results.SimID.*.h5 or directly the NXapm-compliant NeXus/HDF5 file that was created upon preparing the upload or the file shared from a colleague. This design removes the need for unnecessary copies of the data. Currently still though users should execute the transcoder step as it will generate a supplementary XDMF topology field with which the data in either the NeXus/HDF5 or the transcoded vendor files can be displayed using e.g. Paraview. For this purpose XDMF is used. Of course ideally the APT community would at some point converge to use a common data exchange file format. To this end, AMETEK/Cameca's APT file format could be a good starting point but so far it is lacking a consistent way of how to store generalized ranging definitions and post-processing results. POS, ePOS, Rouen's ATO, as well as other so far used representations of data like CSV or text files have, to the best of our current knowledge, no concept of how to marry reconstruction and (optional) ranging data into one self-descriptive format. This summarizes the rationale behind the current choices of the I/O for paraprobe. Furthermore, this summarizes also why the fundamental design of splitting an analysis always into steps of configuration (with parmsetup), task execution (with the respective C/C++ or Python tool of the toolbox), and post-processing (e.g. with autoreporter) is useful because it offers a clear description of provenance tracking. This is a necessary step to make atom probe microscopy data at all better aligned with the aims of the FAIR principles. The internal organization of the data entries in the atom_probe group in this application definition for paraprobe-transcoder results files mirror the definitions of the NXapm for consistency reasons. Mass-to-charge-state ratio values. Three-dimensional reconstructed positions of the ions. Interleaved array of x, y, z positions in the specimen space. Details about how peaks, with taking into account error models, were interpreted as ion types or not. Details and results of the combinatorial analyses of this range definition to identify the charge_state for an ion. Currently charge_state not charge! Specific isotopes building each candidate matching the range. Accumulated mass of the isotopes in each candidate. Not corrected for quantum effects. Product of natural abundance of the isotopes per candidate. Filter criterion on the product of the natural abundances computed from each isotope building the (molecular) ion. Such a filter can be used to reduce the number of possible molecular ions considered when trying to find a unique solution to the question which charge_state does a molecular ion within a given range and given combination of elements have. Filter criterion on the minimum half life which all isotopes building the (molecular) ion need to have to consider the candidate. Such a filter can be used to reduce the number of possible molecular ions considered when trying to find a unique solution to the question which charge_state does a molecular ion within a given range and given combination of elements have. If the value is zero/false it means that non-unique solutions are accepted. These are solutions where multiple candidates differ in their isotopes but have the same charge. Specify if it was different from the number_of_processes in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXbeam_path.nxdl.xml0000644000077000000000000004365514777236751030743 0ustar00rosborn A beam path consisting of one or more optical elements. NXbeam_path is used in NXopt to describe the beam path, i.e. the arrangement of optical elements between the excitation source and the sample, or between the sample and the detector unit. To describe the order of the elements, use 'order(NXtransformations)', where each element's position points to the preceding element via '@depends_on'. Special case beam splitter: A beam splitter is a device which separates the beam into two or more beams. If such a device is part of the beam path use two or more NXbeam_paths to describe the beam paths after the beam splitter. In this case, in the dependency chain of the new beam paths, the first elements each point to the beam splitter, as this is the previous element. Describe the relevant optical elements in the beam path by using the appropriate base classes. You may use as many elements as needed, also several elements of the same type as long as each element has its own name. Entry point of the dependency chain defined by the NXtransformations field, i.e. a link to the last element in the beam path. Example: /entry/instrument/beam_path/detector. Specify the order of the optical elements by defining a dependency chain. For each element, a '@depends_on' attribute should be used to state the position of the element in the beam path by pointing to the previous element. For the very first element, use the string "." instead. For each element in the beam path, one such field must exist with a '@depends_on' attribute defined to specify its position in the beam path. Note that also 'NXopt/ENTRY/INSTRUMENT/sample_stage' and windows ('NXopt/ENTRY/INSTRUMENT/sample_stage/entry_window' and 'NXopt/ENTRY/INSTRUMENT/sample_stage/exit_window') may be added to the dependency chain, i.e. may have an entry in this class even if they are not described in the beam path. ELEMENT is a place holder for the name of an optical beam path element. Note that the name of this field must be exactly the same as the element's field name. Add a link to the previous beam path element. Excitation source. One or more may be needed (e.g. two for a pump-probe setup with one pump and one probe beam). Depending on the source type, different properties are relevant, which are provided through the respective base class (e.g. use NXopt_source for lamps or lasers, NXchem_source for chemical reaction etc.). Some base classes are incomplete (NXchem_source, NXbio_source); the expertise of the respective communities is needed. Use this field to point to the previous optical element. Type of excitation source. Lifespan of the excitation (typically provided in hours). How many hours has the lamp been used? Wavelengths or energy vector of the excitation source. This can be a single value or a spectrum, depending on the type of experiment. Unit of wavelength or energy. Two- or three-dimensional beam profile. Power of one light pulse if the source is a pulsed source. Is the excitation source continuous wave (CW)? Power of CW beam. FWHM bandwidth of the excitation source. Coherence length. Divergence of the excitation beam. Use this field to describe a simple pinhole (round geometry). Define its dimension using 'diameter'. For more complex geometries, 'NXaperture' should be used. Use this field to describe a simple slit (rectangular geometry). Define its dimensions using 'x_gap' and 'y_gap'. For more complex geometries, 'NXaperture' should be used. Use this field to describe an aperture. To specify a window, use the field 'window_NUMBER(NXaperture)'. A window, e.g. an entry or exit window of a cryostat. Use this field to point to the previous optical element. The material of the window. If you specified 'other' as material, decsribe here what it is. Thickness of the window Angle of the window normal (outer) vs. the substrate normal (similar to the angle of incidence). If reference data were measured add a link to the NeXus file where they are described. A device that reduces the intensity of a beam by attenuation. The transmitted intensity divided by the incident intensity. Attenuation of the attenuator in dB. Unit of the measured data is not covered by NXDL units state here which unit was used. Input and output aperture of the attenuator. Geometry (shape, size etc.) of the attenuator. A diffraction grating. Define relevant parameters in the corresponding fields, e.g. order of diffration (diffraction_order) or angular dispersion (angular_dispersion). Define the type of the grating. Dispersion of the grating in nm/mm (or e.g. nm/mrad). Number of grooves per mm. Blaze wavelength of the grating. Efficiency curve versus wavelength or energy. Spectral values, e.g. wavelength or energy. Vector of length N_spectrum. Unit of wavelength array (e.g. nanometer or Angstrom) A device blocking the beam in a temporal periodic pattern, e.g. a optical chopper wheel. Specify the frequency range using 'min_frequency' and 'max_frequency'. Minimum frequency in Hertz. Maximum frequency in Hertz. Frequency resolution in Hertz. A monochromator or spectrometer. Spectral values of the monochromator, e.g. wavelength or energy values used for the measurement. Unit of wavelength array (e.g. nanometer or Angstrom) Diffraction grating. If two or more gratings were used, define the angular dispersion and the wavelength range (min/max wavelength) for each grating and make sure that the wavelength ranges do not overlap. The dispersion should be defined for the entire wavelength range of the experiment. Dispersion of the grating in nm/mm. Minimum wavelength of the grating. Maximum wavelength of the grating. Spectral resolution of the instrument. Define the width of the monochromator slit in the subfield x_gap. Was the slit width fixed? If slit width was not fixed, define the maximum slit width. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXbeam_splitter.nxdl.xml0000644000077000000000000003727614777236751031657 0ustar00rosborn Length of the spectrum vector (e.g. wavelength or energy) for which the refractive index of the beam splitter material and/or coating is defined. Length of the spectrum vector (e.g. wavelength or energy) for which the reflectance or transmission of the beam splitter is given. Number of parameters needed do descripe the shape of the beam splitter. Number of objects the beam splitter is made up of. Number of outputs, i.e. number of paths the beam takes after being split by the beam splitter. A beam splitter, i.e. a device splitting the light into two or more beams. Information about types and properties of beam splitters is provided e.g. [here](https://www.rp-photonics.com/beam_splitters.html). Use two or more NXbeam_paths to describe the beam paths after the beam splitter. In the dependency chain of the new beam paths, the first elements each point to this beam splitter, as this is the previous element. Specify the beam splitter type (e.g. dielectric mirror, pellicle, dichroic mirror etc.). Shape (e.g. prism, plate, cube) and dimension should be described in 'geometry'. Define if the beam splitter is polarizing or not in the field 'polarizing(NX_BOOLEAN)'. If you selected 'other' in 'type' use this field to specify which type of beam splitter was used. Is the beam splitter polarizing? Does the beam splitter have multiple outputs (diffractive optical element), i.e. more than two outputs? Describe the geometry (shape, dimension etc.) of the beam splitter. Specify the dimensions in 'SHAPE/size'. A sketch of the device should be provided in the 'sketch(NXdata)' field to clarify (i) the shape and dimensions of the device, and (ii) the input and outputs (i.e. the direction of the incoming and outcoming (split) beams). Describe the shape (plate, cube, wedged, prism etc.). If you chose 'other' in 'shape' describe what it is. Sketch of the beam splitter showing its geometry. The paths of the incoming and split beam should be illustrated and labelled (0 for the incoming beam, and 1, 2,..., N_outputs for the outputs (i.e. the split beam paths)). Physical extent of the beam splitter device. The beam splitter might be made up of one or more objects (NX_objects). The meaning and location of the axes used will vary according to the value of the 'shape' variable. 'N_shapepar' defines how many parameters: * For 'cube' the parameters are (width, length). * For 'cylinder' the parameters are (diameter, length). * For 'plate' the parameters are (width, height, length). * For 'prism' the parameters are (width, height, length). * For 'wedged' the parameters are (width, height, shortest length). The wedge angle should be provided in 'SHAPE/wedge_angle'. * For 'other' the parameters may be (A, B, C, ...) with the labels defined in the sketch plotted in 'SHAPE/sketch'. Wedge angle if 'shape' is 'wedged'. Beam splitting ratio(s) for the various outputs (i.e. the paths of the beam after being split by the beam splitter). The order of the ratios must be consistent with the labels 1, 2, ... N_outputs defined by the sketch in 'SHAPE/sketch', starting with 1. Clear aperture of the device (e.g. 90% of diameter for a disc, or 90% of length and height for square geometry). Substrate of the beam splitter. Describe the material of the substrate in substrate/substrate_material and provide its index of refraction in substrate/index_of_refraction_substrate, if known. Specify the material of the beam splitter. If the device has a coating it should be described in coating/coating_material. Is the material birefringent? Thickness of the beam splitter substrate. Define the minimum and maximum thickness (for a wedged geomtry). For a homogeneous thickness (e.g. as in plate beam splitters) the minimum and maximum values are equal. Complex index of refraction of the beam splitter substrate. Specify at given spectral values (e.g. wavelength, energy, wavenumber etc.). Is the beam splitter coated? If yes, specify the type and material of the coating and the spectral range for which it is designed. If known, you may also provide its index of refraction. For a beam splitter cube consisting of two prisms which are glued together, you may want to specify the the glue and the coatings of each prism. Specify the coating type (e.g. dielectric, anti-reflection (AR), multilayer coating etc.). Specify the coating material. Thickness of the coating. Wavelength range for which the coating is designed. Enter the minimum and maximum values of the wavelength range. Complex index of refraction of the coating. Specify at given spectral values (e.g. wavelength, energy, wavenumber etc.). Wavelength range for which the beam splitter is designed. Enter the minimum and maximum values of the wavelength range. Alternatively, or additionally, you may define the wavelength range for the coating in coating/wavelength_range_coating. Optical loss of the beam splitter for the various outputs (i.e. the paths of the beam after being split by the beam splitter). The order of the ratios must be consistent with the labels 1, 2, ... N_outputs defined by the sketch in 'SHAPE/sketch', starting with 1. Optimized angle of incidence for the desired splitting ratio. Angle of deflection corresponding to the optimized angle of incidence defined in incident_angle. Range of the angles of incidence (AOI) for which the beam splitter can be operated. Specify the minimum and maximum angles of the range. Reflectance of the beam splitter at given spectral values. Transmission at given spectral values for the various outputs (i.e. the paths of the beam after being split by the beam splitter). The order of the ratios must be consistent with the labels 1, 2, ... N_outputs defined by the sketch in 'SHAPE/sketch', starting with 1. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_alpha_complex.nxdl.xml0000644000077000000000000001444114777236751032277 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The dimensionality of the alpha shape, for now 2 or 3. The number of edges. The number of faces. The number of cells. Computational geometry description of alpha shapes or wrappings to primitives. For details see: * https://dx.doi.org/10.1109/TIT.1983.1056714 for 2D, * https://dx.doi.org/10.1145/174462.156635 for 3D, * https://dl.acm.org/doi/10.5555/871114 for weighted, and * https://doc.cgal.org/latest/Alpha_shapes_3 for 3D implementation * https://doc.cgal.org/latest/Manual/packages.html#PkgAlphaWrap3 for 3D wrap in CGAL, the Computational Geometry Algorithms Library. As a starting point, we follow the conventions of the CGAL library. Specify which general type of alpha shape is computed. Using for now the CGAL terminology. Basic means (unweighted) alpha shapes. Alpha_wrapping means meshes created using alpha wrapping procedures. Specifically when computed with the CGAL, the mode specifies if singular faces are removed (regularized) of the alpha complex. The alpha, (radius of the alpha-sphere) parameter to be used for alpha shapes and alpha wrappings. The offset distance parameter to be used in addition to alpha in the case of alpha_wrapping. Point cloud for which the alpha shape or wrapping should be computed. Triangle soup for which the alpha wrapping should be computed. A meshed representation of the resulting shape. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_cylinder_set.nxdl.xml0000644000077000000000000001540214777236751032145 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The cardinality of the set, i.e. the number of cylinders or cones. Computational geometry description of a set of cylinders in Euclidean space. The members of the set can have different size. For each member the position of the center and the height is mandatory. The radius can either be defined in the radius field or by filling both the upper and the lower radius field. The latter case can be used to represent truncated cones. Integer which specifies the first index to be used for distinguishing identifiers for cylinders. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if the identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Integer used to distinguish members for explicit indexing. The geometric center of each member. A direction vector which is parallel to the cylinder/cone axis and whose magnitude is the height of the cylinder/cone. The radius of the upper circular cap. This field, combined with lower_cap_radius can be used to describe (eventually truncated) circular cones. The radius of the upper circular cap. This field, combined with lower_cap_radius can be used to describe (eventually truncated) circular cones. Reference to or definition of a coordinate system with which the positions and directions are interpretable. Interior volume of each cylinder Lateral surface area Area of the upper and the lower cap of each cylinder respectively. Cap and lateral surface area for each cylinder. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_ellipsoid_set.nxdl.xml0000644000077000000000000001274614777236751032330 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The dimensionality, which has to be at least 2. The cardinality of the set, i.e. the number of ellipses, or ellipsoids. Computational geometry description of a set of ellipsoids in Euclidean space. Individual ellipsoids can have different half axes. Integer which specifies the first index to be used for distinguishing identifiers for ellipsoids. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if the identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Integer used to distinguish ellipsoids for explicit indexing. Geometric center of the ellipsoids. This can be the center of mass. Dimensionality and cardinality of the point and ellipsoid set have to match. The identifier_offset and identifier field of NXcg_point_set do not need to be used as they should be same as the identifier_offset and the identifier for the ellipsoids. If all ellipsoids in the set have the same half-axes. In the case that ellipsoids have different radii use this field instead of half_axes_radius. Reference to or definition of a coordinate system with which the positions and directions are interpretable. Are the ellipsoids closed or hollow? Direction unit vector which points along the largest half-axes. ././@PaxHeader0000000000000000000000000000023500000000000010215 xustar00118 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_face_list_data_structure.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_face_list_data_structure.0000644000077000000000000002547314777236751033047 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The dimensionality, which has to be at least 2. The number of vertices. The number of edges. The number of faces. The total number of vertices of all faces. Faces are polygons. The total number of Weinberg vector values of all faces. Computational geometry description of geometric primitives via a face and edge list. Primitives must not be degenerated or self-intersect. Such descriptions of primitives are frequently used for triangles and polyhedra to store them on disk for visualization purposes. Although storage efficient, such a description is not well suited for topological and neighborhood queries of especially meshes that are built from primitives. In this case, scientists may need a different view on the primitives which is better represented for instance with a half_edge_data_structure instance. The reason to split thus the geometric description of primitives, sets, and specifically meshes of primitives is to keep the structure simple enough for users without these computational geometry demands but also enable those more computational geometry savy users the storing of the additionally relevant data structure. This is beneficial and superior over NXoff_geometry because for instance a half_edge_data_structure instance can be immediately use to reinstantiate the set without having to recompute the half_edge_structure from the vertex and face-list based representation and thus offer a more efficient route to serve applications where topological and graph-based operations are key. Dimensionality. Array which specifies of how many vertices each face is built. Each entry represent the total number of vertices for face, irrespectively whether vertices are shared among faces/are unique or not. Number of edges. Number of faces. Integer which specifies the first index to be used for distinguishing identifiers for vertices. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Integer which specifies the first index to be used for distinguishing identifiers for edges. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Integer which specifies the first index to be used for distinguishing identifiers for faces. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Integer used to distinguish vertices explicitly. Integer used to distinguish edges explicitly. Integer used to distinguish faces explicitly. Positions of the vertices. Users are encouraged to reduce the vertices to unique set of positions and vertices as this supports a more efficient storage of the geometry data. It is also possible though to store the vertex positions naively in which case vertices_are_unique is likely False. Naively here means that one for example stores each vertex of a triangle mesh even though many vertices are shared between triangles and thus the positions of these vertices do not have to be duplicated. The edges are stored as a pairs of vertex identifier values. Array of identifiers from vertices which describe each face. The first entry is the identifier of the start vertex of the first face, followed by the second vertex of the first face, until the last vertex of the first face. Thereafter, the start vertex of the second face, the second vertex of the second face, and so on and so forth. Therefore, summating over the number_of_vertices, allows to extract the vertex identifiers for the i-th face on the following index interval of the faces array: [$\sum_i = 0}^{i = n-1}$, $\sum_{i=0}^{i = n}$]. If true indicates that the vertices are all placed at different positions and have different identifiers, i.e. no points overlap or are counted twice. If true indicates that no edge is stored twice. Users are encouraged to consider and use the half_edge_data_structure instead as this will work towards achieving a cleaner graph-based description if relevant and possible. Specifies for each face which winding order was used if any: * 0 - undefined * 1 - counter-clockwise (CCW) * 2 - clock-wise (CW) ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_geodesic_mesh.nxdl.xml0000644000077000000000000000537414777236751032266 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Computational geometry description of a geodesic mesh. People from geodesic/surveyors will likely have specific demands and different views about what should be included in such a base class, given that nested geodesic meshes are a key component of climate modelling tools. For now we propose to use this base class as a container to organize metadata and data related to geodesic meshes. Specifically an instance of this base class should detail the rule set how how the geodesic (surface) mesh was instantiated as there are many possibilities. A geodesic surface mesh is in this sense a triangulated surface mesh with metadata. For additional details as an introduction into the topic see e.g.: * `E. S. Popko and C. J. Kitrick <https://doi.org/10.1201/9781003134114>`_ Here, especially the section on subdivision schemes is relevant. Reference to or definition of a coordinate system with which the positions and directions are interpretable. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_grid.nxdl.xml0000644000077000000000000001625114777236751030411 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The dimensionality of the grid. The cardinality or total number of cells/grid points. Number of boundaries of the bounding box or primitive to the grid. Computational geometry description of a Wigner-Seitz cell grid in Euclidean space. Frequently convenient three-dimensional grids with cubic cells are used. Exemplar applications are spectral-solver based crystal plasticity and stencil methods like phase-field or cellular automata. The symmetry of the lattice defining the shape of the unit cell. The unit cell dimensions using crystallographic notation. Number of unit cells along each of the d unit vectors. The total number of cells, or grid points has to be the cardinality. If the grid has an irregular number of grid positions in each direction, as it could be for instance the case of a grid where all grid points outside some masking primitive are removed, this extent field should not be used. Instead use the coordinate field. Reference to or definition of a coordinate system with which the positions and directions are interpretable. Integer which specifies the first index to be used for distinguishing identifiers for cells. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if the identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Integer used to distinguish cells for explicit indexing. Position of each cell in Euclidean space. Coordinate of each cell with respect to the discrete grid. A tight bounding box or sphere or bounding primitive about the grid. How many distinct boundaries are distinguished? Most grids discretize a cubic or cuboidal region. In this case six sides can be distinguished, each making an own boundary. Name of domain boundaries of the simulation box/ROI e.g. left, right, front, back, bottom, top. The boundary conditions for each boundary: 0 - undefined 1 - open 2 - periodic 3 - mirror 4 - von Neumann 5 - Dirichlet ././@PaxHeader0000000000000000000000000000023500000000000010215 xustar00118 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_half_edge_data_structure.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_half_edge_data_structure.0000644000077000000000000001624014777236751033004 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The dimensionality, which has to be at least 2. The number of vertices. The number of faces. The number of half-edges. Computational geeometry description of a half-edge data structure. Such a data structure can be used to efficiently circulate around faces and iterate over vertices of a planar graph. In this half-edge data structure vertex identifiers start at 1. Vertices are identified with consecutive integers up to number_of_vertices. This field can be used to document which constant integer has to be added to another set of vertex_identifier to assure that these other identifiers also start at 1. In this half-edge data structure face identifiers start at 1. Faces are identified with consecutive integers up to number_of_faces. This field can be used to document which constant integer has to be added to another set of face_identifier to assure that these other identifiers also start at 1. The face identifier zero is reserved for the NULL face ! In this half-edge data structure half-edge identifiers start at 1. Half-edges are identified with consecutive integers up to number_of_half_edges. This field can be used to document which constant integer has to be added to another set of half_edge_identifier to assure that these other identifiers also start at 1. The position of the vertices. Identifier of the incident half-edge. Identifier of the (starting)/associated half-edge of the face. The identifier of the vertex from which this half-edge is outwards pointing. Identifier of the associated oppositely pointing half-edge. If the half-edge is a boundary half-edge the incident face identifier is NULL, i.e. 0. Identifier of the next half-edge. Identifier of the previous half-edge. Users are referred to the literature for the background of L. Weinberg's work about topological characterization of planar graphs: * `L. Weinberg 1966a, <https://dx.doi.org/10.1109/TCT.1964.1082216>`_ * `L. Weinberg, 1966b, <https://dx.doi.org/10.1137/0114062>`_ * `E. A. Lazar et al. <https://doi.org/10.1103/PhysRevLett.109.095505>`_ and how this work can e.g. be applied in space-filling tessellations of microstructural objects like crystals/grains. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_hexahedron_set.nxdl.xml0000644000077000000000000002542214777236751032464 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The cardinality of the set, i.e. the number of hexahedra. Computational geometry description of a set of hexahedra in Euclidean space. The hexahedra do not have to be connected, can have different size, can intersect, and be rotated. This class can also be used to describe cuboids or cubes, axis-aligned or not. The class represents different access and description levels to offer both applied scientists and computational geometry experts to use the same base class but rather their specific view on the data: * Most simple many experimentalists wish to communicate dimensions/the size of specimens. In this case the alignment with axes is not relevant as eventually the only relevant information to convey is the volume of the specimen. * In many cases, take for instance an experiment where a specimen was taken from a specifically deformed piece of material, e.g. cold-rolled, channel-die deformed, the orientation of the specimen edges with the experiment coordinate system can be of very high relevance. Examples include to know which specimen edge is parallel to the rolling, the transverse, or the normal direction. * Sufficient to pinpoint the sample and laboratory/experiment coordinate system, the above-mentioned descriptions are not detailed enough though to create a CAD model of the specimen. * Therefore, groups and fields for an additional, computational-geometry- based view of the hexahedra is offered which serve different computational tasks: storage-oriented simple views or detailed topological/graph-based descriptions. Hexahedra are important geometrical primitives, which are among the most frequently used elements in finite element meshing/modeling. Hexahedra have to be non-degenerated, closed, and built of polygons which are not self-intersecting. The term hexahedra will be used throughout this base class but includes the especially in engineering and more commonly used special cases, cuboid, cube, box, axis-aligned bounding box (AABB), optimal bounding box (OBB). An axis-aligned bounding box is a common data object in computational science and codes to represent a cuboid whose edges are aligned with a coordinate system. As a part of binary trees these are important data objects for time as well as space efficient queries of geometric primitives in techniques like kd-trees. An optimal bounding box is a common data object which provides the best tight fitting box about an arbitrary object. In general such boxes are rotated. Exact and substantially faster in practice approximate algorithms exist for computing optimal or near optimal bounding boxes for point sets. A qualitative description of each hexahedron/cuboid/cube/box. Qualifier how one edge is longer than all other edges of the hexahedra. Often the term length is associated with one edge being parallel to an axis of the coordinate system. Qualifier often used to describe the length of an edge within a specific coordinate system. Qualifier often used to describe the length of an edge within a specific coordinate system. Position of the geometric center, which often is but not necessarily has to be the center_of_mass of the hexahedrally-shaped sample/sample part. Total area (of all six faces) of each hexahedron. Area of each of the six faces of each hexahedron. Specifies if the hexahedra represent cuboids or cubes eventually rotated ones but at least not too exotic six-faced polyhedra. Only to be used if is_box is present. In this case, this field describes whether hexahedra are boxes whose primary edges are parallel to the axes of the Cartesian coordinate system. Reference to or definition of a coordinate system with which the qualifiers and mesh data are interpretable. Integer which specifies the first index to be used for distinguishing hexahedra. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if the identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Integer used to distinguish hexahedra for explicit indexing. A simple approach to describe the entire set of hexahedra when the main intention is to store the shape of the hexahedra for visualization. Disentangled representations of the mesh of specific hexahedra. Disentangled representation of the planar graph that each hexahedron represents. Such a description simplifies topological processing or analyses of mesh primitive operations and neighborhood queries. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_marching_cubes.nxdl.xml0000644000077000000000000000662014777236751032434 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Computational geometry description of the marching cubes algorithm. Documenting which specific version was used can help to understand how robust the results are with respect to the topology of the triangulation. Reference/link to and/or details of the grid on which a specific marching cubes algorithm implementation is operating. Reference to the specific implementation of marching cubes used. See for example the following papers for details about how to identify a DOI which specifies the implementation used: * `W. E. Lorensen <https://doi.org/10.1109/MCG.2020.2971284>`_ * `T. S. Newman and H. Yi <https://doi.org/10.1016/j.cag.2006.07.021>`_ The value placed here should be a DOI. If there are no specific DOI or details write not_further_specified, or give at least a free-text description. Commercial or otherwise given name to the program which was used. Program version plus build number, commit hash, or description of an ever persistent resource where the source code of the program and build instructions can be found so that the program can be configured in such a manner that the result file is ideally recreatable yielding the same results. ././@PaxHeader0000000000000000000000000000022600000000000010215 xustar00111 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_parallelogram_set.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_parallelogram_set.nxdl.xm0000644000077000000000000002100314777236751032774 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The cardinality of the set, i.e. the number of parallelograms. Computational geometry description of a set of parallelograms in Euclidean space. The parallelograms do not have to be connected, can have different size, can intersect, and be rotated. This class can also be used to describe rectangles or squares, axis-aligned or not. The class represents different access and description levels to offer both applied scientists and computational geometry experts to use the same base class but rather their specific view on the data: * Most simple many experimentalists wish to communicate dimensions/the size of e.g. a region of interest in the 2D plane. In this case the alignment with axes is not relevant as eventually relevant is only the area of the ROI. * In other cases the extent of the parallelogram is relevant though. * Finally in CAD models we would like to specify the polygon which is parallelogram represents. Parallelograms are important geometrical primitives. Not so much because of their uses in nowadays, thanks to improvements in computing power, not so frequently any longer performed 2D simulation. Many scanning experiments probe though parallelogram-shaped ROIs on the surface of samples. Parallelograms have to be non-degenerated, closed, and built of polygons which are not self-intersecting. The term parallelogram will be used throughout this base class but includes the especially in engineering and more commonly used special cases, rectangle, square, 2D box, axis-aligned bounding box (AABB), or optimal bounding box (OBB) but here the analogous 2D cases. An axis-aligned bounding box is a common data object in computational science and codes to represent a rectangle whose edges are aligned with the axes of a coordinate system. As a part of binary trees these are important data objects for time- as well as space-efficient queries of geometric primitives in techniques like kd-trees. An optimal bounding box is a common data object which provides the best tight fitting box about an arbitrary object. In general such boxes are rotated. Other than in 3D dimensions the rotation calipher method offers a rigorous approach to compute optimal bounding boxes in 2D. A qualitative description of each parallelogram/rectangle/square/box. Qualifier how one edge is longer than all the other edge of the parallelogam. Often the term length is associated with one edge being parallel to an axis of the coordinate system. Qualifier often used to describe the length of an edge within a specific coordinate system. Position of the geometric center, which often is but not necessarily has to be the center_of_mass of the parallelogram. Only to be used if is_box is present. In this case, this field describes whether parallelograms are rectangles/squares whose primary edges are parallel to the axes of the Cartesian coordinate system. Reference to or definition of a coordinate system with which the qualifiers and mesh data are interpretable. Integer which specifies the first index to be used for distinguishing parallelograms. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if the identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Integer used to distinguish parallelograms for explicit indexing. A simple approach to describe the entire set of parallelograms when the main intention is to store the shape of the parallelograms for visualization. Disentangled representations of the mesh of specific parallelograms. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_point_set.nxdl.xml0000644000077000000000000001047214777236751031467 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The dimensionality, which has to be at least 1. The cardinality of the set, i.e. the number of points. Computational geometry description of a set of points in Euclidean space. The relevant coordinate system should be referred to in the NXtransformations instance. Points may have an associated time value; however users are advised to store time data of point sets rather as instances of time events, where for each point in time there is an NXcg_point_set instance which specifies the points locations. This is a frequent situation in experiments and computer simulations, where positions of points are taken at the same point in time; and therefore an additional time array would demand to store redundant pieces of information for each point. Integer which specifies the first index to be used for distinguishing identifiers for points. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if the identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Integer used to distinguish points for explicit indexing. The array of point coordinates. The optional array of time for each vertex. Reference to or definition of a coordinate system with which the positions and directions are interpretable. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_polygon_set.nxdl.xml0000644000077000000000000002375314777236751032033 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The dimensionality, which has to be either 2 or 3. The cardinality of the set, i.e. the number of polygons. The total number of vertices when visiting every polygon. Computational geometry description of a set of polygons in Euclidean space. Polygons are related are specialized polylines: * A polygon is a geometric primitive that is bounded by a closed polyline * All vertices of this polyline lay in the d-1 dimensional plane. whereas vertices of a polyline do not necessarily lay on a plane. * A polygon has at least three vertices. Each polygon is built from a sequence of vertices (points with identifiers). The members of a set of polygons may have a different number of vertices. Sometimes a collection/set of polygons is referred to as a soup of polygons. As three-dimensional objects, a set of polygons can be used to define the hull of what is effectively a polyhedron; however users are advised to use the specific NXcg_polyhedron_set base class if they wish to describe closed polyhedra. Even more general complexes can be thought, for instance piecewise-linear complexes, as these can have holes though, polyhedra without holes are one subclass of such complexes, users should rather design an own base class e.g. NXcg_polytope_set to describe such even more complex primitives. Integer which specifies the first index to be used for distinguishing polygons. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if the identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Integer used to distinguish polygons for explicit indexing. A simple approach to describe the entire set of polygons when the main intention is to store the shape of the polygons for visualization. The accumulated length of the polygon edge. Array of interior angles. There are many values per polygon as number_of_vertices. The angle is the angle at the specific vertex, i.e. between the adjoining edges of the vertex according to the sequence in the polygons array. Usually, the winding_order field is required to interpret the value. Curvature type: * 0 - unspecified, * 1 - convex, * 2 - concave The center of mass of each polygon. Axis-aligned or (approximate) (optimal) bounding boxes to each polygon. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_polyhedron_set.nxdl.xml0000644000077000000000000002063514777236751032523 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The cardinality of the set, i.e. the number of polyhedra. The total number of edges for all polyhedra. The total number of faces for all polyhedra. Computational geometry description of a polyhedra in Euclidean space. Polyhedra, also so-called cells (especially in the convex of tessellations), here described have to be all non-degenerated, closed, built of and thus built out of not-self-intersecting polygon meshes. Polyhedra may make contact, so that this base class can be used for a future description of tessellations. For more complicated manifolds and especially for polyhedra with holes, users are advised to check if their particular needs are described by creating (eventually customized) instances of an NXcg_polygon_set, which can be extended for the description of piecewise-linear complexes. Interior volume Position of the geometric center, which often is but not necessarily has to be the center_of_mass of the polyhedra. Total surface area as the sum of all faces. The number of faces for each polyhedron. Faces of adjoining polyhedra are counted for each polyhedron. This field can be used to interpret the array/field with the individual area values for each face. Area of each of the four triangular faces of each tetrahedron. The number of edges for each polyhedron. Edges of adjoining polyhedra are counterd for each polyhedron. This field can be used to interpret the array/field with the individual length for each edge. Length of each edge of each tetrahedron. Reference to or definition of a coordinate system with which the qualifiers and mesh data are interpretable. Integer which specifies the first index to be used for distinguishing polyhedra. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if the identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Integer used to distinguish polyhedra for explicit indexing. A simple approach to describe the entire set of polyhedra when the main intention is to store the shape of the polyhedra for visualization. Disentangled representations of the mesh of specific polyhedron. Disentangled representation of the planar graph that each polyhedron represents. Such a description simplifies topological processing or analyses of mesh primitive operations and neighborhood queries. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_polyline_set.nxdl.xml0000644000077000000000000002064514777236751032174 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The dimensionality, which has to be at least 1. The cardinality of the set, i.e. the number of polylines. The number of vertices, supporting the polylines. The total number of vertices traversed when visiting every polyline. Computational geometry description of a set of polylines in Euclidean space. Each polyline is built from a sequence of vertices (points with identifiers). Each polyline must have a start and an end point. The sequence describes the positive traversal along the polyline when walking from the start vertex to the end/last vertex. The total number of vertices, irrespective of their eventual uniqueness, i.e. the total number of vertices that have to be visited when walking along each polyline. Array which specifies of how many vertices each polyline is built. The number of vertices represent the total number of vertices for each polyline, irrespectively whether vertices are shared or not. See the docstring for polylines for further details about how a set with different polyline members should be stored. Reference to or definition of a coordinate system with which the qualifiers and polyline data are interpretable. Integer which specifies the first index to be used for distinguishing polylines. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if the identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Integer used to distinguish polylines for explicit indexing. Positions of the vertices which support the members of the polyline set. Users are encouraged to reduce the vertices to unique set of positions and vertices as this supports a more efficient storage of the geometry data. It is also possible though to store the vertex positions naively in which case vertices_are_unique is likely False. Naively here means that one for example stores each vertex of a triangle mesh even though many vertices are shared between triangles and thus the positions of these vertices do not have to be duplicated. If true indicates that the vertices are all placed at different positions and have different identifiers, i.e. no points overlap or are counted twice. Sequence of vertex identifiers which describe each polyline. A trivial example is a set with two polylines with three vertices each. If the polylines meet in a junction, say the second vertex is shared and marking the junction between the two polylines, it is possible that there are only five unique positions suggesting five unique vertices. A non-trivial example is a set with several polylines, each of which with eventually different number of vertices. The array stores the vertex identifiers in the order how the polylines are visited: The first entry is the identifier of the start vertex of the first polyline, followed by the second vertex of the first polyline, until the last vertex of the polyline. Thereafter, the start vertex of the second polyline, and so on and so forth. Using the (cumulated) counts in number_of_vertices, the vertices of the n-th polyline can be accessed on the following array index interval: :math:`[\sum_{i=0}^{i=N-1}, \sum_{i=0}^{i=N}]`. The length of each polyline. If true specifies that a polyline is closed, i.e. its end point is connected to the start point. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_roi_set.nxdl.xml0000644000077000000000000000362014777236751031124 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Base class to hold geometric primitives. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_sphere_set.nxdl.xml0000644000077000000000000001167014777236751031625 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The dimensionality, which has to be at least 2. The cardinality of the set, i.e. the number of circles or spheres. Computational geometry description of a set of spheres in Euclidean space. Each sphere can have a different radius. Integer which specifies the first index to be used for distinguishing identifiers for spheres. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if the identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Integer used to distinguish spheres for explicit indexing. Geometric center of the spheres. This can be the center of mass. Dimensionality and cardinality of the point and sphere set have to match. The identifier_offset and identifier field of NXcg_point_set do not need to be used as they should be same as the identifier_offset and the identifier for the spheres. In the case that all spheres have the same radius. In the case that spheres have different radius use this instead of the radius field. Reference to or definition of a coordinate system with which the positions and directions are interpretable. Are the spheres closed or hollow? ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_tetrahedron_set.nxdl.xml0000644000077000000000000001672314777236751032662 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The cardinality of the set, i.e. the number of tetrahedra. Computational geometry description of a set of tetrahedra in Euclidean space. The tetrahedra do not have to be connected. As tetrahedral elements they are among hexahedral elements one of the most frequently used geometric primitive for meshing and describing volumetric and surface descriptions of objects at the continuum scale. A set of tetrahedra in 3D Euclidean space. The tetrahedra do not have to be connected, can have different size, can intersect, and be rotated. Tetrahedra are the simplest and thus important geometrical primitive. They are frequently used as elements in finite element meshing/modeling. Tetrahedra have to be non-degenerated, closed, and built of triangles which are not self-intersecting. Interior volume Position of the geometric center, which often is but not necessarily has to be the center_of_mass of the tetrahedra. Total surface area as the sum of all four triangular faces. Area of each of the four triangular faces of each tetrahedron. Length of each edge of each tetrahedron. Reference to or definition of a coordinate system with which the qualifiers and mesh data are interpretable. Integer which specifies the first index to be used for distinguishing tetrahedra. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if the identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Integer used to distinguish tetrahedra for explicit indexing. A simple approach to describe the entire set of tetrahedra when the main intention is to store the shape of the tetrahedra for visualization. should take the possibility to describe Disentangled representations of the mesh of specific tetrahedra. Disentangled representation of the planar graph that each tetrahedron represents. Such a description simplifies topological processing or analyses of mesh primitive operations and neighborhood queries. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_triangle_set.nxdl.xml0000644000077000000000000001306614777236751032145 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The dimensionality, which has to be at least 2. The cardinality of the set, i.e. the number of triangles. The number of unique vertices supporting the triangles. Computational geometry description of a set of triangles in Euclidean space. Reference to or definition of a coordinate system with which the qualifiers and primitive data are interpretable. Integer which specifies the first index to be used for distinguishing triangles. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if the identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Integer used to distinguish triangles for explicit indexing. A simple approach to describe the entire set of triangles when the main intention is to store the shape of the triangles for visualization. Array of edge length values. For each triangle the edge length is reported for the edges traversed according to the sequence in which vertices are indexed in triangles. Array of interior angle values. For each triangle the angle is reported for the angle opposite to the edges which are traversed according to the sequence in which vertices are indexed in triangles. The center of mass of each polygon. Axis-aligned or (approximate) (optimal) bounding boxes to each polygon. ././@PaxHeader0000000000000000000000000000023600000000000010216 xustar00119 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_triangulated_surface_mesh.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_triangulated_surface_mesh0000644000077000000000000000466614777236751033137 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Computational geometry description of a mesh of triangles. The mesh may be self-intersecting and have holes but the triangles must not be degenerated. A graph-based approach to describe the mesh when it is also desired to perform topological processing or analyses on the mesh. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcg_unit_normal_set.nxdl.xml0000644000077000000000000000552714777236751032672 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The dimensionality, which has to be at least 2. The cardinality of the set, i.e. the number of unit normals. Computational geometry description of a set of (oriented) unit normal vectors. Direction of each normal Qualifier how which specifically oriented normal to its primitive each normal represents. * 0 - undefined * 1 - outer * 2 - inner ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXchamber.nxdl.xml0000644000077000000000000000324014777236751030406 0ustar00rosborn Component of an instrument to store or place objects and specimens. Given name/alias. Free-text field for describing details about the chamber. For example out of which material was the chamber built. ././@PaxHeader0000000000000000000000000000022600000000000010215 xustar00111 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXchemical_composition.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXchemical_composition.nxdl.xm0000644000077000000000000000523214777236751033024 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The number of samples or things. (Chemical) composition of a sample or a set of things. Total based on which composition information is normalized. Count or weight which, when divided by total yields the composition of this element, isotope, molecule or ion. Count divided by total in atom percent. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcircuit_board.nxdl.xml0000644000077000000000000000373614777236751031630 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Circuit board with e.g. ADC and/or DAC electronic components. Currently used to store the settings of the so-called magboards used in Nion electron microscopes but likely this could be a useful base class for substantially more use cases where details at a deep technical instrument design level are relevant or important. TBD by Nion Co. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXclustering.nxdl.xml0000644000077000000000000001227614777236751031175 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Number of numeral labels per object. Number of categorical labels per object. Total number of clusters detected. Metadata to the results of a clustering analysis. Clustering algorithms are routine tools to segment a set of objects/primitives into groups, objects of different type. A plethora of algorithms have been proposed for geometric primitives as objects, such as points, triangles, or (abstract) objects. This base class considers metadata and results of one clustering applied to a set in which objects are either categorized as noise or belonging to a cluster, specifically here only one cluster. How many numeric labels does each object have. How many categorical labels does each object have. Reference to a set of objects investigated in a cluster analysis. Objects must have clear integer identifier. Reference to numeric attribute data for each object. Reference to categorical attribute data for each object. Which identifier is the first to be used to label a cluster. The value should be chosen in such a way that special values can be resolved: * identifier_offset-1 indicates an object belongs to no cluster. * identifier_offset-2 indicates an object belongs to the noise category. Setting for instance identifier_offset to 1 recovers the commonly used case that objects of the noise category get values to -1 and unassigned points to 0. Total number of objects categorized as unassigned. Total number of objects categorized as noise. Total number of clusters (excluding noise and unassigned). Number of objects associated to each cluster. The labels are implicit, meaning the zeroth/first entry in the array belongs to the first cluster, the second entry to the second cluster and so on and so forth. The first cluster has the value of identifier_offset as its identifier. The second cluster has identifier_offset + 1, and so on and so forth. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcollectioncolumn.nxdl.xml0000644000077000000000000000641214777236751032362 0ustar00rosborn Subclass of NXelectronanalyser to describe the electron collection column of a photoelectron analyser. Scheme of the electron collection lens, i.e. standard, deflector, PEEM, momentum microscope, etc. Voltage applied to the extractor lens Current necessary to keep the extractor lens at a set voltage. Variations indicate leakage, field emission or arc currents to the extractor lens. Distance between sample and detector entrance Labelling of the lens setting in use. The space projected in the angularly dispersive directions, real or reciprocal The magnification of the electron lens assembly. The size and position of an aperture inserted in the column, e.g. field aperture or contrast aperture Deflectors in the collection column section Individual lenses in the collection column section ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcontainer.nxdl.xml0000644000077000000000000001542314777236751030775 0ustar00rosborn State of a container holding the sample under investigation. A container is any object in the beam path which absorbs the beam and whose contribution to the overall attenuation/scattering needs to be determined to process the experimental data. Examples of containers include glass capillary tubes, vanadium cans, windows in furnaces or diamonds in a Diamond Anvil Cell. The following figures show a complex example of a container: .. figure:: container/ComplexExampleContainer.png A hypothetical capillary furnace. The beam passes from left to right (blue dashes), passing through window 1, then window 2, before passing through the downstream wall of the capillary. It is then scattered by the sample with scattered beams passing through the upstream wall of the capillary, then windows 4 and 5. As part of the corrections for a PDF experiment it is necessary to subtract the PDF of the empty container (i.e. each of the windows and the capillary). To calculate the PDF of the empty container it is necessary to have the measured scattering data and to know the nature (e.g. density, elemental composition, etc.) of the portion of the container which the beam passed through. .. figure:: container/ComplexContainerBeampath.png A complete description of the shapes of the container elements with their orientation relative to the beam and also information on whether they are upstream or downstream of the sample is also therefore important. For example, although the windows 2 and 4 have the same shape, the path taken through them by the beam is very different and this needs to be modelled. Furthermore, it is not inconceivable that windows might move during an experiment and thus the changes to the beampath would need to be accounted for. This class encodes the position of the container with respect to the sample and allows the calculation of the beampath through the container. It also includes sufficient data to model beam absorption of the container and a link to a dataset containing a measurement of the container with nothing inside, to allow data corrections (at a specific beam energy/measurement time) to be made. Descriptive name of container. Verbose description of container and how it fits into the wider experimental set up. Chemical composition of the material the container is made from. Specified using CIF conventions. Abbreviated version of CIF standard: * Only recognized element symbols may be used. * Each element symbol is followed by a 'count' number. A count of '1' may be omitted. * A space or parenthesis must separate each cluster of (element symbol + count). * Where a group of elements is enclosed in parentheses, the multiplier for the group must follow the closing parentheses. That is, all element and group multipliers are assumed to be printed as subscripted numbers. * Unless the elements are ordered in a manner that corresponds to their chemical structure, the order of the elements within any group or moiety depends on whether or not carbon is present. * If carbon is present, the order should be: - C, then H, then the other elements in alphabetical order of their symbol. - If carbon is not present, the elements are listed purely in alphabetic order of their symbol. * This is the *Hill* system used by Chemical Abstracts. Density of the material the container is made from. Fraction of the volume of the container occupied by the material forming the container. Relative molecular mass of container. Details of beam incident on container, including the position relative to the sample (to determine whether the container is upstream or downstream of the sample). Shape of the container. In combination with orientation this should allow the beampath through the container to be modelled to allow the adsorption to be calculated. The angle the container makes to the beam and how it may change during the experiment.In combination with shape this should allow the beampath through the container to be modelled to allow the adsorption of the container to be calculated. A link to a full data collection which contains the actual measured data for this container within the experimental set up (with no sample or inner container(s)). This data set will also include the wavelength/energy, measurement time and intensity for which these data are valid. ././@PaxHeader0000000000000000000000000000022700000000000010216 xustar00112 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcoordinate_system_set.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcoordinate_system_set.nxdl.x0000644000077000000000000001733414777236751033073 0ustar00rosborn Container to hold different coordinate systems conventions. It is the purpose of this base class to define these conventions and offer a place to store mappings between different coordinate systems which are relevant for the interpretation of the data described by the application definition and base class instances. For each Cartesian coordinate system users should use a set of NXtransformations: * These should define the three base vectors. * The location of the origin. * The affine transformations which bring each axis of this coordinate system into registration with the McStas coordinate system. * Equally, affine transformations should be given for the inverse mapping. As an example one may take an experiment or computer simulation where there is a laboratory (lab) coordinate system, a sample/specimen coordinate system, a crystal coordinate system, and additional coordinate systems, which are eventually attached to components of the instrument. If no additional transformation is specified in this group or if an instance of an NXcoordinate_system_set is absent it should be assumed the so-called McStas coordinate system is used. Many application definitions in NeXus refer to this `McStas <https://mailman2.mcstas.org/pipermail/mcstas-users/2021q2/001431.html>`_ coordinate system. This is a Cartesian coordinate system whose z axis points along the neutron propagation axis. The systems y axis is vertical up, while the x axis points left when looking along the z-axis. Thus, McStas is a right-handed coordinate system. Within each NXtransformations a depends_on section is required. The depends_on field specifies if the coordinate system is the root/reference (which is indicated by writing "." in the depends_on section.) A group of transformations which specify: * Three base vectors of the coordinate system. * Origin of the coordinate system. * A depends_on keyword. Its value can be "." or the name of an NXtransformations instance which needs to exist in the NXcoordinate_system_set instance. * If the coordinate system is the reference one it has to be named reference. In case of having more than one NXtransformations there has to be for each additional coordinate system, i.e. the one not the reference: * A set of translations and rotations which map each base vector to the reference. * A set of translations and rotations which map each reference base vector to the coordinate system. The NXtransformations for these mappings need to be formatted according to the descriptions in NXtransformations. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcorrector_cs.nxdl.xml0000644000077000000000000000667614777236751031514 0ustar00rosborn Corrector for aberrations in an electron microscope. Different technology partners use different naming schemes and models for quantifying the aberration coefficients. The corrector in an electron microscope is composed of multiple lenses and multipole stigmators with vendor-specific details which are often undisclosed. Specific information about the concrete alignment procedure which is a process during which the corrector is configured to enable a calibrated usage of the microscope. Discouraged free-text field to add further details about the alignment procedure. The outer tilt angle of the beam in tableau aquisition. The exposure time of the single tilt images. The factor of enlargement of the apparent size, not physical size, of an object. Place for storing measured or estimated aberrations (for each image or final). ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcs_computer.nxdl.xml0000644000077000000000000000613514777236751031336 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Computer science description of a set of computing nodes. Given name/alias to the computing system, e.g. MyDesktop. Name of the operating system, e.g. Windows, Linux, Mac, Android. Version plus build number, commit hash, or description of an ever persistent resource where the source code of the program and build instructions can be found so that the program can be configured in such a manner that the result file is ideally recreatable yielding the same results. Ideally a (globally) unique persistent identifier of the computer, i.e. the Universally Unique Identifier (UUID) of the computing node. A list of physical processing units (can be multi-core chips). A list of physical coprocessor/graphic cards/accelerator units. Details about the memory sub-system. Details about the I/O sub-system. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcs_cpu.nxdl.xml0000644000077000000000000000325514777236751030267 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Computer science description of a central processing unit (CPU) of a computer. Given name of the CPU. Users should be as specific as possible. ././@PaxHeader0000000000000000000000000000023000000000000010210 xustar00113 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcs_filter_boolean_mask.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcs_filter_boolean_mask.nxdl.0000644000077000000000000001171714777236751032760 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Number of entries (e.g. number of points or objects). Number of bits assumed for the container datatype used. Length of mask considering the eventual need for padding. Computer science base class for packing and unpacking booleans. One use case is processing of object sets (like point cloud data). When one applies e.g. a spatial filter to a set of points to define which points are analyzed and which not, it is useful to document which points were taken. One can store this information in a compact manner with an array of boolean values. If the value is True the point is taken, else it is not. If the points are identified by an array of integer identifiers and an arbitrary spatial filtering, the boolean array will be filled with True and False values in an arbitrary manner. Especially when the number of points is large, for instance several thousands and more, some situations can be more efficiently stored if one would not store the boolean array but just list the identifiers of the points taken. For instance if within a set of 1000 points only one point is taken, it would take (naively) 4000 bits to store the array but only 32 bits to store e.g. the ID of that taken point. Of course the 4000 bit field is so sparse that it could be compressed resulting also in a substantial reduction of the storage demands. Therefore boolean masks are useful compact descriptions to store information about set memberships in a compact manner. In general it is true, though, that which representation is best, i.e. most compact (especially when compressed) depends strongly on occupation of the array. This base class just bookkeeps metadata to inform software about necessary modulo operations to decode the set membership of each object. This is useful because the number of objects not necessarily is an integer multiple of the bit depth. Number of objects represented by the mask. Number of bits assumed matching on a default datatype. (e.g. 8 bits for a C-style uint8). The unsigned integer array representing the content of the mask. If padding is used the padded bits have to be set to 0. Link to/or array of identifiers for the objects. The decoded mask is interpreted consecutively, i.e. the first bit in the mask matches to the first identifier, the second bit in the mask to the second identifier and so on and so forth. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcs_gpu.nxdl.xml0000644000077000000000000000325514777236751030273 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Computer science description of a graphic processing unit (GPU) of a computer. Given name of the GPU. Users should be as specific as possible. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcs_io_obj.nxdl.xml0000644000077000000000000000421314777236751030734 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Computer science description of a storage object in an input/output system. Qualifier for the type of storage medium used. Total amount of data which the medium can hold. Given name to the I/O unit. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcs_io_sys.nxdl.xml0000644000077000000000000000300614777236751030777 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Computer science description of system of a computer. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcs_mm_sys.nxdl.xml0000644000077000000000000000325714777236751031011 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Computer science description of a main memory system of a computer. How much physical memory does the system provide. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcs_prng.nxdl.xml0000644000077000000000000000774514777236751030456 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Computer science description of pseudo-random number generator. The purpose of such metadata is to identify if exactly the same sequence can be reproduced, like for a PRNG or not (for a true physically random source). Different approaches for generating random numbers with a computer exists. Some use a dedicated physical device where the state is unpredictable (physically). Some use a mangling of the system clock (system_clock), where also without additional pieces of information the sequence is not reproducible. Some use so-called pseudo-random number generator (PRNG) are used. These are algorithms which yield a deterministic sequence of practically randomly appearing numbers. These algorithms different in their quality in how close the resulting sequences are random. Nowadays one of the most commonly used algorithm is the MersenneTwister (mt19937). Name of the PRNG implementation and version. If such information is not available or if the PRNG type was set to other the DOI to the publication or the source code should be given. Version and build number, or commit hash. Parameter of the PRNG controlling its initialization and thus the specific sequence of numbers it generates. Number of initial draws from the PRNG which are discarded in an effort to equilibrate the sequence and make it thus to statistically more random. If no warmup was performed or if warmup procedures are unclear, users should set the value to zero. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcs_profiling.nxdl.xml0000644000077000000000000001664214777236751031475 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Computer science description for summary performance/profiling data of an application. Performance monitoring and benchmarking of software is a task where questions can be asked at various levels of detail. In general, there are three main contributions to performance: * Hardware capabilities and configuration * Software configuration and capabilities * Dynamic effects of the system in operation and the system working together with eventually multiple computers, especially when these have to exchange information across a network. At the most basic level users may wish to document how long e.g. a data analysis with a scientific software (app). A frequent idea is here to judge how critical the effect is on the workflow of the scientists, i.e. is the analysis possible in a few seconds or would it take days if I were to run this analysis on a comparable machine. In this case, mainly the order of magnitude is relevant, as well as how this can be achieved with using parallelization (i.e. reporting the number of CPU and GPU resources used, the number of processes and/or threads, and basic details about the computing node/computer. At more advanced levels benchmarks may go as deep as detailed temporal tracking of individual processor instructions, their relation to other instructions, the state of call stacks, in short eventually the entire app execution history and hardware state history. Such analyses are mainly used for performance optimization as well as for tracking bugs and other development purposes. Specialized software exists which documents such performance data in specifically-formatted event log files or databases. This base class cannot and should not replace these specific solutions. Instead, the intention of the base class is to serve scientists at the basic level to enable simple monitoring of performance data and log profiling data of key algorithmic steps or parts of computational workflows, so that these pieces of information can guide users which order of magnitude differences should be expected or not. Developers of application definitions should add additional fields and references to e.g. more detailed performance data to which they wish to link the metadata in this base class. Path to the directory from which the tool was called. Command line call with arguments if applicable. ISO 8601 time code with local time zone offset to UTC information included when the app was started. ISO 8601 time code with local time zone offset to UTC information included when the app terminated or crashed. Wall-clock time how long the app execution took. This may be in principle end_time minus start_time; however usage of eventually more precise timers may warrant to use a finer temporal discretization, and thus demand a more precise record of the wall-clock time. Qualifier which specifies with how many nominal processes the app was invoked. The main idea behind this field, for instance for app using a Message Passing Interface parallelization is to communicate how many processes were used. For sequentially running apps number_of_processes and number_of_threads is 1. If the app uses exclusively GPU parallelization number_of_gpus can be larger than 1. If no GPU is used number_of_gpus is 0 even though the hardware may have GPUs installed, thus indicating these were not used though. Qualifier with how many nominal threads were accessible to the app at runtime. Specifically here the maximum number of threads used for the high-level threading library used (e.g. OMP_NUM_THREADS), posix. Qualifier with how many nominal GPUs the app was invoked at runtime. A collection with one or more computing nodes each with own resources. This can be as simple as a laptop or the nodes of a cluster computer. A collection of individual profiling event data which detail e.g. how much time the app took for certain computational steps and/or how much memory was consumed during these operations. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcs_profiling_event.nxdl.xml0000644000077000000000000000754414777236751032677 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Number of processes. Computer science description of a profiling event. ISO 8601 time code with local time zone offset to UTC information included when the event tracking started. ISO 8601 time code with local time zone offset to UTC information included when the event tracking ended. Free-text description what was monitored/executed during the event. Wall-clock time how long the event took. This may be in principle end_time minus start_time; however usage of eventually more precise timers may warrant to use a finer temporal discretization, and thus demand a more precise record of the wall-clock time. Elapsed time may contain time portions where resources were idling. Number of processes used (max) during the execution of this event. Number of threads used (max) during the execution of this event. Number of GPUs used (max) during the execution of this event. Maximum amount of virtual memory allocated per process during the event. Maximum amount of resident memory allocated per process during the event. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcsg.nxdl.xml0000644000077000000000000000543614777236751027572 0ustar00rosborn Constructive Solid Geometry base class, using :ref:`NXquadric` and :ref:`NXoff_geometry` One of the standard construction solid geometry set operations, or if the CSG is a pointer to the geometry provided by an :ref:`NXquadric` or an :ref:`NXoff_geometry`. Takes values: The first operand of constructive solid geometry operation. Compulsory if 'operation' is UNION, INTERSECTION, DIFFERENCE or COMPLEMENT. The second operand of constructive solid geometry operation. Compulsory if 'operation' is UNION, INTERSECTION or DIFFERENCE. Path to a field that is either an :ref:`NXquadric` (if 'operation' = IS_QUADRIC) or an :ref:`NXoff_geometry` (if 'operation' = IS_MESH) that defines the surface making up the constructive solid geometry component. Compulsory if 'operation' is IS_QUADRIC or IS_MESH. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXcxi_ptycho.nxdl.xml0000644000077000000000000002400014777236751031153 0ustar00rosborn These symbols will be used below to coordinate the shapes of the datasets. The number of points in the x direction Number of points in the y direction. Number of detector pixels in x Number of detector pixels in y Application definition for a ptychography experiment, compatible with CXI from version 1.6. This is compatible with CXI from version 1.6 if this application definition is put at the top "entry" level. Above this a "cxi_version" field should be defined. The CXI format is name based, rather than class based, and so it is important to pay attention to the naming convention to be CXI compatible. There are duplications due to the format merger. These should be achieved by linking, with hdf5 Virtual Dataset being used to restructure any data that needs to be remapped. To be fully CXI compatible, all units (including energy) must be in SI units. An example here is that CXI expects the data to always to have shape (npts_x*npts_y, frame_size_x, frame_size_y). For nexus this is only true for arbitrary scan paths with raster format scans taking shape (npts_x, npts_y, frame_size_x, frame_size_y). Official NeXus NXDL schema to which this file conforms This is the energy of the machine, not the beamline. should have value "[, data]" should have value "data" This is an array of shape (npts_x*npts_y, 3) and can be a Virtual Dataset of x and y this should take the value "translation:$slowaxisname:$fastaxisname" This should be "image" This data must always have shape (npts_x*npts_y, frame_size_x, frame_size_y) regardless of the scan pattern. Use hdf5 virtual dataset to achieve this. The distance between the detector and the sample This should be "[x,.]" for arbitrary scanning patterns, and "[x,.,.]" for raster This should be "data" To ensure CXI compatibility the data in this group must always have shape that is (npts_x*npts_y, frame_size_x, frame_size_y). For nexus-style raster scans it is proposed that hdf5 virtual dataset is used. This must contain two fields with the x and y motors that are linked via the dependency tree according to the real-life motor layout dependency. For raster scans x and y will have shape (npts_x, npts_y) For arbitrary scans x and y will be (npts_x*npts_y,) An attribute with the units for each motor is required. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXdac.nxdl.xml0000644000077000000000000000313614777236751027540 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Digital-to-analog converter component/integrated circuit. TBD. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXdeflector.nxdl.xml0000644000077000000000000000456214777236751030764 0ustar00rosborn Deflectors as they are used e.g. in an electron analyser. Qualitative type of deflector with respect to the number of pole pieces Colloquial or short name for the deflector. For manufacturer names and identifiers use ``NXfabrication`` and ``identifierNAME``. Excitation voltage of the deflector. For dipoles it is a single number. For higher orders, it is an array. Excitation current of the deflector. For dipoles it is a single number. For higher orders, it is an array. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXdelocalization.nxdl.xml0000644000077000000000000001457114777236751032017 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Number of points/objects. Number of mark data per point/object. Number of atoms in the whitelist. Number of isotopes in the whitelist. Base class to describe the delocalization of point-like objects on a grid. Such a procedure is for instance used in image processing and e.g. atom probe microscopy (APM) to discretize a point cloud onto a grid to enable e.g. computing of point density, composition, or concentration values, obtain scalar fields, and compute gradients of these fields. Reference or link to the grid on which the delocalization is applied. Reference or link to the points which are delocalized on the grid. The weighting model specifies how mark data are mapped to a weight per point. For atom probe microscopy (APM) as an example, different models are used which account differently for the multiplicity of an ion/atom: * default, points all get the same weight 1.; for APM this is equivalent to ion species * atomic_decomposition, points get as much weight as they have atoms of a type in element_whitelist, * isotope_decomposition, points get as much weight as they have isotopes of a type in isotope_whitelist. This description shows an example that could be reinterpreted for similar such data processing steps in other fields of science. A list of elements (via proton number) to consider for the atomic_decomposition weighting model. Elements must exist in the periodic table of elements. A list of isotopes to consider for the isotope_decomposition weighting model. Isotopes must exist in the nuclid table. Entries in the fastest changing dimension should be the pair of proton (first entry) and neutron number (second entry). Attribute data for each member of the point cloud. For APM these are the ion species labels generated via ranging. The number of mark data per point is 1 in the case for atom probe. Weighting factor with which the integrated intensity per grid cell is multiplied specifically for each point. For APM the weight are positive integer values, specifically the multiplicity of the ion, according to the details of the weighting_model. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXdispersion.nxdl.xml0000644000077000000000000000325714777236751031174 0ustar00rosborn A dispersion denoting a sum of different dispersions. All NXdispersion_table and NXdispersion_function groups will be added together to form a single dispersion. The name of the composite model. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXdispersion_function.nxdl.xml0000644000077000000000000001161614777236751033077 0ustar00rosborn The number of repetitions for the repeated parameters This describes a dispersion function for a material or layer The name of this dispersion model. This should be a python parsable function. Here we should provide which keywords are available and a BNF of valid grammar. The sign convention being used (n + or - ik) The identifier used to represent energy in the formula. It is recommended to use `E`. The minimum energy value at which this formula is valid. The maximum energy value at which this formula is valid. The energy unit used in the formula. The field value is a scaling factor for the units attribute. It is recommeded to set the field value to 1 and carry all the unit scaling information in the units attribute. The identifier useed to represent wavelength in the formula. It is recommended to use `lambda`. The wavelength unit used in the formula. The field value is a scaling factor for the units attribute. It is recommeded to set the field value to 1 and carry all the unit scaling information in the units attribute. The minimum wavelength value at which this formula is valid. The maximum wavelength value at which this formula is valid. Which representation does the formula evaluate to. This may either be n for refractive index or eps for dielectric function. The appropriate token is then to be used inside the formula. ././@PaxHeader0000000000000000000000000000023700000000000010217 xustar00120 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXdispersion_repeated_parameter.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXdispersion_repeated_paramete0000644000077000000000000000503214777236751033151 0ustar00rosborn The number of parameter repetitions A repeated parameter for a dispersion function The name of the parameter A description of what this parameter represents A unit array associating a unit with each parameter. The first element should be equal to values/@unit. The values should be SI interpretable standard units with common prefixes (e.g. mikro, nano etc.) or their short-hand notation (e.g. nm, mm, kHz etc.). The value of the parameter ././@PaxHeader0000000000000000000000000000023500000000000010215 xustar00118 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXdispersion_single_parameter.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXdispersion_single_parameter.0000644000077000000000000000337314777236751033107 0ustar00rosborn A single parameter for a dispersion function The name of the parameter A description of what this parameter represents The value of the parameter ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXdispersion_table.nxdl.xml0000644000077000000000000000653014777236751032340 0ustar00rosborn The symbols in this schema to denote the dimensions The number of energy and dielectric function points A dispersion table denoting energy, dielectric function tabulated values. The name of this dispersion model. The sign convention being used (n + or - ik) The wavelength array of the tabulated dataset. This is essentially a duplicate of the energy field. There should be one or both of them present. The energy array of the tabulated dataset. This is essentially a duplicate of the wavelength field. There should be one or both of them present. The refractive index array of the tabulated dataset. The dielectric function of the tabulated dataset. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXdispersive_material.nxdl.xml0000644000077000000000000002564614777236751033056 0ustar00rosborn NXdispersion An application definition for a dispersive material. Version number to identify which definition of this application definition was used for this entry/data. URL where to find further material (documentation, examples) relevant to the application definition Name of the program used for creating this dispersion Version of the program used Date and time of creating this dispersion. List of comma-separated elements from the periodic table that are contained in the sample. If the sample substance has multiple components, all elements from each component must be included in `atom_types`. The colloquial name of the material, e.g. graphite or diamond for carbon. The phase of the material Additional information about the phase if the material phase is other. This field may be used to denote additional phase information, such as crystalin phase of a crystal (e.g. 4H or 6H for SiC) or if a measurement was done on a thin film or bulk material. Denotes whether the dispersion is calculated or derived from an experiment A text description of this reference, e.g. `E. Example et al, The mighty example, An example journal 50 (2023), 100` The dispersion along the optical axis of the material. This should be the only dispersion available for isotropic materials. For uniaxial materials this denotes the ordinary axis. For biaxial materials this denotes the x axis or epsilon 11 tensor element of the diagionalized permittivity tensor. The name of this dispersion model. This should only be filled for biaxial materials. It denotes the epsilon 22 direction of the diagionalized permittivity tensor. The name of this dispersion model. This should only be filled for uniaxial or biaxial materials. For uniaxial materials this denotes the extraordinary axis. For biaxial materials this denotes the epsilon 33 tensor element of the diagionalized perimittivty tensor. The name of this dispersion model. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXebeam_column.nxdl.xml0000644000077000000000000001001314777236751031427 0ustar00rosborn Container for components to form a controlled beam in electron microscopy. The source which creates the electron beam. Voltage relevant to compute the energy of the electrons immediately after they left the gun. Type of radiation. Emitter type used to create the beam. If the emitter type is other, give further details in the description field. Material of which the emitter is build, e.g. the filament material. Ideally, a (globally) unique persistent identifier, link, or text to a resource which gives further details. Affine transformation which detail the arrangement in the microscope relative to the optical axis and beam path. A sensor used to monitor an external or internal condition. Individual ocharacterization results for the position, shape, and characteristics of the electron beam. NXtransformations should be used to specify the location of the position at which the beam was probed. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXelectronanalyser.nxdl.xml0000644000077000000000000001265014777236751032364 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays Number of fast axes (axes acquired symultaneously, without scanning a pysical quantity) Number of slow axes (axes acquired scanning a pysical quantity) Subclass of NXinstrument to describe a photoelectron analyser. Free text description of the type of the detector Name or model of the equipment Acronym or other shorthand name Energy resolution of the electron analyser (FWHM of gaussian broadening) Momentum resolution of the electron analyser (FWHM) Angular resolution of the electron analyser (FWHM) Spatial resolution of the electron analyser (Airy disk radius) List of the axes that are acquired simultaneously by the detector. These refer only to the experimental variables recorded by the electron analyser. Other variables such as temperature, manipulator angles etc. are labeled as fast or slow in the data. .. csv-table:: Examples :header: "Mode", "fast_axes", "slow_axes" Hemispherical in ARPES mode, "['energy', 'kx']","" "Hemispherical with channeltron, sweeping energy mode", "", [\"energy\"] "Tof", "['energy', 'kx', 'ky']","" "Momentum microscope, spin-resolved", "['energy', 'kx', 'ky']", "['spin up-down', 'spin left-right']" Axes may be less abstract than this, i.e. ['detector_x', 'detector_y']. If energy_scan_mode=sweep, fast_axes: ['energy', 'kx']; slow_axes: ['energy'] is allowed. List of the axes that are acquired by scanning a physical parameter, listed in order of decreasing speed. See fast_axes for examples. Describes the electron collection (spatial and momentum imaging) column Describes the energy dispersion section Describes the spin dispersion section Describes the electron detector Deflectors outside the main optics ensambles described by the subclasses Individual lenses outside the main optics ensambles described by the subclasses ././@PaxHeader0000000000000000000000000000022600000000000010215 xustar00111 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXelectrostatic_kicker.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXelectrostatic_kicker.nxdl.xm0000644000077000000000000000467614777236751033044 0ustar00rosborn definition for a electrostatic kicker. extended description of the kicker. define position of beamline element relative to production target kicker timing as defined by ``description`` attribute current set on supply. current read from supply. volage set on supply. voltage read from supply. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXellipsometry.nxdl.xml0000644000077000000000000004112714777236751031543 0ustar00rosborn Variables used throughout the document, e.g. dimensions or parameters. Length of the spectrum array (e.g. wavelength or energy) of the measured data. Number of sensors used to measure parameters that influence the sample, such as temperature or pressure. Number of measurements (1st dimension of measured_data array). This is equal to the number of parameters scanned. For example, if the experiment was performed at three different temperatures and two different pressures N_measurements = 2*3 = 6. Number of detection angles of the beam reflected or scattered off the sample. Number of angles of incidence of the incident beam. Number of observables that are saved in a measurement. e.g. one for intensity, reflectivity or transmittance, two for Psi and Delta etc. This is equal to the second dimension of the data array 'measured_data' and the number of column names. Number of time points measured, the length of NXsample/time_points Ellipsometry, complex systems, up to variable angle spectroscopy. Information on ellipsometry is provided, e.g. in: * H. Fujiwara, Spectroscopic ellipsometry: principles and applications, John Wiley & Sons, 2007. * R. M. A. Azzam and N. M. Bashara, Ellipsometry and Polarized Light, North-Holland Publishing Company, 1977. * H. G. Tompkins and E. A. Irene, Handbook of Ellipsometry, William Andrew, 2005. Open access sources: * https://www.angstromadvanced.com/resource.asp * https://pypolar.readthedocs.io/en/latest/ Review articles: * T. E. Jenkins, "Multiple-angle-of-incidence ellipsometry", J. Phys. D: Appl. Phys. 32, R45 (1999), https://doi.org/10.1088/0022-3727/32/9/201 * D. E. Aspnes, "Spectroscopic ellipsometry - Past, present, and future", Thin Solid Films 571, 334-344 (2014), https://doi.org/10.1016/j.tsf.2014.03.056 * R. M. A. Azzam, "Mueller-matrix ellipsometry: a review", Proc. SPIE 3121, Polarization: Measurement, Analysis, and Remote Sensing, (3 October 1997), https://doi.org/10.1117/12.283870 * E. A. Irene, "Applications of spectroscopic ellipsometry to microelectronics", Thin Solid Films 233, 96-111 (1993), https://doi.org/10.1016/0040-6090(93)90069-2 * S. Zollner et al., "Spectroscopic ellipsometry from 10 to 700 K", Adv. Opt. Techn., (2022), https://doi.org/10.1515/aot-2022-0016 This is the application definition describing ellipsometry experiments. Such experiments may be as simple as identifying how a reflected beam of light with a single wavelength changes its polarization state, to a variable angle spectroscopic ellipsometry experiment. The application definition defines: * elements of the experimental instrument * calibration information if available * parameters used to tune the state of the sample * sample description An application definition for ellipsometry. Version number to identify which definition of this application definition was used for this entry/data. URL where to find further material (documentation, examples) relevant to the application definition. An optional free-text description of the experiment. However, details of the experiment should be defined in the specific fields of this application definition rather than in this experiment description. Specify the type of ellipsometry. Properties of the ellipsometry equipment. Name of the company which build the instrument. ISO8601 date when the instrument was constructed. UTC offset should be specified. Commercial or otherwise defined given name of the program that was used to generate the result file(s) with measured data and metadata. This program converts the measured signals to ellipsometry data. If home written, one can provide the actual steps in the NOTE subfield here. What type of ellipsometry was used? See Fujiwara Table 4.2. Define which element rotates, e.g. polarizer or analyzer. Specify the used light source. Multiple selection possible. If focussing probes (lenses) were used, please state if the data were corrected for the window effects. Were the recorded data corrected by the window effects of the focussing probes (lenses)? Specify the angular spread caused by the focussing probes. Properties of the detector used. Integration time is the count time field, or the real time field. See their definition. Properties of the rotating element defined in 'instrument/rotating_element_type'. Define how many revolutions of the rotating element were averaged for each measurement. If the number of revolutions was fixed to a certain value use the field 'fixed_revolutions' instead. Define how many revolutions of the rotating element were taken into account for each measurement (if number of revolutions was fixed to a certain value, i.e. not averaged). Specify the maximum value of revolutions of the rotating element for each measurement. The spectroscope element of the ellipsometer before the detector, but often integrated to form one closed unit. Information on the dispersive element can be specified in the subfield GRATING. Note that different gratings might be used for different wavelength ranges. The dispersion of the grating for each wavelength range can be stored in grating_dispersion. Was the backside of the sample roughened? Relevant for infrared ellipsometry. Select which type of data was recorded, for example Psi and Delta (see: https://en.wikipedia.org/wiki/Ellipsometry#Data_acquisition). It is possible to have multiple selections. Data types may also be converted to each other, e.g. a Mueller matrix contains N,C,S data as well. This selection defines how many columns (N_observables) are stored in the data array. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXem.nxdl.xml0000644000077000000000000041270414777236751027417 0ustar00rosborn Characterization of a sample during a session on an electron microscope. **The idea and aim of NXem**: Electron microscopy (EM) research, whether it be performed with scanning electron microscope (SEM) or transmission electron microscope (TEM) instruments, uses versatile tools for preparing and characterizing samples and specimens. The term specimen is considered a synonym for sample in this application definition. A specimen is a physical portion of material that is studied/characterized during the microscope session, eventually in different places on the specimen surface, illuminating the surface layers or shining through thin specimens. These places are named regions of interest (ROIs). Fundamentally, an electron microscope is an electron accelerator. Experimentalists use it in sessions during which they characterize as well as prepare specimens. This application definition describes data and metadata about processes and characterization tasks applied to one specimen. The application definition focuses on the usage of EM in materials research. The application definition design makes it in principle applicable also in cryo-EM on biomaterials. Multiple specimens have to be described with multiple :ref:`NXentry` instances. **Electron microscopes motivate the development of a comprehensive data schema:** There are research groups who use an EM in a manner where it is exclusively operated by a single, instrument-responsible scientists or a team of scientists. These users may perform analyses for other users as a service task, especially in large research facility settings. Oftentimes, though, and especially for cutting-edge instruments, the scientists guide the process and maybe even control the microscope. Instruments are usually controlled on-premises but also more and more functionalities for remote control have become available. Scientists oftentimes can ask technicians for support. In all cases, these people are considered users. Users might have different roles though. The rational behind a common EM schema rather than making separate schemas for SEM or TEM are primarily the key similarities of SEM and TEM instruments: Both type of instruments have electro-magnetic lenses. These may differ in design, alignment, number, and level of corrected for aberrations. As an obvious difference, a TEM is mainly used for measuring the transmitted electron beam. This calls for using a different lens setup and relative placement of the specimen in the lens setup. Also TEM specimens are substantially thinner than specimens characterized with SEM to enable an illumination through the specimen. This offers capabilities for probing of additional physical mechanisms of electron-matter interaction which are unavailable in SEMs. Nevertheless, both types of electron microscopes use detector systems which measure different types of signals that originate from the same set of radiation/specimen interactions. Often these detectors have a similar design and technology or are even used both in SEMs and TEMs. **A comprehensive schema instead of specific SEM or TEM schemas**: Given these physical and technical differences, different instruments have been developed. This led to a coexistence of two broad interacting communities: SEM and TEM users. From a data science perspective, we acknowledge that the more specific a research question is and the narrower it is the addressed circle of users which develops or uses schemas for research data management (RDM) with EM, the more understandable it is that scientists of either community (or sub-community) ask for designing method-specific schemas. Researchers who have a single (main) microscope of some vendor in their lab, may argue they need an NXem_vendor_name schema or an NXem_microscope_name or an NXem_sem or a NXem_tem schema. Scientists exclusively working with one technique or type of signal probed (X-rays, electrons) may argue they wish to be pragmatic and store only what is immediately relevant for their particular technique and research questions. In effect, they may advocate for method-specific schemas such as NXem_ebsd, NXem_eels, NXem_edx, or NXem_imaging. However, the history of electron microscopy has shown that these activities led to a zoo of schemas and vocabulary, with implementation in many data and file formats, difficult to make interoperable. Instead of trying to maintain this, we would like to advocate that the `FAIR principles <https://doi.org/10.1038/sdata.2016.18>`_ should guide all decisions how data and metadata should be stored. EM instruments, software, and research are moving targets. Consequently, there is a key challenge and inconvenience with having many different schemas with associated representations of data and metadata: Each combination of schemas or an interoperable-made handshake between two file formats or software packages has to be maintained by software developers. This counts especially when data should be processed interoperably between software packages. This brings two problems: Many software tools and parsers for the handshaking between tools have to be maintained. This can result in usage of different terminology, which in turn results in representations and connections made between different data representations and workflows that are not machine-actionable. `There are community efforts to harmonize the terminology. <https://gitlab.hzdr.de/em_glossary/em_glossary>`_ **The advantage of working towards a common vocabulary and representation**: A common vocabulary can serve interoperability as developers of schemas and scientists can reuse for instance these terms, thus supporting interoperability. Ideally, scientists specialize an application definition only for the few very specific additional quantities of their instruments and techniques. This is better than reimplementing the wheel for descriptions of EM instruments. This route of more standardization can support the EM community in that it removes the necessity for having to maintain a very large number of schemas. Aiming for more standardization, i.e. a lower number of schemas rather than a single standard for electron microscopy is a compromise that can serve academia and industry as it enables a focusing of software development efforts on those schemas, on fixing and discussing them, and on harmonizing their common vocabulary. These activities can be specifically relevant also for technology partners building EM hard- and software as it improves the longevity of certain schemas; and thus can help with incentivizing them to support the community with implementing support for such schemas into their applications. In effect, everybody can gain from this as it will likely reduce the cases in which scientists have to fix bugs in making their own tools compliant and interoperable with tools of their colleagues and the wider community. The here proposed NXem application definition offers modular components (EM-research specific base classes) for defining schemas for EM research. Thereby, NXem can be useful to extends top-level ontologies towards a domain- and method-specific ontology for electron microscopy as it is used for materials research. Working towards a common vocabulary is a community activity that profits from everybody reflecting in detail whether certain terms they have used in the past are not eventually conceptually similar if not the same as what this application definition and its base classes provide. We are happy for receiving your feedback. **Addressing the generality versus specificity challenge**: It is noteworthy to understand that (not only for NeXus), schemas differ already if at least one field is required in one version of the schema, but it is set optional in another schema. If group(s), field(s), or attributes are removed or added, or even a docstring is changed, schemas can become inconsistent. It is noteworthy to mention that the idea of a NeXus application definition serves as a contract between a data provider and a data consumer. Providers can be the software of a specific microscopes or users with specific analysis needs. Consumers can be again specific software tools, like vendor software for controlling the instrument or a scientific software for doing artificial intelligence analyses on EM data). Such changes of a schema lead to new versions. **Verification of constraints and conditions**: Tools like NeXus do not avoid or protect against all such possible inconsistencies; however NeXus offers a mechanism and toolset, through which schemas can be documented and defined. In effect, having an openly documented (at a case-specific level of technical detail) schema is a necessary but alone not a sufficient step to take EM research on a route of machine-actionable and interoperable FAIR data. This stresses again the fundamental and necessary role of working towards a common vocabulary and, with a longer perspective in mind, a machine-actionable knowledge representation and verification engine. So far many conditions and requirements are formulated in the docstrings of the respective entries of the application definition. **NXem takes a key step towards standardization of EM data schemas**. It offers a controlled vocabulary and set of relations between concepts and enables the description of the data which are collected for research with electron microscopes. To be most efficient and offering reusability, the NXem application definition should be understood as a template that one should ideally use as is. NXem can be considered a base for designing more specialized definitions. These should ideally be prefixed with NXem_method (e.g. NXem_ebsd). **The use of NXem should be as follows:** Offspring application definitions should not remove groups but leave these optional or, even better, propose changes to NXem. A particular challenge with electron microscopes as physical instruments are their dynamics. To make EM data understandable, repeatable, and eventually corresponding experiments reproducible in general requires a documentation of the spatio-temporal dynamics of the instrument in its environment. It is questionable to which level such a reproducibility is possible with EM at all considering beam damage, effects of the environment, and other not exactly quantifiable influences. While this points to the physical limitations there are also practical and economical constraints on how completely EM research can be documented: For most commercial systems there is a specific accessibility beyond which detailed settings like lens excitations and low-level hardware settings may not be retrievable as technology partners have a substantiated interest in finding a compromise between being open to their users and securing their business models. By design, EM experiments illuminate the specimen with electrons as a consequence of which the specimen changes if not may get destroyed. As such, repeatability of numerical processing and clear descriptions of procedures and system setups should be addressed first. If especially a certain simulation package needs a detailed view of the geometry of the lens system and its excitations during the course of the experiment, it is difficult to fully abstract the technical details of the hardware into a set of names for fields and groups that make for a compromise between clarity but being system-agnostic at the same time. Settings of apertures are an example where aperture modes are in most cases aliases behind which there is a set of very detailed settings specific to the software and control units used. These settings are difficult to retrieve, are not fully documented by technology partners. This simplification for users of microscopes makes experiments easier understandable. On the flipside these subtilities limit the opportunities of especially open- source developments to make data schemas covering enough for general usage and specific enough and sufficiently detailed to remain useful for research by electron microscopy domain experts. Instead, currently it is for the docstring to specify what is conceptually eventually behind such aliases. The design rule we followed while drafting this NXem application definition and base classes is that there are numerous (technical) details about an EM which may warrant a very detailed technical disentangling of settings and reflection of numerous settings as deeply nested groups, fields and attributes. An application definition can offer a place to hold these nested representations; however as discussed at the cost of generality. Which specific details matter for answering scientific research questions is a difficult question to answer by a single team of scientists, especially if the application definition is to speak for a number of vendors. What makes it especially challenging is when the application definition is expected to hold all data that might be of relevance for future questions. We are skeptical if there is one such representation that can fulfill all these aims and interest, while remaining at the same time approachable and executable by a large number of scientists in a community. However, we are also convinced that this is not a reason to accept the status quo of having a very large set of oftentimes strongly overlapping and redundant schemas. NXem is our proposal to motivate the EM community to work towards more standardization and discussion of what constitutes data, i.e. metadata, numerical and categorical data in research with electron microscopes. We found that existent terminology can be encoded into a more controlled vocabulary. We have concluded that despite all these details of current EM research with SEM, TEM, and focused-ion beam instruments, there a clearly identifiable common components and generalizable settings of EM research use cases. Therefore, **This application definition has the following components at the top-level:** * Each signal, such as a spectrum or image taken at the microscope, should have an associated time-zone-aware time stamp and report of the specific settings of the microscope at that point in time when the image was taken. This is why instances of :ref:`NXevent_data_em` have their own em_lab section. The reason is that EMs can be highly dynamic, used to illuminate the specimen differently or show drift during signal acquisition, to name but a few effects. What constitutes a single EM experiment/measurement? This can be the collecting of a single diffraction pattern with a scanning TEM (STEM), taking of a secondary electron image for fracture analysis, taking a set of EBSD line scans and/or surface mappings in an SEM, or the ion-beam-milling of a specimen in preparation for e.g. an atom probe experiment. * :ref:`NXmonitor`; instances to keep track of time-dependent quantities pertaining to specific components of the instrument. Alternatively, NXevent_data_em instances can be used to store time-zone-aware dates of the components, which is relevant for documenting as exactly as practically possible settings when images and spectra were taken. * :ref:`NXinstrument`; conceptually this is a container to store an arbitrary level of detail of the technical components of the microscope as a device and the lab in which the microscope is operated. * :ref:`NXuser`; conceptually, this is a set with at least one NXuser instance which details who operated or performed the measurement. Additional NXusers can be referred to in an NXevent_data_em instance to store individualized details of who executed an event of data acquisition or processing. * :ref:`NXevent_data_em` instances as an NXevent_data_em_set; each NXevent_data_em instance is a container to group specific details about the state of the microscope when a measurement was taken and relevant data and eventual processing steps were taken (on-the-fly). * :ref:`NXdata`; at the top-level, this is a place for documenting available default plottable data. A default plottable can be useful for research data management systems to show a visual representation of some aspect of the content of the EM session. Default plottables are not intended to serve every possible analysis and visualization demand but are instead a preview. We made this choice because what constitutes a useful default plot is often a matter of interpretation, somewhat of personal taste, and community standards. In effect, default plottables are case- and method-specific. Usually a session at a microscope is used to collect multiple signals. Examples for possible default plottables could be arbitrarily taken secondary, back-scattered, electron image, diffraction pattern, EELS spectra, composition, or orientation mappings to name but a few. **There are a few design choices to consider with sub-ordinate groups:** * Images and spectra should be stored as :ref:`NXimage_set` and :ref:`NXspectrum_set` instances to hold data at the earliest possible step in the computational processing (which is usually performed with the microscope control and or integrated analysis software). The formatting of the NXdata groups enables the display of image and spectra with web technology visualization software. * When two- and three-dimensional geometric primitive data are stored, it is useful to write additional optional `XDMF <https://www.xdmf.org/index.php/XDMF_Model_and_Format>`_ fields which support additional plotting of the data with visualization software. * Consumable results of EM characterization tasks are usually a sub-set of data artifacts, as there is not an infinite amount of possible electron/ion beam-specimen interactions. * Images based on electron counts are typically detected with specific operation modes such as bright field or dark field imaging in TEM or secondary/back-scattered electron imaging in SEM. * Also spectra (X-ray quanta or Auger electron counts) typically are referred to under the assumption of a specific operation mode of the microscope. * These data are in virtually all cases a result of some numerical processing. These data and processing steps are modelled as instances of :ref:`NXprocess` which use terms from a controlled vocabulary e.g. SE (secondary electron), BSE (back-scattered electron), Kikuchi, X-ray, Auger, Cathodolum(inescence). **A key question often asked with EM experiments is how the actual (meta)data should be stored (in memory or on disk)**. The application definition NXem is a graph which describes how numerical data and (meta)data for EM research are related to one another. Electron microscopy experiments are usually controlled/performed via commercial integrated acquisition and instrument control software. In many cases, an EM dataset is useful only if it gets post-processed already during the acquisition, i.e. while the scientist is sitting at the microscope. Many of these processes are automated, while some demand GUI interactions with the control software. Examples include collecting of diffraction pattern and on-the-fly indexing of these. It is possible that different types of programs might be used to perform these processing steps whether on-the-fly or not. If this is the case the processing should be structured with individual :ref:`NXprocess` instances. If the program and/or version used for processing referred to in an NXprocess group is different to the program and version mentioned in this field, the NXprocess needs to hold an own program and version. An at least as strong as SHA256 hashvalue of the file that specifies the application definition. NeXus NXDL schema to which this file conforms. Ideally, a (globally) unique persistent identifier for referring to this experiment. The identifier is usually defined/issued by the facility, laboratory, or the principle investigator. The identifier enables to link experiments to e.g. proposals. Free-text description about the experiment. Users are strongly advised to detail the sample history in the respective field and fill rather as completely as possible the fields of this application definition rather than write details about the experiment into this free-text description field. ISO 8601 time code with local time zone offset to UTC information included when the microscope session started. If the application demands that time codes in this section of the application definition should only be used for specifying when the experiment was performed - and the exact duration is not relevant - this start_time field should be used. Often though it is useful to specify a time interval by specifying both a start_time and an end_time to allow for more detailed bookkeeping and interpretation of the experiment. The user should be aware that even with having both time instances specified, it may not be possible to infer how long the experiment took or for how long data were acquired. More detailed timing data over the course of the experiment have to be collected to compute this. These computations can take advantage of individual time stamps in NXevent_data_em instances to provide additional pieces of information. ISO 8601 time code with local time zone offset to UTC included when the microscope session ended. Binary container for a file or a compressed collection of files which can be used to add further descriptions and details to the experiment. The container can hold a compressed archive. A small image that is representative of the entry; this can be an image taken from the dataset like a thumbnail of a spectrum. A 640 x 480 pixel jpeg image is recommended. Adding a scale bar to that image is recommended but not required as the main purpose of the thumbnail is to provide e.g. thumbnail images for displaying them in data repositories. Contact information and eventually details of at least one person involved in the taking of the microscope session. This can be the principle investigator who performed this experiment. Adding multiple users if relevant is recommended. Given (first) name and surname of the user. Name of the affiliation of the user at the point in time when the experiment was performed. Postal address of the affiliation. Email address of the user at the point in time when the experiment was performed. Writing the most permanently used email is recommended. Globally unique identifier of the user as offered by services like ORCID or ResearcherID. If this field is field the specific service should also be written in orcid_platform Name of the OrcID or ResearcherID where the account under orcid is registered. (Business) (tele)phone number of the user at the point in time when the experiment was performed. Which role does the user have in the place and at the point in time when the experiment was performed? Technician operating the microscope. Student, postdoc, principle investigator, guest are common examples. Account name that is associated with the user in social media platforms. Name of the social media platform where the account under social_media_name is registered. A description of the material characterized in the experiment. Sample and specimen are threaded as de facto synonyms. A qualifier whether the sample is a real one or a virtual one (in a computer simulation) Ideally (globally) unique persistent identifier. The name distinguishes the specimen from all others and especially the predecessor/origin from where the specimen was cut. This field must not be used for an alias of the sample. Instead, use short_title for this, more convenient alias name. In cases where multiple specimens have been loaded into the microscope the name has to identify the specific one, whose results are stored by this NXentry, because a single NXentry should be used only for the characterization of a single specimen. Details about the specimen preparation should be stored in the sample history. Ideally, a reference to a (globally) unique persistent identifier, representing a data artifact which documents ideally as many details of the material, its microstructure, and its thermo-chemo-mechanical processing/preparation history as possible. The sample_history is the record what happened before the specimen was placed into the microscope at the beginning of the session. In the case that such a detailed history of the sample/specimen is not available, use this field as a free-text description to specify a sub-set of the entire sample history, i.e. what you would consider are the key steps and relevant information about the specimen, its material, microstructure, thermo-chemo-mechanical processing state, and the details of the preparation. Specific details about eventual physically-connected material like embedding resin should be documented ideally also in the sample_history. If all fails, the description field can be used but it is strongly discouraged because it leads to eventually non-machine-actionable data. ISO 8601 time code with local time zone offset to UTC information when the specimen was prepared. Ideally report the end of the preparation, i.e. the last known time the measured specimen surface was actively prepared. Usually this should be a part of the sample history, i.e. the sample is imagined handed over for analysis. Knowing when the specimen was exposed to e.g. specific atmosphere is especially required for environmentally sensitive material such as hydrogen charged specimens or experiments including tracers with a short half time. Further time stamps prior to preparation_date should better be placed in resources which describe the sample_history. Possibility to give an abbreviation or alias of the specimen name field. List of comma-separated elements from the periodic table that are contained in the sample. If the sample substance has multiple components, all elements from each component must be included in `atom_types`. The purpose of the field is to offer materials database systems an opportunity to parse the relevant elements without having to interpret these from the sample history. (Measured) sample thickness. The information is recorded to qualify if the beam used was likely able to shine through the specimen. For scanning electron microscopy, in many cases the specimen is much thicker than what is illuminatable by the electron beam. In this case the value should be set to the actual thickness of the specimen viewed for an illumination situation where the nominal surface normal of the specimen is parallel to the optical axis. (Measured) density of the specimen. For multi-layered specimens this field should only be used to describe the density of the excited volume. For scanning electron microscopy the usage of this field is discouraged and instead an instance of an :ref:`NXinteraction_vol_em` within individual :ref:`NXevent_data_em` instances can provide a much better description of the relevant details why one may wish to store the density of the specimen. Discouraged free-text field in case properly designed records for the sample_history are not available. Hard link to a location in the hierarchy of the NeXus file where the data for default plotting are stored. Metadata and numerical data of the microscope and the lab in which it stands. The em_lab section contains a description of the instrument and its components. The component descriptions in this section differ from those inside individual NXevent_data_em sections. These event instances take the role of time snapshot. For an NXevent_data_em instance users should store only those settings for a component which are relevant to understand the current state of the component. Here, current means at the point in time, i.e. the time interval, which the event represents. For example it is not relevant to store in each event's electron_source group again the details of the gun type and manufacturer but only the high-voltage if for that event the high-voltage was different. If for all events the high-voltage was the same it is not even necessary to include an electron_source section in the event. Individual sections of specific type should have the following names: * NXaperture: the name should match with the name of the lens * NXlens_em: condenser_lens, objective_lens are commonly used names * NXcorrector_cs: device for correcting spherical aberrations * NXstage_lab: a collection of component for holding the specimen and eventual additional component for applying external stimuli on the sample * NXdetector: several possible names like secondary_electron, backscattered_electron, direct_electron, ebsd, edx, wds, auger, cathodoluminescence, camera, ronchigram Given name of the microscope at the hosting institution. This is an alias. Examples could be NionHermes, Titan, JEOL, Gemini, etc. Location of the lab or place where the instrument is installed. Using GEOREF is preferred. If the lens is described at least one of the fields voltage, current, or value should be defined. If the lens is described at least one of the fields voltage, current, or value should be defined. Description of the type of the detector. Electron microscopes have typically multiple detectors. Different technologies are in use like CCD, scintillator, direct electron, CMOS, or image plate to name but a few. Instrument-specific alias/name A container for storing a set of NXevent_data_em instances. An event is a time interval during which the microscope was configured in a specific way. The microscope is considered as stable enough during this interval that a measurement with one or multiple detectors is possible. What constitutes such time interval depends on how the microscope is used and which measurements the user would like to perform. Each NXevent_data_em instance holds one acquisition task with detectors. Each NXevent_data_em section contains an em_lab group in which specific settings and states of the microscope during the time interval can be stored to document the history of states of the microscope over the course of the session. The NXem application definition offers maximal flexibility. One extreme could be that the only one NXevent_data_em instance is used and this covers the time interval of the entire session at the microscope. The other extreme case is that each collection of an image or even single spot measurement is defined as an NXevent_data_em instance. In this case the em_lab group inside the NXevent_data_em also holds the specific time-dependent state of the microscope with which in theory all dynamics of the system (if measured) can be captured and documented. Nowadays microscopes exists for which hard- and software solutions enable a tracking of the dynamics of the microscope and the actions of the user (such as with solution like AXONSynchronicity from Protochips). The NXem application definition can however also be used for less complex interaction and lower demands wrt to time tracking activities. An NXevent_data_em instance holds specific details about how raw data from a detector were processed. Raw data may already be post-processed as they are accessible only by the control software with after some internal processing happened. Nevertheless, these data have to be distinguished from post-processed data where e.g. raw data are converted to interpreted spectra, or orientation mappings. This post-processing tasks can be performed (on-the-fly, i.e. during acquisition for sure during the microscope session) or afterwards. Post-processing is performed with commercial software or various types and scripts. Currently, several specializations of NXimage_set and Nspectrum_set are used which store some details of this processing. However, as post- processing tasks can be substantially more advanced and involved it is clear that data artifacts from the measurement and data artifacts generated during post-processing are weakly connected only, maybe exclusively by the fact that a complex numerical post-processing workflow just takes one raw dataset from an NXevent_data_em instance but generates multiple derived data artifacts from this. All these should be described as own application definitions and only weak connections should be made to an instance of NXem. Instances of NXsubentry is one mechanism in NeXus how this can be achieved in the future. A container holding a specific result of the measurement and eventually metadata how that result was obtained numerically. NXevent_data_em instances can hold several specific NXimage_em or NXspectrum_em instances taken and considered as one event, i.e. a point in time when the microscope had the settings specified either in NXinstrument or in this NXevent_data_em instance. The application definition is designed without an explicit need for having an NXevent_data_em instance that contains an NXimage_em or NXspectra_em instance. Thereby, an NXevent_data_em can also be used for just documentation about the specific state of the microscope irrespective whether data have been collected during this time interval. In other words the NXinstrument group details primarily the more static settings and components of the microscope as they are found by the operator during the session. The NXevent_data_em samples the dynamics. It is not necessary to store data in NXebeam, NXibeam instances of NXevent_data_em but in this case it is assumed that the settings were constant over the entire course of the microscope session and thus all relevant metadata inside the NXinstrument groups are sufficient to understand the session. So far there exists no standard which a majority of the technology partners and the materials science electron microscopy community have accepted which could be used for a very generic documentation, storage and exchange of electron microscope data. Therefore, it is still a frequent case that specific files have many fields which cannot safely be mapped or interpreted. **Therefore, users are always given the advice to keep the vendor files.** Working however with these vendor files inside specific software, like materials databases, demands for parsers which extract pieces of information from the vendor representation (numerical data and metadata) and map them on a schema with which the database and its associated software tools can work with. Currently, one would loose immediately track of e.g. provenance and the origin of certain data in NXevent_data_em instances unless really all data are safely and reliably copied over into an instance of the schema. Currently, though, this is sadly effectively prevented in many cases as vendors indeed implemented often sophisticated provenance and commercial software state tracking tools but these are not yet documented covering enough in our opinion so that it is safe to assume all vendor field names are known, logically understood, interpretable, and thus mappable on a common schema using a controlled common vocabulary. Therefore we encourage user for now to store for each NXimage_set or NXspectra_set instance to supply the so-called source of the data. This can for instance be the name and hashvalue of the original file which was acquired during the microscope session and from which then certain details like numerical data and metadata were copied into an instance of this schema for the purpose of working with the data in e.g. tools offered by research data management (RDM) systems or materials database. During our work on implementing file format/metadata parsers and developing this application definition, we realized that **several software tools currently do not consistently format critical metadata like time-zone-aware timestamps** when events of data collection or processing happened. We would like to encourage the community and especially the vendors to work towards a standardization, or at least an open documentation of the way how time-zone-aware time data are collected and stored how and where during a microscope session and how they end up in files and databases with which users interact. This would enable to supplement instances of this schema with specific time data and assure that these time data can be used to reliably contextualize individual datasets and processing steps in materials information systems. For the reason that these measures have not yet been fully taken, the start_time and end_time is a recommended option. The idea behind these time-zone-aware dates is to identify when the data were collected at the microscope but NOT when they were transcoded by some software tool(s) while storing the data in an instance of this schema. Annulus inner half angle Annulus outer half angle ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXem_ebsd.nxdl.xml0000644000077000000000000032701614777236751030415 0ustar00rosborn Number of arguments per orientation for given parameterization. Number of scan points. Number of pixel along the slowest changing dimension for a rediscretized, i.e. standardized default orientation mapping. Number of pixel along slow changing dimension for a rediscretized i.e. standardized default orientation mapping. Number of pixel along fast changing dimension for a rediscretized i.e. standardized default orientation mapping. Application definition for collecting and indexing Kikuchi pattern into orientation maps. This NXem_ebsd application is a proposal how to represent data, metadata, and connections between these for the research field of electron microscopy. More specifically, exemplified here for electron backscatter diffraction (EBSD). The application definition solves two key documentation issues which are missing so far to document provenance of data and metadata in the field of EBSD. The application definition can be an example that is relevant for related workflows in orientation microscopy. Firstly, an instance of NXem_ebsd (such as a NeXus/HDF5 file which is formatted according to the NXem_ebsd application definition) stores the connection between the microscope session and the key datasets which are considered typically results of the various processing steps involved when working with EBSD data. Different groups in this application definition make connections to data artifacts which were collected when working with electron microscopes via the NXem partner application definition. Using a file which stores information according to the NXem application definition has the benefit that it connects the sample, references to the sample processing, the user operating the microscope, details about the microscope session, and details about the acquistion and eventual indexing of Kikuchi pattern, associated overview images, like secondary electron or backscattered electron images of the region-of-interest probed and many more pieces of information. Secondly, this NXem_ebsd application definition connects and stores the conventions and reference frames which were used and are the key to mathematically correctly interpret every EBSD result. Otherwise, results would be ripped out of their context, as it is the situation with many traditional studies where EBSD data were indexed on-the-fly and shared with the community only via sharing the results file with some technology-partner-specific file but leaving important conventions out or relying on the assumptions that colleagues know these even though multiple definitions are possible. This application definition covers experiments with one-, two-dimensional, and so-called three-dimensional EBSD datasets. The third dimension is either time (in the case of quasi in-situ experiments) or space (in the case of serial- sectioning) methods where a combination of mechanical or ion milling is used repetitively to measure the same region-of-interest at different depth increments. Material removal can be achieved with electron or ion polishing, using manual steps or using automated equipment like a robot system. Three-dimensional experiments require to follow a sequence of specimen, surface preparation, and data collection steps. By nature these methods are destructive in that they either require the removal of the previously measured material region or that the sample surface can degrade due to e.g. contamination or other electron-matter interaction. For three-dimensional EBSD, multiple two-dimensional EBSD orientation mappings are combined into one reconstructed stack. That is serial-sectioning is mainly a computational workflow. Users collect data for each serial sectioning step via an experiment. This assures that data for associated microscope sessions and steps of data processing stay connected and contextualized. Eventual tomography methods also use such a workflow because first diffraction images are collected (e.g. with X-ray) and then these imagres are indexed and computed into a 3D orientation mapping. The here proposed NXem_ebsd application definition contains conceptual ideas how this splitting between measurement and post-processing can be granularized also for such X-ray-based techniques, whether it be 3DXRD or HEDM. An at least as strong as SHA256 hashvalue of the file that specifies the application definition. NeXus NXDL schema to which this file conforms. Ideally, a (globally) unique persistent identifier for referring to this workflow. The identifier is usually defined/issued by the facility, laboratory, or the principle investigator. The identifier enables to link workflows/experiments to e.g. proposals. Free-text description about the workflow. Users are strongly advised to detail the sample history in the respective field and fill rather as completely as possible the fields of the application definition behind instead of filling in these details into the experiment_description free-text description field. ISO 8601 time code with local time zone offset to UTC information included when the processing of the workflow started. If the application demands that time codes in this section of the application definition should only be used for specifying when the workflow was executed - and the exact duration is not relevant - this start_time field should be used. Often though it is useful to specify a time interval with specifying both start_time and end_time to allow for more detailed bookkeeping and interpretation of the workflow. ISO 8601 time code with local time zone offset to UTC included when the processing of the workflow ended. Program which was used for creating the file instance which is formatted according to the NXem_ebsd application definition. Contact information and eventually details of at least one person involved in performing the workflow. This can be the principle investigator who performed this experiment. Adding multiple users if relevant is recommended. Given (first) name and surname of the user. Name of the affiliation of the user at the point in time when the experiment was performed. Postal address of the affiliation. Email address of the user at the point in time when the experiment was performed. Writing the most permanently used email is recommended. Globally unique identifier of the user as offered by services like ORCID or ResearcherID. If this field is field the specific service should also be written in orcid_platform Name of the OrcID or ResearcherID where the account under orcid is registered. (Business) (tele)phone number of the user at the point in time when the experiment was performed. Which role does the user have in the place and at the point in time when the experiment was performed? Technician operating the microscope. Student, postdoc, principle investigator, guest are common examples. Account name that is associated with the user in social media platforms. Name of the social media platform where the account under social_media_name is registered. Details about simulations for Kikuchi pattern using kinematic or dynamic diffraction theory. Usually, the output of such computer simulations are spherical Kikuchi images which only when projected or observed in some region-of-interest will represent a set of rectangular Kikuchi pattern with the same rectangular shape and image size. Therefore, these pattern should be stored. The spherical diffraction pattern can be stored as a set of triangulated geodesic meshes. The rectangular patterns should be stored as NXimage_set_em_kikuchi stack. Do not store pattern in the simulation group if they have been measured are not simulated. The experiment group captures relevant details about the conditions of and the tools used for collecting the Kikuchi diffraction pattern. The most frequently collected EBSD data are captured as rectangular ROIs composed from square or hexagonally-shaped pixels. Substantially less frequently, because such experiments are more costly and technically demanding, correlated experiments are performed. One important class of such correlated experiments are the so-called (quasi) in-situ experiments. Here the same or nearly the same ROI is analyzed via a cycles of thermomechanical treatment, sample preparation, measurement, on-the-fly-indexing. Phenomena investigated like this are recrystallization, strain accumulation, material damage. Post-processing is required to correlate and reidentify eventual features or local ROIs across several orientation maps. Another important class of correlated experiments are the so-called serial-sectioning experiments. Here the same sample is repetitively measured and polished to create a stack of orientation data which can be reconstructed to a three-dimensional volume ROI. Physical time since the beginning of a timestamp that is required to be same for all experiments in the set. The purpose of this marker is to identify how all experiments in the set have have to be arranged sequentially based on the time elapsed. The time is relevant to sort e.g. experiments of consecutive quasi in-situ experiments where a measurement was e.g. taken after 0 minutes of annealing, 30 minutes, 6 hours, or 24 hours of annealing. Transformation which details where the region-of-interest described under indexing is located in absolute coordinates and rotation with respect to which coordinate system. The EBSD system, including components like the electron gun, pole-piece, stage tilting, EBSD detector, and the gnomonic projection have to be calibrated to achieve reliable results. Specifically, the gnomonic projection has to be calibrated. In most practical cases, especially in engineering, there is a substantially larger number of sessions where such a calibrated system is used assuming that somebody has properly calibrated the system rather than that the user actively recalibrates it or is even allowed to do so. Especially the projection geometry has to calibrated which is usually achieved with measuring silicon, quartz or standards, and comparing against simulated diffraction pattern. In the first case, the user assumes that the principle geometry of the hardware components and the settings in the control and EBSD pattern acquisition software are calibrated. Consequently, users pick from an existent library of phase candidates. One example are the CRY or CIF files of the classical HKL/Channel 5/Flamenco software products. Each entry of the library of such phase candidates in this NeXus proposal is represented by one NXem_ebsd_crystal_structure_model base class. For each phase an instance of this base class is to be used to store crystallographic and simulation-relevant data. Indexing is a data processing step performed after/during the beam scans the specimen (depends on configuration). Users load the specimen, and first collect a coarse image of the surface. Next, an approximate value for the calibrated working distance is chosen and the stage tilted. Users then may configure the microscope for collecting higher quality data and push in the EBSD detector. Subsequently, they fine tune the illumination and aberration settings and select one or multiple ROIs to machine off. The on-the-fly indexing parameter are defined and usually the automated measurement queue started. Nowadays, this is usually an automated/unsupervised process. The pattern collection runs during the allocated session time slot which the user has booked ends or when the queue finishes prematurely. Kikuchi pattern surplus eventually multi-modal detector signals are collected and usually indexed on-the-fly. The Kikuchi patterns may or not be deleted directly after a solution was found (on-the-fly) so Kikuchi pattern are not always stored. Results files are in many labs afterwards copied automatically for archival purposes to certain storage locations. The result of such an EBSD measurement/experiment is a set of usually proprietary or open files from technology partners (microscope and EBSD detector manufacturers). In the second case, the system is being calibrated during the session using standards (silicon, quartz, or other common specimens). There is usually one person in each lab responsible for doing such calibrations. Important is that often this person or technician(s) are also in charge of configuring the graphical user interface and software with which most users control and perform their analyses. For EBSD this has key implications because, taking TSL OIM/EDAX as an example, the conventions how orientations are stored is affected by how reference frames are set up and this setup is made at the level of the GUI software. Unfortunately, these pieces of information are not necessarily stored in the results files. In effect, key conventions become disconnected from the data so it remains the users personal obligation to remember these settings, write them down in the lab notebook, or these metadata get lost. All these issues are a motivation and problem which NXem_ebsd solves. A link/cross reference to an existent instance of NXem_ebsd with ideally an associated instance of NXem detailed under measurement which informs about the calibration procedures. Commit identifying this resource. Path which resolves which specific NXimage_set_em_kikuchi instance was used as the raw data to the EBSD data (post)-processing workflow when performing the calibration. Relevant result of the session at the microscope for this experiment which enables to connect the measurement of the Kikuchi pattern and their processing into orientation microscopy maps. Name or link to an existent instance of an EBSD raw dataset ideally as an instance of an NXem application definition which has at least one NXimage_set_em_kikuchi instance i.e. one stack of Kikuchi pattern. The path to this instance in the origin has to be specified under path. When NXem is not used or the aim is to rather explore first how community-specific files with EBSD data, such as ANG, CPR, or HDF5- based formats can be parsed from, inject here the name of that file. The em_om parser will currently not interpret the majority of the many system- and technique-specific metadata which come with the files from e.g. technology partners. This is because the current culture in the EBSD community is that many of the metadata fields are neither in all cases fully documented nor use a standardized vocabulary although many people understand terms from different implementations and how these metadata can likely be compared to one another. In addition, it is common practice in the research field of EBSD that users transcode their raw data into other (often text-based or HDF5) files with custom formatting to realize an information transfer between specific software tools including commercial software from technology partner, custom scripts in Matlab using tools like MTex, or Python scripting with tools like hyperspy, pyxem, orix, diffsims, kikuchipy, or EBSD data stack alignment tools like DREAM.3D. We have opted that in the first iteration this implementation of a RDMS-agnostic FAIR data schema for EBSD that we discard these metadata because these ad hoc file formats are not designed to communicate also specifically and most importantly the eventually different context of the metadata. Another reason for this choice was also to emphasize that in fact such challenges do exist in the community and thus pointing them out may support the discussion to arrive at eventually more complete solutions. As developing these solutions should not be our authority and necessarily demands feedback from the technology partners, we have opted for this intermediate approach to stimulate discussion. Commit or e.g. at least SHA256 checksum identifying this resource. Path which resolves which specific NXimage_set_em_kikuchi instance was used as the raw data to this EBSD data (post)-processing workflow. OIM, orientation imaging microscopy. Post-processing of the Kikuchi patterns to obtain orientation per phase model and scan point. Fundamentally different algorithms can be used to index EBSD/EBSP pattern. Common is that pattern indexing is a computational step of comparing simulated with measured diffraction pattern. Quality descriptors are defined based on which an indexing algorithm yields a quantitative measure of how similar measured and assumed/simulated pattern are, and thus if no, one, or multiple so-called solutions were found. Assumed or simulated pattern use kinematical or dynamical electron diffraction theory. Hough transform (which is essentially a discretized Radon transform, for details see e.g A short introduction to the Radon and Hough transforms and how they relate by M. van Ginkel et al.). Recently, dictionary-based indexing methods are increasingly becoming used partly driven by the move to use artificial intelligence algorithms. An inspection of publicly available EBSD datasets with an open-source license which are available on Zenodo was performed prior to implementing of the associated em_om parser for NXem_ebsd. This analysis revealed that EBSD data are in most cases stored in two ways: Case one was via a file in formats from technology partners. Examples are binary formats like OSC, H5OINA, OIP, EBSP, and many derived text-based formats like CPR, CRC, ANG, CTF, HKL and more. Recently, there is trend towards using HDF5-based formats. These files contain some result and metadata to the numerical steps and the computational workflow which was performed to index Kikuchi pattern on-the-fly. Examples of metadata include scan point positions, indexing solutions per scan point, some quality descriptors for the solutions, as well as crystal structure and phase metadata. Case two were raw pattern in some custom format, often text-based with some but in general no conclusive and interoperable representation of all relevant metadata. Often it remains unclear what individual fields and data arrays of these fields resolve and/or mean conceptually. For some fields, publications were referred to. However, software tools change over time and thus which specific data end in a file and which specific conceptual information is behind these data can change with software versions. Other cases were storing results of custom post-processing steps and associated Kikuchi pattern. Testing of advanced indexing, pseudo-symmetry resolving methods, i.e. any sort of prototyping or alternative indexing strategies so far seem to require some flexibility for implementing rapid prototypic capabilities. The drawback of this is that such results come formatted on a case-by-case basis and are thus not interoperable. Therefore, we first need to collect how these files have been generated and which metadata in these files (or database entries) represent which pieces of information conceptually. Ideally, one would do so by creating a complete set of information in e.g. an NXem application definition, such as a log of timestamped events and processing steps, metadata and data. Eventually even interactions with the graphical user interface of commercial software during the microscope session should be stored and become a part of the application definition. Such a set of pieces of information could then be used via reading directly for the NXem application definition. However, in most cases such a data representation is not available yet. Therefore, the on_the_fly_indexing group stores which source_file contains the results of the on-the-fly indexing. For commercial systems these files can be e.g. ANG, CPR/CRC, H5OINA, OSC. It is possible that the file or database entry which is referred to under origin is the same as the one under a given acquisition/origin in one of the experiment groups. This is because some commercial file formats make no clear distinction between which metadata are acquisition and/or indexing metadata. Commercial program which was used to index the EBSD data incrementally after they have been captured and while the microscope was capturing (on-the-fly). This is the usual production workflow how EBSD data are collected in materials engineering, in industry, and academia. Name of the file from which data relevant for creating default plots were taken in the case that the data in the experiment group were indexed on-the-fly. Hash of that file. TBD, path which resolves which specific NXimage_set_em_kikuchi instance was used as the raw data to this EBSD data (post)-processing workflow when performing the calibration. Principal algorithm used for indexing. Details about the background correction applied to each Kikuchi pattern. Binning i.e. downsampling of the pattern. Specific parameter relevant only for certain algorithms used Which return value did the indexing algorithm yield for each scan point. Practically useful is to use an uint8 mask. * 0 - Not analyzed * 1 - Too high angular deviation * 2 - No solution * 100 - Success * 255 - Unexpected errors How many phases i.e. crystal structure models were used to index each scan point if any? Let's assume an example to explain how this field should be used: In the simplest case users collected one pattern for each scan point and have indexed using one phase, i.e. one instance of an NXem_ebsd_crystal_structure_model. In another example users may have skipped some scan points (not indexed) them at all) and/or used differing numbers of phases for different scan points. The cumulated of this array decodes how phase_identifier and phase_matching arrays have to be interpreted. In the simplest case (one pattern per scan point, and all scan points indexed using that same single phase model), phase_identifier has as many entries as scan points and phase_matching has also as many entries as scan points. The array n_phases_per_scan_point details how the phase_identifier and the phase_matching arrays have to be interpreted. For the example with a single phase phase_identifier has trivial values either 0 (no solution) or 1 (solution matching sufficiently significant with the model for phase 1). When there are multiple phases, it is possible (although not frequently needed) that a pattern matches eventually (not equally well) sufficiently significant with multiple pattern. This can especially happen in cases of pseudosymmetry and more frequently with an improperly calibrated system or false or inaccurate phase models e.g. (ferrite, austenite). Having such field is especially relevant for recent machine learning or dictionary based indexing schemes because in combination with phase_matching these fields communicate the results in a model-agnostic way. Depending on the n_phases_per_scan_point value phase_identifier and phase_matching arrays represent a collection of concatenated tuples, which are organized in sequence: The solutions for the 0-th scan point, the 1-th scan point, the n_sc - 1 th scan point and omitting tuples for those scan points with no phases according to n_phases_per_scan_point One-dimensional array, pattern by pattern labelling the solutions found. The array n_phases_per_scan_point has to be specified because it details how the phase_identifier and the phase_matching arrays have to be interpreted. See documentation of phase_identifier for further details. Phase_matching is a descriptor for how well the solution matches or not. Examples can be confidence index (ci), mean angular deviation (mad), some AI-based matching probability (other), i.e. the details are implementation-specific. How are orientations parameterized? Inspect euler_angle_convention in case of using euler to clarify the sequence of rotations assumed. Matrix of parameterized orientations identified. The slow dimension iterates of the individual solutions as defined by n_phases_per_scan_point. Values for phases without a solution should be correctly identified as IEEE NaN. Matrix of calibrated centre positions of each scan point in the sample surface reference system. Fraction of successfully indexed pattern of the set averaged over entire set. An overview of the entire area which was scanned. For details about what defines the image contrast inspect descriptor. Descriptor representing the image contrast. Container holding a default plot of the region on the sample investigated with EBSD. Descriptor values displaying the ROI. Signal Calibrated center of mass of the pixel along the slow axis. Label for the y axis Calibrated center of mass of the pixel along the fast axis. Label for the x axis Default inverse pole figure (IPF) plot of the data specific for each phase. No ipf_mapID instances for non-indexed scan points as these are by definition assigned the null phase with phase_identifier 0. The IPF mapping is interpolated from the scan point data mapping onto a rectangular domain with square pixels and the orientations colored according to the coloring scheme used in the respective ipf_color_modelID/program. The main purpose of the ipf_mapID group is not to keep raw data or scan point related data but offer a default way how a research data management system can display a preview of the dataset so that users working with the RDMS can get an overview of the dataset. This matches the first aim of NXem_ebsd which is foremost to bring colleagues and users of EBSD together to discuss which pieces of information need to be stored together. We are convinced a step-by-step design and community-driven discussion about which pieces of information should and/or need to be included is a practical strategy to work towards an interoperable description and data model for exchanging data from EBSD between different tools and research data management systems (RDMS). With this design the individual RDMS solutions and tools can still continue to support specific custom data analyses workflow and routes but at least there is then one common notation of understanding whereby also users not necessarily expert in all the details of the EBSD story can understand better these data and thus eventually this can motivate data reuse and repurposing. It is important to mention that we cannot assume, at least for now, that the parser which writes to an NXem_ebsd-compliant file is also responsible or capable at all of computing the inverse pole figure color keys and maps itself. This cannot be assumed working because this mapping of orientation data uses involved mathematical algorithms and functions which not every tools used in the EBSD community is capable of using or is for sure not using in exactly the same way. Currently, we assume it is the responsibilty of the tool used which generated the data under on_the_fly_indexing to compute these plots and deliver these to the parser. Specific case studies have been explored by the experiment team of Area B of the FAIRmat project to realize and implement such mapping. The first case study uses the H5OINA format and the pyxem/orix library. As orix is a Python library, the coloring is performed by the em_om parser. The second case study uses MTex and its EBSD color coding model. As MTex is a Matlab tool, an intermediate format is written from MTex first which stores these pieces of information. The parser then pulls these data from the intermediate Matlab-agnostic representation and supplements the file with missing pieces of information as it is required by NXem_ebsd. The third case study shows how a generic set of Kikuchi pattern can be loaded with the em_om parser. The pattern are loaded directly from a ZIP file and mapped to an simulation image section for now. The fourth case study uses the DREAM.3D package which provides an own set of EBSD data post-processing procedures. DREAM.3D documents the processing steps with a pipeline file which is stored inside DREAM.3D output files. In this case study, the parser reads the DREAM.3D file and maps data relevant from the perspective of NXem_ebsd plus adds relevant IPF color maps as they were computed by DREAM.3D. Given that in this case the origin of the data is the DREAM.3D file again provenance is kept and more details can be followed upon when resolving origin. These examples offer a first set of suggestions on how to make EBSD data injectable into research data management system using schemes which themselves are agnostic to the specific RDMS and interoperable. Steps of collecting the raw data and post-processing these with custom scripts like MTex or commercial tools so far are mainly undocumented. The limitation is that a program which consumes results or dump files from these tools may not have necessarily all the sufficient information available to check if the injected orientation data and color models are matching the conventions which a user or automated system has injected into an electronic lab notebook from which currently the em_om parser collects the conventions and stores them into this NXem_ebsd instance. The immediate benefit of the here presented NXem_ebsd concept though is that the conventions and reference frame definitions are expected in an ELN-agnostic representation to make NXem_ebsd a generally useful data scheme for EBSD. Ideally, the em_om parser would load convention-compliant EBSD data and use subsequently a community library to transcode/convert orientation conventions and parameterized orientation values. Thereafter, convention- compliant default plot(s) could be created that would be truely interoperable. However, given the variety of post-processing tools available surplus the fact that these are not usually executed along standardized post-processing workflows which perform exactly the same algorithmic steps, this is currently not a practically implementable option. Indeed, first developers who wish to implement this would first have to create a library for performing such tasks, mapping generally between conventions, i.e. map and rotate coordinate systems at the parser level. The unfortunate situation in EBSD is that due to historical reasons and competitive strategies, different players in the field have implemented (slightly) different approaches each of which misses some part of a complete workflow description which is behind EBSD analyses: Sample preparation, measurement, indexing, post-processing, paper... The here exemplified default plot do not so far apply relevant rotations but takes the orientation values as they come from the origin and using coloring them as they come. It is thus the scientists responsibility to enter and check if the respective dataset is rotation-conventions-wise consistent and fit for a particular task. Ideally, with all conventions defined it can be possible to develop a converter which rotates the input data. This application definition does not assume this and users should be aware of this limitation. The key point is that the conventions however are captured and this is the most important step to the development of such a generic transcoder for creating interoperable EBSD datasets. Currently the conventions remain in the mind or manual lab book of the respective scientists or technicians instead of getting stored and communicated with research papers that are written based on specific dataset, i.e. database entries. The default gridded representation of the data should not be misinterpreted as the only possible way how EBSD data and OIM maps can be created! Indeed, the most general case is that patterns are collected for scan points. The scan generator of an electron microscope is instructed to steer the beam in such a way across the specimen surface that the beam illuminates certain positions for a certain amount time (usually equally-spaced and spending about the same amount of time at each position). Therefore, scan positions can be due to such regular flight plans and represent sampling on lines, line stacks, rectangular regions-of- interests, but also could instruct spiral, random, or adaptive scans instead of tessellations with square or hexagonal pixels. The majority of EBSD maps is though is reporting results for a regular grid (square, hexagon). What matters though in terms of damage induced by the electron beam and signal quality is the real electron dose history, i.e. for how long the beam exposed which location of the specimen. Especially when electron charging occurs (i.e. an excess amount of charge accumulates due to e.g. poor conducting away of this charge or an improper mounting, too high dose, etc. such details are relevant. Specifically, the default visualization is an inverse pole-figure (IPF) map with the usual RGB color coding. Different strategies and normalization schemes are in use to define such color coding. Finally, we should mention that each ipf_map represents data for scan points indexed as one phase. The alias/name of this phase should be stored in phase_name, the phase_identifier give an ID which must not be zero as this value is reserved for non-indexed / null model scan points. Specifying which phase this IPF mapping visualizes. Alias/name for the phase whose indexed scan points are displayed. Which IPF definition computation according to backend. Along which axis to project? Typically [0, 0, 1] is chosen. Bitdepth used for the RGB color model. Usually 8 bit. The tool/implementation used for creating the IPF color map from the orientation data. Effectively, this program is the backend which performs the computation of the inverse pole figure mappings which can be for some use cases the parser. Consider the explanations in the docstring of the ipf_mapID group. The RGB image which represents the IPF map. RGB array, with resolution per fastest changing value defined by bitdepth. IPF color-coded orientation mapping Calibrated center of mass of the pixel along the slow axis. Label for the y axis Calibrated center of mass of the pixel along the fast axis. Label for the x axis For each stereographic standard triangle (SST), i.e. a rendering of the fundamental zone of the crystal-symmetry-reduced orientation space SO3, it is possible to define a color model which assigns each point in the fundamental zone a color. Different mapping models are in use and implement (slightly) different scaling relations. Differences are which base colors of the RGB color model are placed in which extremal position of the SST and where the white point is located. For further details see: * [G. Nolze et al.](https://doi.org/10.1107/S1600576716012942) * Srikanth Patala and coworkers"'" work and of others. Details are implementation-specific and not standardized yet. Given that the SST has a complicated geometry, it cannot yet be visualized using tools like H5Web, which is why for now the em_om parsers takes a rasterized image which is rendered by the backend tool. RGB array, with resolution per fastest changing value defined by bitdepth. IPF color key in stereographic standard triangle (SST) Pixel coordinate along the slow axis. Label for the y axis Pixel coordinate along the fast axis. Label for the x axis This application definition also enables to describe a workflow where several EBSD datasets are not only documented but also correlated based on time, position (spatial), or both (spatiotemporal). Spatial correlations between repetitively characterized regions-of-interests are typically correlated using image registration and alignment algorithms. For this typically so-called landmarks are used. These can be grains with a very large size or specific shape, i.e. grains which are qualitatively different enough to be used as a guide how images are shifted relative to one another. Other commonly used landmarks are fiducial marks which are milled into the specimen surface using focus-ion beam milling and/or various types of indentation methods. As far as the same physical region-of-interest is just measured several times, the additional issue of the depth increment is not a concern. However, correct assumptions for the depth increment, amount of material removed along the milling direction is relevant for accurate and precise three-dimensional (serial-sectioning) correlations. For these studies it can be tricky though to assume or estimate useful depth increments. Different strategies have been proposed like calibrations, wedged-shaped landmarks and computer simulation assisted assumption making. Despite the use of landmarks, there are many practical issues which make the processing of correlations imprecise and inaccurate. Among these are drift and shift of the specimen, instabilities of the holder, the beam, irrespective of the source of the drift, charging effects, here specifically causing local image distortions and rotations which may require special processing algorithms to reduce such imprecisions. Time correlations face all of the above-mentioned issues surplus the challenge that specific experimental protocols have to be used to ensure the material state is observed at specific physical time. The example of quasi in-situ characterization of crystal growth phenomena, a common topic in engineering or modern catalysis research makes it necessary to consider that e.g. the target value for the desired annealing temperature is not just gauged based on macroscopic arguments but considers that transient effects take place. Heating or quenching a sample might thus might not have been executed under conditions in the interaction volume as they are documented and/or assumed. These issue cause that correlations have an error margin as to how accurately respective datasets were not only just synced based on the geometry of the region-of-interests and the time markers but also to asssure which physical conditions the specimen experienced over the course of the measurements. The fourth example of the em_om reference implementation explores the use of the correlation group with a serial-sectioning datasets that was collected by the classical Inconel 100 dataset collected by M. D. Uchic and colleagues (M. Groeber M, Haley BK, Uchic MD, Dimiduk DM, Ghosh S 3d reconstruction and characterization of polycrystalline microstructures using a fib-sem system data set. Mater Charac 2006, 57 259–273. 10.1016/j.matchar.2006.01.019M). This dataset was specifically relevant in driving forward the implementation of the DREAM.3D software. DREAM.3D is an open-source software project for post-processing and reconstructing, i.e. correlating sets of orientation microscopy data foremost spatially. One focus of the software is the (post-)processing of EBSD datasets. Another cutting edge tool with similar scope but a commercial solution by Bruker is QUBE which was developed by P. Konijnenberg and coworkers. Conceptually, software like DREAM.3D supports users with creating linear workflows of post-processing tasks. Workflows can be instructed via the graphical user interface or via so-called pipeline processing via command line calls. DREAM.3D is especially useful because its internal system documents all input, output, and parameter of the processing steps. This makes DREAM.3D a good candidate to interface with tools like em_om parser. Specifically, DREAM.3D documents numerical results via a customized HDF5 file format called DREAM3D. Workflow steps and settings are stored as nested dictionaries in JSON syntax inside a supplementary JSON file or alongside the data in the DREAM3D file. DREAM.3D has a few hundred algorithms implemented. These are called filters in DREAM.3D terminology. Users configure a workflow which instructs DREAM.3D to send the data through a chain of predefined and configured filters. Given that for each analysis the filter is documented via its version tags surplus its parameter and setting via a controlled vocabulary, interpreting the content of a DREAM3D HDF5 file is possible in an automated manner using a parser. This makes DREAM.3D analyses repeatable and self-descriptive. A key limitation though is that most frequently the initial set of input data come from commercial files like ANG. This missing link between the provenance of these input files, their associated creation as electron microscope session, is also what NXem_ebsd solves. Nevertheless, as this can be solved with e.g. NXem_ebsd we are convinced that the DREAM.3D and the em_om parser can work productively together to realize RDMS-agnostic parsing of serial-section analyses. The internal documentation of the DREAM.3D workflow also simplifies the provenance tracking represented by an instance of NXem_ebsd as not every intermediate results has to be stored. Therefore, the fourth example focuses on the key result obtained from DREAM.3D - the reconstructed and aligned three-dimensional orientation map. Usually, this result is the starting point for further post-processing and characterization of structural features. As here orientation microscopy is insofar scale invariant using DREAM.3D, NXem_ebsd, and em_om should be useful for different characterization methods, such as EBSD, Transmission Kikuchi Diffraction (TKD), Automated Crystal Orientation Mapping (ACOM), Nanobeam Electron Diffraction (using commercial systems like NanoMegas ASTAR) or open-source implementations of these techniques (such as via pyxem/orix). The result of orientation microscopy methods are maps of local orientation and thermodynamic phase (crystal structure) pieces of information. Virtually all post-processing of such results for structural features includes again a workflow of steps which are covered though by the NXms partner application definition. The respective source of the data in an instance of NXms can again be a link or reference to an instance of NXem_ebsd to complete the chain of provenance. An overview of the entire reconstructed volume. For details about what defines the image contrast inspect descriptor. Descriptor representing the image contrast. Container holding a default plot of the reconstructed volume. Descriptor values displaying the ROI. Signal Calibrated center of mass of the pixel along the slow axis. Label for the z axis Calibrated center of mass of the pixel along the fast axis. Label for the y axis Calibrated center of mass of the pixel along the fastest axis. Label for the x axis Default inverse pole figure (IPF) plot of the data specific for each phase. No ipf_mapID instances for non-indexed scan points as these are by definition assigned the null phase with phase_identifier 0. The same comments apply as to the two-dimensional representation. Specifying which phase this IPF mapping visualizes. Alias/name for the phase whose indexed scan points are displayed. Which IPF definition computation according to backend. Along which axis to project? Typically [0, 0, 1] is chosen. Bitdepth used for the RGB color model. Usually 8 bit. The tool/implementation used for creating the IPF color map from the orientation data. Effectively, this program is the backend which performs the computation of the inverse pole figure mappings which can be for some use cases the parser. Consider the explanations in the docstring of the ipf_mapID group. The RGB image which represents the IPF map. RGB array, with resolution per fastest changing value defined by bitdepth. IPF color-coded orientation mapping Calibrated center of mass of the pixel along the slow axis. Label for the z axis Calibrated center of mass of the pixel along the faster axis. Label for the y axis Calibrated center of mass of the pixel along the fastest axis. Label for the x axis Same comments as for the two-dimensional case apply. RGB array, with resolution per fastest changing value defined by bitdepth. IPF color key in stereographic standard triangle (SST) Pixel coordinate along the slow axis. Label for the y axis Pixel coordinate along the fast axis. Label for the x axis ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXem_ebsd_conventions.nxdl.xml0000644000077000000000000006675414777236751033053 0ustar00rosborn Conventions for rotations and coordinate systems to interpret EBSD data. This is the main issue which currently is not in all cases documented and thus limits the interoperability and value of collected EBSD data. Not communicating EBSD data with such contextual pieces of information and the use of file formats which do not store this information is the key unsolved problem. Mathematical conventions and materials-science-specific conventions required for interpreting every collection of orientation data. Convention how a positive rotation angle is defined when viewing from the end of the rotation unit vector towards its origin, i.e. in accordance with convention 2 of DOI: 10.1088/0965-0393/23/8/083501. Counter_clockwise is equivalent to a right-handed choice. Clockwise is equivalent to a left-handed choice. How are rotations interpreted into an orientation according to convention 3 of DOI: 10.1088/0965-0393/23/8/083501. How are Euler angles interpreted given that there are several choices (e.g. ZXZ, XYZ, etc.) according to convention 4 of DOI: 10.1088/0965-0393/23/8/083501. The most frequently used convention is ZXZ which is based on the work of H.-J. Bunge but other conventions are possible. To which angular range is the rotation angle argument of an axis-angle pair parameterization constrained according to convention 5 of DOI: 10.1088/0965-0393/23/8/083501. Which sign convention is followed when converting orientations between different parameterizations/representations according to convention 6 of DOI: 10.1088/0965-0393/23/8/083501. Details about eventually relevant named directions that may give reasons for anisotropies. The classical example is cold-rolling where one has to specify which directions (rolling, transverse, and normal) align how with the direction of the base vectors of the sample_reference_frame. Type of coordinate system and reference frame according to convention 1 of DOI: 10.1088/0965-0393/23/8/083501. Direction of the positively pointing x-axis base vector of the processing_reference_frame. We assume the configuration is inspected by looking towards the sample surface from a position that is located behind the detector. Name or alias assigned to the x-axis base vector, e.g. rolling direction. Direction of the positively pointing y-axis base vector of the processing_reference_frame. We assume the configuration is inspected by looking towards the sample surface from a position that is located behind the detector. For further information consult also the help info for the xaxis_direction field. Name or alias assigned to the y-axis base vector, e.g. transverse direction. Direction of the positively pointing z-axis base vector of the processing_reference frame. We assume the configuration is inspected by looking towards the sample surface from a position that is located behind the detector. For further information consult also the help info for the xaxis_direction field. Name or alias assigned to the z-axis base vector, e.g. normal direction. Location of the origin of the processing_reference_frame. This specifies the location Xp = 0, Yp = 0, Zp = 0. Assume regions-of-interest in this reference frame form a rectangle or cuboid. Edges are interpreted by inspecting the direction of their outer unit normals (which point either parallel or antiparallel) along respective base vector direction of the reference frame. Details about the sample/specimen reference frame. Type of coordinate system and reference frame according to convention 1 of DOI: 10.1088/0965-0393/23/8/083501. The reference frame for the sample surface reference is used for identifying positions on a (virtual) image which is formed by information collected from an electron beam scanning the sample surface. We assume the configuration is inspected by looking towards the sample surface from a position that is located behind the detector. Reference DOI: 10.1016/j.matchar.2016.04.008 The sample surface reference frame has coordinates Xs, Ys, Zs. In three dimensions these coordinates are not necessarily located on the surface of the sample as there are multiple faces/sides of the sample. Most frequently though the coordinate system here is used to define the surface which the electron beam scans. Direction of the positively pointing x-axis base vector of the sample surface reference frame. We assume the configuration is inspected by looking towards the sample surface from a position that is located behind the detector. Different tools assume that different strategies can be used and are perceived as differently convenient to enter details about coordinate system definitions. In this ELN users have to possibility to fill in what they assume is sufficient to define the coordinate system directions unambiguously. Software which works with this user input needs to offer parsing capabilities which detect conflicting input and warn accordingly. Direction of the positively pointing y-axis base vector of the sample surface reference frame. We assume the configuration is inspected by looking towards the sample surface from a position that is located behind the detector. For further information consult also the help info for the xaxis_direction field. Direction of the positively pointing z-axis base vector of the sample surface reference frame. We assume the configuration is inspected by looking towards the sample surface from a position that is located behind the detector. For further information consult also the help info for the xaxis_direction field. Location of the origin of the sample surface reference frame. This specifies the location Xs = 0, Ys = 0, Zs = 0. Assume regions-of-interest in this reference frame form a rectangle or cuboid. Edges are interpreted by inspecting the direction of their outer unit normals (which point either parallel or antiparallel) along respective base vector direction of the reference frame. Details about the detector reference frame. Type of coordinate system/reference frame used for identifying positions in detector space Xd, Yd, Zd, according to DOI: 10.1016/j.matchar.2016.04.008. Direction of the positively pointing x-axis base vector of the detector space reference frame. We assume the configuration is inspected by looking towards the sample surface from a position that is located behind the detector. Different tools assume that different strategies can be used and are perceived as differently convenient to enter details about coordinate system definitions. In this ELN users have to possibility to fill in what they assume is sufficient to define the coordinate system directions unambiguously. Software which works with this user input needs to offer parsing capabilities which detect conflicting input and warn accordingly. Direction of the positively pointing y-axis base vector of the detector space reference frame. We assume the configuration is inspected by looking towards the sample surface from a position that is located behind the detector. For further information consult also the help info for the xaxis_direction field. Direction of the positively pointing z-axis base vector of the detector space reference frame. We assume the configuration is inspected by looking towards the sample surface from a position that is located behind the detector. For further information consult also the help info for the xaxis_direction field. Where is the origin of the detector space reference frame located. This is the location of Xd = 0, Yd = 0, Zd = 0. Assume regions-of-interest in this reference frame form a rectangle or cuboid. Edges are interpreted by inspecting the direction of their outer unit normals (which point either parallel or antiparallel) along respective base vector direction of the reference frame. Details about the gnomonic projection reference frame. Type of coordinate system/reference frame used for identifying positions in the gnomonic projection space Xg, Yg, Zg according to DOI: 10.1016/j.matchar.2016.04.008. Direction of the positively pointing "gnomomic" x-axis base vector when viewing how the diffraction pattern looks on the detector screen. We assume the configuration is inspected by looking towards the sample surface from a position that is located behind the detector. Different tools assume that different strategies can be used and are perceived as differently convenient to enter details about coordinate system definitions. In this ELN users have to possibility to fill in what they assume is sufficient to define the coordinate system directions unambiguously. Software which works with this user input needs to offer parsing capabilities which detect conflicting input and warn accordingly. Direction of the positively pointing "gnomomic" y-axis base vector when viewing how the diffraction pattern looks on the detector screen. We assume the configuration is inspected by looking towards the sample surface from a position that is located behind the detector. For further information consult also the help info for the xaxis_direction field. Direction of the positively pointing "gnomomic" z-axis base vector when viewing how the diffraction pattern looks on the detector screen. We assume the configuration is inspected by looking towards the sample surface from a position that is located behind the detector. For further information consult also the help info for the xaxis_direction field. Is the origin of the gnomonic coordinate system located where we assume the location of the pattern centre. This is the location Xg = 0, Yg = 0, Zg = 0 according to reference DOI: 10.1016/j.matchar.2016.04.008. Details about the definition of the pattern centre as a special point in the gnomonic projection reference frame. From which border of the EBSP (in the detector reference frame) is the pattern centre's x-position (PCx) measured? Keywords assume the region-of-interest is defined by a rectangle. We observe this rectangle and inspect the direction of the outer-unit normals to the edges of this rectangle. In which direction are positive values for PCx measured from the specified boundary. Keep in mind that the gnomonic space is in virtually all cases embedded in the detector space. Specifically, the XgYg plane is defined such that it is embedded/laying inside the XdYd plane (of the detector reference frame). When the normalization direction is the same as e.g. the detector x-axis direction, we state that we effectively normalize in fractions of the width of the detector. The issue with terms like width and height is that these degenerate if the detector region-of-interest is square-shaped. This is why we should better avoid talking about width and height but state how we would measure distances practically with a ruler and how we then measure positive distances. From which border of the EBSP (in the detector reference frame) is the pattern centre's y-position (PCy) measured? For further details inspect the help button of xaxis_boundary_convention. In which direction are positive values for PCy measured from the specified boundary. For further details inspect the help button of xaxis_normalization_direction. ././@PaxHeader0000000000000000000000000000024100000000000010212 xustar00122 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXem_ebsd_crystal_structure_model.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXem_ebsd_crystal_structure_mo0000644000077000000000000002113214777236751033214 0ustar00rosborn Number of reflectors (Miller crystallographic plane triplets). Number of atom positions. Crystal structure phase models used for indexing Kikuchi pattern. This base class contains key metadata relevant to every physical kinematic or dynamic diffraction model to be used for simulating Kikuchi diffraction pattern. The actual indexing of Kikuchi pattern however maybe use different algorithms which build on these simulation results but evaluate different workflows of comparing simulated and measured Kikuchi pattern to make suggestions which orientation is the most likely (if any) for each scan point investigated. Traditionally Hough transform based indexing has been the most frequently used algorithm. More and more dictionary based alternatives are used. Either way both algorithm need a crystal structure model. Identifier of an entry from crystallographic_database which was used for creating this structure model. Name of the crystallographic database to resolve crystallographic_database_identifier e.g. COD or others. Crystallography unit cell parameters a, b, and c. Crystallography unit cell parameters alpha, beta, and gamma. Volume of the unit cell Crystallographic space group True if space group is considered a centrosymmetric one. False if space group is considered a non-centrosymmetric one. Centrosymmetric has all types and combinations of symmetry elements (translation, rotational axis, mirror planes, center of inversion) Non-centrosymmetric compared to centrosymmetric is constrained (no inversion). Chiral compared to non-centrosymmetric is constrained (no mirror planes). True if space group is considered a chiral one. False if space group is consider a non-chiral one. Laue group Point group using International Notation. Crystal system Numeric identifier for each phase. The value 0 is reserved for the unknown phase essentially representing the null-model that no phase model was sufficiently significantly confirmed. Consequently, the value 0 must not be used as a phase_identifier. Name of the phase/alias. Labels for each atom position The hash value :math:`H` is :math:`H = Z + N*256` with :math:`Z` the number of protons and :math:`N` the number of neutrons of each isotope respectively. Z and N have to be 8-bit unsigned integers. For the rationale behind this `M. Kühbach et al. (2021) <https://doi.org/10.1017/S1431927621012241>`_ Atom positions x, y, z. Relative occupancy of the atom position. How many reflectors are distinguished. Value has to be n_hkl. Miller indices :math:`(hkl)`. D-spacing. Relative intensity of the signal for the plane. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXenergydispersion.nxdl.xml0000644000077000000000000000676714777236751032417 0ustar00rosborn Subclass of NXelectronanalyser to describe the energy dispersion section of a photoelectron analyser. Energy dispersion scheme employed, for example: tof, hemispherical, cylindrical, mirror, retarding grid, etc. Energy of the electrons on the mean path of the analyser. Pass energy for hemispherics, drift energy for tofs. Center of the energy window The interval of transmitted energies. It can be two different things depending on whether the scan is fixed or swept. With a fixed scan it is a 2 vector containing the extrema of the transmitted energy window (smaller number first). With a swept scan of m steps it is a 2xm array of windows one for each measurement point. Size, position and shape of a slit in dispersive analyzer, e.g. entrance and exit slits. Diameter of the dispersive orbit Way of scanning the energy axis (fixed or sweep). Length of the tof drift electrode Deflectors in the energy dispersive section Individual lenses in the energy dispersive section ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXevent_data_em.nxdl.xml0000644000077000000000000003251014777236751031602 0ustar00rosborn Metadata and settings of an electron microscope for scans and images. The need for such a structuring of data is evident from the fact that electron microscopes are dynamic. Oftentimes it suffices to calibrate the instrument at the start of the session. Subsequently, data (images, spectra, etc.) can be collected. Users may wish to take only a single scan or image and complete their microscope session; however frequently users are working much longer at the microscope, recalibrate and take multiple data items (scans, images, spectra). Each item comes with own detector and eventually on-the-fly processing settings and calibrations. For the single data item use case one may argue that the need for an additional grouping is redundant. Instead, the metadata could equally be stored inside the respective groups of the top-level mandatory NXinstrument group. On the flip side, even for a session with a single image, it would also not harm to nest the data. In fact, oftentimes scientists feel that there is a need to store details about eventual drift of the specimen in its holder (if such data is available) or record changes to the lens excitations or apertures used and/or changed. Although current microscopes are usually equipped with stabilization systems for many of the individual components, it can still be useful to store time-dependent data in detail. Another reason if not a need for having more finely granularizable options for storing time-dependent data, is that over the course of a session one may reconfigure the microscope. What is a reconfiguration? This could be the change of an aperture mode because a scientist may first collect an image with some aperture and then pick a different value and continue. As the aperture affects the electron beam, it will affect the system. Let aside for a moment the technology and business models, an EM could be monitored (and will likely become so more in the future) for streaming out spatio-temporal details about its components, locations of (hardware components) and objects within the region-of-interest. Eventually external stimuli are applied and the specimen repositioned. Some snapshot or integrated data from this stream are relevant for understanding signal genesis and electron/ion-beam-sample interaction (paths). In such a generic case it might be necessary to sync these streaming data with those intervals in time when specific measurements are taken (spectra collected, images taken, diffraction images indexed on-the-fly). Therefore, both the instrument and specimen should always be considered as dynamic. Scientists often report or feel (difficult to quantify) observations that microscopes *perform differently* across sessions, without sometimes being able to identify clear root causes. Users of the instrument may consider such conditions impractical, or *too poor* and thus either abort their session or try to bring the microscope first into a state where conditions are considered more stable, better, or of some whatever high enough quality to reuse data collection. In all these cases it is practical to have a mechanism how time-dependent data of the instrument state can be stored and documented in a interoperable way. Where should these data be stored? With NeXus these data should not only be stored in the respective instrument component groups of the top-level NXinstrument. The reason is that this group should be reserved for as stable as possible quantities which do not change over the session. Thereby we can avoid to store repetitively that there is a certain gun or detector available but just store the changes. This is exactly what the em_lab group is for inside NXevent_data_em. Ideally, NXevent_data_em are equipped with a start_time and end_time to represent a time interval (remind the idea of the instrument state stream) during which the scientist considered (or practically has to consider) the microscope (especially ebeam and specimen) as stable enough. Arguably it is oftentimes tricky to specify a clear time interval when the microscope is stable enough. Take for instance the acquisition of an image or spectra stack. It is not fully possible (technically) to avoid that even within a single image instabilities of the beam are faced and drift occurs. Maybe in many cases this these instabilities are irrelevant but does this warrant to create a data schema where either the microscope state can only be stored very coarsely or one is forced to store it very finely? This is a question of how one wishes to granularize pieces of information. A possible solution is to consider each probed position, i.e. point in time when the beam was not blanked and thus when the beam illuminates a portion of the material, i.e. the interaction volume, whose signal contributions are then counted by the one or multiple detector(s) as per pixel- or per voxel signal in the region-of-interest. NXevent_data_em in combination with the NXem application definition allows researchers to document this. Noteworty to mention is that we understand that in many cases realizing such a fine temporal and logical granularization and data collection is hard to achieve in practice. A frequently made choice, mainly for convenience, is that drift and scan distortions are considered a feature or inaccuracy of the image and/or spectrum and thus one de facto accepts that the microscope was not as stable as expected during the acquisition of the image. We learn that the idea of a time interval during the microscope session may be interpreted differently by different users. Here we consider the choice to focus on images and spectra, and eventually single position measurements as the smallest granularization level. Which eventually may require to add optional NXprocess instances for respectively collected data to describe the relevant distortions. Nevertheless, the distortions are typically corrected for by numerical protocols. This fact warrants to consider the distortion correction a computational workflow which can be modelled as a chain of NXprocess instances each with own parameters. an own A more detailed overview of such computational steps to cope with scan distortions is available in the literature: * `C. Ophus et al. <https://dx.doi.org/10.1016/j.ultramic.2015.12.002>`_ * `B. Berkels et al. <https://doi.org/10.1016/j.ultramic.2018.12.016>`_ * `L. Jones et al. <https://link.springer.com/article/10.1186/s40679-015-0008-4>`_ For specific simulation purposes, mainly in an effort to digitally repeat or simulate the experiment, it is tempting to consider dynamics of the instrument, implemented as time-dependent functional descriptions of e.g. lens excitations, beam shape functions, trajectories of groups of electrons, or detector noise models. For now the preferred strategy to handle these cases is through customizations of the specific fields within NXevent_data_em instances. Another alternative could be to sample finer, eventually dissimilarly along the time axi; however this may cause situations where an NXevent_data_em instance does not contain specific measurements (i.e. images, spectra of scientific relevance). In this case one should better go for a customized application definition with a functional property description inside members (fields or groups) in NXevent_data_em instances; or resort to a specific offspring application definition of NXem which documents metadata for tracking explicitly electrons (with ray-tracing based descriptors/computational geometry descriptors) or tracking of wave bundles. This perspective on much more subtle time-dependent considerations of electron microscopy can be advantageous also for storing details of time-dependent additional components that are coupled to and/or synced with a microscope. Examples include cutting-edge experiments where the electron beam gets coupled/excited by e.g. lasers. In this case, the laser unit should be registered under the top-level NXinstrument section. Its spatio-temporal details could be stored inside respective additional groups of the NXinstrument though inside instances of here detailed NXevent_data_em. ISO 8601 time code with local time zone offset to UTC information included when the snapshot time interval started. If the user wishes to specify an interval of time that the snapshot should represent during which the instrument was stable and configured using specific settings and calibrations, the start_time is the start (left bound of the time interval) while the end_time specifies the end (right bound) of the time interval. ISO 8601 time code with local time zone offset to UTC information included when the snapshot time interval ended. Reference to a specific state and setting of the microscope. Which specific event/measurement type. Examples are: * In-lens/backscattered electron, usually has quadrants * Secondary_electron, image, topography, fractography, overview images * Backscattered_electron, image, Z or channeling contrast (ECCI) * Bright_field, image, TEM * Dark_field, image, crystal defects * Annular dark field, image (medium- or high-angle), TEM * Diffraction, image, TEM, or a comparable technique in the SEM * Kikuchi, image, SEM EBSD and TEM diffraction * X-ray spectra (point, line, surface, volume), composition EDS/EDX(S) * Electron energy loss spectra for points, lines, surfaces, TEM * Auger, spectrum, (low Z contrast element composition) * Cathodoluminescence (optical spectra) * Ronchigram, image, alignment utility specifically in TEM * Chamber, e.g. TV camera inside the chamber, education purposes. This field may also be used for storing additional information about the event. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXevent_data_em_set.nxdl.xml0000644000077000000000000000306514777236751032460 0ustar00rosborn Container to hold NXevent_data_em instances of an electron microscope session. An event is a time interval during which the microscope was configured, considered stable, and used for characterization. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXfiber.nxdl.xml0000644000077000000000000002003214777236751030072 0ustar00rosborn Length of the spectrum vector (e.g. wavelength or energy) for which the refractive index of the core material is given. Length of the spectrum vector (e.g. wavelength or energy) for which the refractive index of the cladding material is given. Length of the spectrum vector (e.g. wavelength or energy) for which the attenuation curve is given. An optical fiber, e.g. glass fiber. Specify the quantities that define the fiber. Fiber optics are described in detail [here](https://www.photonics.com/Article.aspx?AID=25151&PID=4), for example. Descriptive name or brief description of the fiber, e.g. by stating its dimension. The dimension of a fiber can be given as 60/100/200 which refers to a core diameter of 60 micron, a clad diameter of 100 micron, and a coating diameter of 200 micron. Type/mode of the fiber. Modes of fiber transmission are shown in Fig. 5 [here](https://www.photonics.com/Article.aspx?AID=25151&PID=4). Type of dispersion. Spectrum-dependent (or refractive index-dependent) dispersion of the fiber. Specify in ps/nm*km. Core of the fiber, i.e. the part of the fiber which transmits the light. Specify the material of the core of the fiber. Core diameter of the fiber (e.g. given in micrometer). Complex index of refraction of the fiber. Specify at given wavelength (or energy, wavenumber etc.) values. Core of the fiber, i.e. the part of the fiber which transmits the light. Specify the material of the core of the fiber. Clad diameter of the fiber (e.g. given in micrometer). Complex index of refraction of the fiber. Specify at given wavelength (or energy, wavenumber etc.) values. Coating of the fiber. Specify the material of the coating of the fiber. Outer diameter of the fiber (e.g. given in micrometer). Length of the fiber. Spectral range for which the fiber is designed. Enter the minimum and maximum values (lower and upper limit) of the wavelength range. Unit of spectral array (e.g. nanometer or angstrom for wavelength, or electronvolt for energy etc.). Transfer rate of the fiber (in GB per second). GB/s Numerical aperture (NA) of the fiber. Wavelength-dependent attenuation of the fiber (specify in dB/km). Use dB/km. Power loss of the fiber in percentage. Acceptance angle of the fiber. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXgraph_edge_set.nxdl.xml0000644000077000000000000001135214777236751031750 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The number of edges. A set of (eventually directed) edges which connect nodes/vertices of a graph. Total number of edges, counting eventual bidirectional edges only once. Integer which specifies the first index to be used for distinguishing edges. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if the identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Integer used to distinguish edges for explicit indexing. Specifier whether each edge is non-directional, one-directional, or bidirectional. Use the smallest available binary representation which can store three different states: * 0 / state 0x00 is non-directional * 1 / state 0x01 is one-directional * 2 / state 0x02 is bi-directional Pairs of node/vertex identifier. Each pair represents the connection between two nodes. In the case that the edge is non- or bi-directional node identifier should be stored in ascending order is preferred. In the case of one-directional, for each pair the identifier of the source node is the first entry in the pair. The identifier of the target is the second entry in the pair, i.e. the pair encodes the information as if one traverses the edge from the source node walking to the target node. A human-readable qualifier which type or e.g. class instance the edge is an instance of. A human-readable label/caption/tag for the edge. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXgraph_node_set.nxdl.xml0000644000077000000000000000765514777236751032004 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The dimensionality of the graph. Eventually use one for categorical. The cardinality of the set, i.e. the number of nodes/vertices of the graph. A set of nodes/vertices in space representing members of a graph. Integer which specifies the first index to be used for distinguishing nodes. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if the identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Integer used to distinguish nodes for explicit indexing. A human-readable qualifier which type or e.g. class instance the node is an instance of. As e.g. a NeXus application definition is a graph, more specifically a hierarchical directed labelled property graph, instances which are groups like NXgraph_node_set could have an is_a qualifier reading NXgraph_node_set. A human-readable label/caption/tag of the graph. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXgraph_root.nxdl.xml0000644000077000000000000000311614777236751031153 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. An instance of a graph. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXibeam_column.nxdl.xml0000644000077000000000000001415114777236751031442 0ustar00rosborn Container for components of a focused-ion-beam (FIB) system. FIB capabilities turn especially scanning electron microscopes into specimen preparation labs. FIB is a material preparation technique whereby portions of the sample are illuminated with a focused ion beam with controlled intensity intense enough and with sufficient ion momentum to remove material in a controllable manner. The fact that an electron microscope with FIB capabilities has needs a second gun with own relevant control circuits, focusing lenses, and other components, warrants an own base class to group these components and distinguish them from the lenses and components for creating and shaping the electron beam. For more details about the relevant physics and application examples consult the literature, for example: * `L. A. Giannuzzi et al. <https://doi.org/10.1007/b101190>`_ * `E. I. Preiß et al. <https://link.springer.com/content/pdf/10.1557/s43578-020-00045-w.pdf>`_ * `J. F. Ziegler et al. <https://www.sciencedirect.com/science/article/pii/S0168583X10001862>`_ * `J. Lili <https://www.osti.gov/servlets/purl/924801>`_ The source which creates the ion beam. Given name/alias for the ion gun. Emitter type used to create the ion beam. If the emitter type is other, give further details in the description field. Which ionized elements or molecular ions form the beam. Examples are gallium, helium, neon, argon, krypton, or xenon, O2+. Average/nominal brightness Charge current Ion acceleration voltage upon source exit and entering the vacuum flight path. Affine transformation which detail the arrangement in the microscope relative to the optical axis and beam path. Individual characterization results for the position, shape, and characteristics of the ion beam. NXtransformations should be used to specify the location or position at which details about the ion beam are probed. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXimage_set.nxdl.xml0000644000077000000000000001124214777236751030743 0ustar00rosborn Number of images in the stack. Number of pixel per image in the slow direction. Number of pixel per image in the fast direction. Container for reporting a set of images taken. Details how images were processed from the detector readings. Resolvable data artifact (e.g. filename) from which the all values in the NXdata instances in this NXimage_set were loaded during parsing. An at least as strong as SHA256 hashvalue of the data artifact which source represents digitally to support provenance tracking. Imaging (data collection) mode of the instrument during acquisition of the data in this NXimage_set instance. Link or name of an NXdetector instance with which the data were collected. Image (stack). Image intensity values. Image identifier Image identifier. Pixel coordinate center of mass along y direction. Coordinate along y direction. Pixel coordinate center of mass along x direction. Coordinate along x direction. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXimage_set_em_adf.nxdl.xml0000644000077000000000000001376314777236751032250 0ustar00rosborn Number of images in the stack. Number of pixel per image in the slow direction. Number of pixel per image in the fast direction. Container for reporting a set of annular dark field images. Virtually the most important case is that spectra are collected in a scanning microscope (SEM or STEM) for a collection of points. The majority of cases use simple d-dimensional regular scan pattern, such as single point, line profiles, or (rectangular) surface mappings. The latter pattern is the most frequently used. For now the base class provides for scans for which the settings, binning, and energy resolution is the same for each scan point. Details how (HA)ADF images were processed from the detector readings. Typically the name of the input, (vendor) file from which all the NXdata instances in this NXimage_set_em_adf were loaded during parsing to represent them in e.g. databases. An at least as strong as SHA256 hashvalue of the dataset/file which represents the source digitally to support provenance tracking. Commercial or otherwise given name to the program which was used to process detector data into the adf image(s). Program version plus build number, commit hash, or description of an ever persistent resource where the source code of the program and build instructions can be found so that the program can be configured in such a manner that the result file is ideally recreatable yielding the same results. Annulus inner half angle Annulus outer half angle Annular dark field image stack. Image intensity values. Image identifier Image ID. Pixel center of mass along y direction. Coordinate along y direction. Pixel center of mass along x direction. Coordinate along x direction. ././@PaxHeader0000000000000000000000000000022600000000000010215 xustar00111 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXimage_set_em_kikuchi.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXimage_set_em_kikuchi.nxdl.xm0000644000077000000000000002355714777236751032773 0ustar00rosborn Number of scanned points. Scan point may have none, one, or more pattern. Number of diffraction pattern. Number of pixel per Kikuchi pattern in the slow direction. Number of pixel per Kikuchi pattern in the fast direction. Measured set of electron backscatter diffraction data, aka Kikuchi pattern. Kikuchi pattern are the raw data for computational workflows in the field of orientation (imaging) microscopy. The technique is especially used in materials science and materials engineering. Based on a fuse of the `M. A. Jackson et al. <https://doi.org/10.1186/2193-9772-3-4>`_ of the DREAM.3D community and the open H5OINA format of Oxford Instruments `P. Pinard et al. <https://doi.org/10.1017/S1431927621006103>`_ EBSD can be used, usually with FIB/SEM microscopes, for three-dimensional orientation microscopy. So-called serial section analyses. For a detailed overview of these techniques see e.g. * `M. A. Groeber et al. <https://doi.org/10.1186/2193-9772-3-5>`_ * `A. J. Schwartz et al. <https://doi.org/10.1007/978-1-4757-3205-4>`_ * `P. A. Rottman et al. <https://doi.org/10.1016/j.mattod.2021.05.003>`_ With serial-sectioning this involves however always a sequence of measuring, milling. In this regard, each serial section (measuring) and milling is an own NXevent_data_em instance and thus there such a three-dimensional characterization should be stored as a set of two-dimensional data, with as many NXevent_data_em instances as sections were measured. These measured serial sectioning images need virtually always post-processing to arrive at the aligned and cleaned image stack before a respective digital model of the inspected microstructure can be analyzed. The resulting volume is often termed a so-called (representative) volume element (RVE). Several software packages are available for performing this post-processing. For now we do not consider metadata of these post-processing steps as a part of this base class because the connection between the large variety of such post-processing steps and the measured electron microscopy data is usually very small. If we envision a (knowledge) graph for EBSD it consists of individual sub-graphs which convey information about the specimen preparation, the measurement of the specimen in the electron microscope, the indexing of the collected Kikuchi pattern stack, eventual post-processing of the indexed orientation image via similarity grouping algorithms to yield (grains, texture). Conceptually these post-processing steps are most frequently serving the idea to reconstruct quantitatively so-called microstructural features (grains, phases, interfaces). Materials scientists use these features according to the multi-scale materials modeling paradigm to infer material properties. They do so by quantifying correlations between the spatial arrangement of the features, their individual properties, and (macroscopic) properties of materials. Details how Kikuchi pattern were processed from the detector readings. Scientists interested in EBSD should inspect the respective NXem_ebsd application definition which can be used as a partner application definition to detail substantially more details to this processing. Collected Kikuchi pattern as an image stack. As raw and closest to the first retrievable measured data as possible, i.e. do not use this container to store already averaged, filtered or whatever post-processed pattern unless these are generated unmodifiably by the instrument given the way how the instrument and control software was configured for your microscope session. Array which resolves the scan point to which each pattern belongs. Scan points are evaluated in sequence starting from scan point zero until scan point n_sc - 1. Evaluating the cumulated of this array decodes which pattern in intensity belong to which scan point. In an example we may assume we collected three scan points. For the first we measure one pattern, for the second we measure three pattern, for the last we measure no pattern. The values of scan_point_identifier will be 0, 1, 1, 1, as we have measured four pattern in total. In most cases usually one pattern is averaged by the detector for some amount of time and then reported as one pattern. Use compressed arrays allows to store the scan_point_identifier efficiently. Signal intensity. For so-called three-dimensional or serial sectioning EBSD it is necessary to follow a sequence of specimen surface preparation and data collection. In this case users should collect the data for each serial sectioning step in an own instance of NXimage_set_em_kikuchi. All eventual post-processing of these measured data should be documented via NXebsd, resulting microstructure representations should be stored as NXms. Kikuchi pattern intensity Pattern are enumerated starting from 0 to n_p - 1. Kikuchi pattern identifier Pixel coordinate along the y direction. Label for the y axis Pixel coordinate along the x direction. Label for the x axis ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXinteraction_vol_em.nxdl.xml0000644000077000000000000000424514777236751032673 0ustar00rosborn Base class for storing details about a modelled shape of interaction volume. The interaction volume is mainly relevant in scanning electron microscopy when the sample is thick enough so that the beam is unable to illuminate through the specimen. Computer models like Monte Carlo or molecular dynamics / electron beam interaction simulations can be used to qualify and/or quantify the shape of the interaction volume. Explicit or implicit descriptions are possible. * An implicit description is via a set of electron/specimen interactions represented ideally as trajectory data from the computer simulation. * An explicit description is via an iso-contour surface using either a simulation grid or a triangulated surface mesh of the approximated iso-contour surface evaluated at specific threshold values. Iso-contours could be computed from electron or particle fluxes through an imaginary control surface (the iso-surface). Threshold values can be defined by particles passing through a unit control volume (electrons) or energy-levels (e.g. the case of X-rays). Details depend on the model. * Another explicit description is via theoretical models which may be relevant e.g. for X-ray spectroscopy Further details on how the interaction volume can be quantified is available in the literature for example: * `S. Richter et al. <https://doi.org/10.1088/1757-899X/109/1/012014>`_ * `J. Bünger et al. <https://doi.org/10.1017/S1431927622000083>`_ ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXion.nxdl.xml0000644000077000000000000001701614777236751027600 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Maximum number of atoms/isotopes allowed per (molecular) ion (fragment). Number of mass-to-charge-state-ratio range intervals for ion type. Set of atoms of a molecular ion or fragment in e.g. ToF mass spectrometry. A unique identifier whereby such an ion can be referred to via the service offered as described in identifier_type. How can the identifier be resolved? Ion type (ion species) identifier. The identifier zero is reserved for the special unknown ion type. A vector of isotope hash values. These values have to be stored in an array, sorted in decreasing order. The array is filled with zero hash values indicating unused places. The individual hash values are built with the following hash function: The hash value :math:`H` is :math:`H = Z + N*256` with :math:`Z` the number of protons and :math:`N` the number of neutrons of each isotope respectively. Z and N have to be 8-bit unsigned integers. For the rationale behind this `M. Kühbach et al. (2021) <https://doi.org/10.1017/S1431927621012241>`_ A supplementary row vector which decodes the isotope_vector into a human-readable matrix of nuclids with the following formatting: The first row specifies the isotope mass number, i.e. using the hashvalues from the isotope_vector this is :math:`Z + N`. As an example for a carbon-14 isotope the number is 14. The second row specifies the number of protons :math:`Z`, e.g. 6 for the carbon-14 example. This row matrix is thus a mapping the notation of using superscribed isotope mass and subscripted number of protons to identify isotopes. Unused places filling up to n_ivecmax need to be filled with zero. Color code used for visualizing such ions. Assumed volume of the ion. In atom probe microscopy this field can be used to store the reconstructed volume per ion (average) which is typically stored in range files and will be used when building a tomographic reconstruction of an atom probe dataset. Charge of the ion. Signed charge state of the ion in multiples of electron charge. Only positive values will be measured in atom probe microscopy as the ions are accelerated by a negatively signed bias electric field. In the case that the charge state is not explicitly recoverable, the value should be set to zero. In atom probe microscopy this is for example the case when using classical range file formats like RNG, RRNG for atom probe data. These file formats do not document the charge state explicitly. They report the number of atoms of each element per molecular ion surplus the mass-to-charge-state-ratio interval. With this it is possible to recover the charge state only for specific molecular ions as the accumulated mass of the molecular ion is defined by the isotopes, which without knowing the charge leads to an underconstrained problem. Details on ranging can be found in the literature: `M. K. Miller <https://doi.org/10.1002/sia.1719>`_ Human-readable ion type name (e.g. Al +++) The string should consists of ASCII UTF-8 characters, ideally using LaTeX notation to specify the isotopes, ions, and charge state. Examples are 12C + or Al +++. Although this name may be human-readable and intuitive, parsing such names becomes impractical for more complicated cases. Therefore, for the field of atom probe microscopy the isotope_vector should be the preferred machine-readable format to use. Associated lower (mqmin) and upper (mqmax) bounds of mass-to-charge-state ratio interval(s) [mqmin, mqmax] (boundaries included) for which the respective ion is one to be labelled with ion_identifier. The field is primarily of interest to document the result of indexing a ToF/mass spectrum. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXisocontour.nxdl.xml0000644000077000000000000000600114777236751031207 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The dimensionality of the description. Computational geometry description of isocontouring/phase-fields in Euclidean space. Iso-contouring algorithms such as MarchingCubes and others are frequently used to segment d-dimensional regions into regions where intensities are lower or higher than a threshold value, the so-called isovalue. Frequently in computational materials science phase-field methods are used which generate data on discretized grids. Isocontour algorithms are often used in such context to pinpoint the locations of microstructural features from this implicit phase-field-variable-based description. One of the key intentions of this base class is to provide a starting point for scientists from the phase-field community (condensed matter physicists, and materials engineers) to incentivize that also phase-field simulation data could be described with NeXus, provided base classes such as the this one get further extend according to the liking of the phase-field community. The discretized grid on which the iso-contour algorithm operates. The threshold or iso-contour value. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXiv_temp.nxdl.xml0000644000077000000000000000774614777236751030467 0ustar00rosborn Number of different temperature setpoints used in the experiment. Number of different voltage setpoints used in the experiment. Application definition for temperature-dependent IV curve measurements. In this application definition, times should be specified always together with an UTC offset. This is the application definition describing temperature dependent IV curve measurements. For this a temperature is set. After reaching the temperature, a voltage sweep is performed. For each voltage a current is measured. Then, the next desired temperature is set and an IV measurement is performed. Describes an environment setup for a temperature-dependent IV measurement experiment. The temperature and voltage must be present as independently scanned controllers and the current sensor must also be present with its readings. This NXdata should contain separate fields for the current values at different temperature setpoints, for example current_at_100C. There should also be two more fields called temperature and voltage containing the setpoint values. There should also be a field with an array of rank equal to the number of different temperature setpoints and each child's dimension equal to the number of voltage setpoints. ././@PaxHeader0000000000000000000000000000025200000000000010214 xustar00131 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXlab_electro_chemo_mechanical_preparation.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXlab_electro_chemo_mechanical0000644000077000000000000002067514777236751033047 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Grinding and polishing of a sample using abrasives in a wet lab. Manual procedures, electro-chemical, vibropolishing. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. A preparation step performed by a human or a robot/automated system. Carrier/plate used on which the abrasive/(lubricant) mixture was applied. Medium on the abrasive_medium_carrier (cloth or grinding plate) whereby material is abrasively weared. Lubricant Qualitative statement how the revelation of the machine was configured. If the rotation was controlled manually, e.g. by turning knobs choose manual and estimate the nominal average rotation. If the rotation was controlled via choosing from a fixed set of options offered by the machine choose fixed and specify the nominal rotation. If programmed use rotation_history (e.g. for automated/robot systems). Qualitative statement how the (piston) force with which the sample was pressed into/against the abrasive medium was controlled if at all. If the force was controlled manually e.g. by turning knobs choose manual and estimate nominal average force. If the force was controlled via choosing from a fixed set of options offered by the machine choose fixed and specify the nominal force. If programmed use force_history (e.g. for automated/robot systems). Qualitative statement for how long (assuming regular uninterrupted) preparation at the specified conditions the preparation step was applied. Turns per unit time. Force exerted on the sample to press it into the abrasive. Seconds Qualitative statement how the material removal was characterized. How thick a layer was removed. A preparation step performed by a human or a robot/automated system with the aim to remove residual abrasive medium from the specimen surface. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXlab_sample_mounting.nxdl.xml0000644000077000000000000000770314777236751033034 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Embedding of a sample in a medium for easing processability. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Qualitative statement how the sample was mounted. Type of material. Electrical conductivity of the embedding medium. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXlens_opt.nxdl.xml0000644000077000000000000001646614777236751030646 0ustar00rosborn Size of the wavelength array for which the refractive index of the material is given. Size of the wavelength array for which the refractive index of the coating is given. Size of the wavelength array for which the reflectance or transmission of the lens is given. Description of an optical lens. Type of the lens (e.g. concave, convex etc.). If you chose 'other' as type specify what it is. Is it a chromatic lens? Diameter of the lens. Properties of the substrate material of the lens. If the lens has a coating specify the coating material and its properties in 'coating'. Specify the substrate material of the lens. Thickness of the lens substrate at the optical axis. Complex index of refraction of the lens material. Specify at given wavelength (or energy, wavenumber etc.) values. If the lens has a coating describe the material and its properties. Some basic information can be found e.g. [here] (https://www.opto-e.com/basics/reflection-transmission-and-coatings). If the back and front side of the lens are coated with different materials, use separate COATING(NXsample) fields to describe the coatings on the front and back side, respectively. For example: coating_front(NXsample) and coating_back(NXsample). Specify the coating type (e.g. dielectric, anti-reflection (AR), multilayer coating etc.). Describe the coating material (e.g. MgF2). Thickness of the coating. Complex index of refraction of the coating. Specify at given spectral values (wavelength, energy, wavenumber etc.). Reflectance of the lens at given spectral values. Transmission of the lens at given spectral values. Focal length of the lens on the front side (first value), i.e. where the beam is incident, and on the back side (second value). Curvature radius of the lens. Instead of 'FACE' in the name of this field, the user is advised to specify for which surface (e.g. front or back) the curvature is provided: e.g. curvature_front or curvature_back. The front face is the surface on which the light beam is incident, while the back face is the one from which the light beam exits the lens. Abbe number (or V-number) of the lens. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXmagnetic_kicker.nxdl.xml0000644000077000000000000000470614777236751032134 0ustar00rosborn definition for a magnetic kicker. extended description of the kicker. define position of beamline element relative to production target kicker timing as defined by ``description`` attribute current set on supply. current read from supply. voltage set on supply. voltage read from supply. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXmanipulator.nxdl.xml0000644000077000000000000000620514777236751031344 0ustar00rosborn Extension of NXpositioner to include fields to describe the use of manipulators in photoemission experiments. Name of the manipulator. A description of the manipulator. Type of manipulator, Hexapod, Rod, etc. Is cryocoolant flowing through the manipulator? Temperature of the cryostat (coldest point) Power in the heater for temperature control. Temperature at the closest point to the sample. This field may also be found in NXsample if present. Current to neutralize the photoemission current. This field may also be found in NXsample if present. Possible bias of the sample with trespect to analyser ground. This field may also be found in NXsample if present. Class to describe the motors that are used in the manipulator ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXmatch_filter.nxdl.xml0000644000077000000000000000517214777236751031454 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. How many different match values does the filter specify. Settings of a filter to select or remove entries based on their value. Meaning of the filter: Whitelist specifies which entries with said value to include. Entries with all other values will be filtered out. Blacklist specifies which entries with said value to exclude. Entries with all other values will be included. Array of values to filter according to method. For example if the filter specifies [1, 5, 6] and method is whitelist, only entries with values matching 1, 5 or 6 will be processed. All other entries will be filtered out. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXmpes.nxdl.xml0000644000077000000000000004444214777236751027762 0ustar00rosborn This is the most general application definition for multidimensional photoelectron spectroscopy. Datetime of the start of the measurement. Contact information of at least the user of the instrument or the investigator who performed this experiment. Adding multiple users if relevant is recommended. Name of the user. Name of the affiliation of the user at the point in time when the experiment was performed. Full address (street, street number, ZIP, city, country) of the user's affiliation. Email address of the user. Author ID defined by https://orcid.org/. The source used to generate the primary photons. Properties refer strictly to parameters of the source, not of the output beam. For example, the energy of the source is not the optical power of the beam, but the energy of the electron beam in a synchrotron and so on. Type of probe. In photoemission it's always photons, so the full NIAC list is restricted. Distance of the point of evaluation of the beam from the sample surface. Energy resolution of the analyser with the current setting. May be linked from a NXcalibration. Scheme of the electron collection column. The size and position of the field aperture inserted in the column. To add additional or other apertures use the APERTURE group of NXcollectioncolumn. The size and position of the contrast aperture inserted in the column. To add additional or other apertures use the APERTURE group of NXcollectioncolumn. Size, position and shape of the entrance slit in dispersive analyzers. To add additional or other slits use the APERTURE group of NXenergydispersion. Size, position and shape of the exit slit in dispersive analyzers. To add additional or other slits use the APERTURE group of NXenergydispersion. Type of electron amplifier in the first amplification step. Description of the detector type. Raw data before calibration. Manipulator for positioning of the sample. Document an event of data processing, reconstruction, or analysis for this data. Describe the appropriate axis calibrations for your experiment using one or more of the following NXcalibrations Has an energy calibration been applied? This is the calibrated energy axis to be used for data plotting. Has an angular calibration been applied? This is the calibrated angular axis to be used for data plotting. Has an spatial calibration been applied? This is the calibrated spatial axis to be used for data plotting. Has an momentum calibration been applied? This is the momentum axis to be used for data plotting. The chemical formula of the sample. For mixtures use the NXsample_component group in NXsample instead. A descriptor to keep track of the treatment of the sample before entering the photoemission experiment. Ideally, a full report of the previous operations, in any format (NXnote allows to add pictures, audio, movies). Alternatively, a reference to the location or a unique identifier or other metadata file. In the case these are not available, free-text description. List of comma-separated elements from the periodic table that are contained in the sample. If the sample substance has multiple components, all elements from each component must be included in `atom_types`. Date of preparation of the sample for the XPS experiment (i.e. cleaving, last annealing). Description of the surface preparation technique for the XPS experiment, i.e. UHV cleaving, in-situ growth, sputtering/annealing etc. Ideally, a full report of the previous operations, in any format(NXnote allows to add pictures, audio, movies). Alternatively, a reference to the location or a unique identifier or other metadata file. In the case these are not available, free-text description. In the case of a fixed temperature measurement this is the scalar temperature of the sample. In the case of an experiment in which the temperature is changed and recoded, this is an array of length m of temperatures. This should be a link to /entry/instrument/manipulator/sample_temperature. Represents a measure of one- or more-dimensional photoemission counts, where the varied axis may be for example energy, momentum, spatial coordinate, pump-probe delay, spin index, temperature, etc. The axes traces should be linked to the actual encoder position in NXinstrument or calibrated axes in NXprocess. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXms.nxdl.xml0000644000077000000000000007266514777236751027445 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Number of boundaries of the bounding box or primitive to domain. Number of parameter required for the chosen orientation parameterization. Number of texture components identified. Application definition, spatiotemporal characterization of a microstructure. An at least as strong as SHA256 hashvalue of the file that specifies the application definition. NeXus NXDL schema to which this file conforms. Ideally, a (globally) unique persistent identifier for referring to this experiment or computer simulation. The identifier is usually defined/issued by the facility, laboratory, or the principle investigator. The identifier enables to link experiments to e.g. proposals. Free-text description about the workflow (experiment/analysis/simulation). Users are strongly advised to detail the sample history in the respective field and fill rather as completely as possible the fields of this application definition rather than write details about the experiment into this free-text description field. ISO 8601 time code with local time zone offset to UTC information included when the characterization started. ISO 8601 time code with local time zone offset to UTC included when the characterization ended. Specify if the (characterization) results/data of this instance of an application definition are based on the results of a simulation or the results of a post-processing of measured data to describe a microstructure. The term microstructure is used to describe the spatial arrangement of crystal defects inside a sample/specimen without demanding necessarily that this structure is mainly at the micron length scale. Nanostructure and macrostructure are close synonyms. Material architecture is a narrow synonym. Given that microstructure simulations nowadays more and more consider the atomic arrangement, this application definition can also be used to describe features at the scale of atoms. Contact information and eventually details of at least one person involved in creating this result. This can be the principle investigator who performed this experiment. Adding multiple users if relevant is recommended. Given (first) name and surname of the user. Name of the affiliation of the user at the point in time when the experiment was performed. Postal address of the affiliation. Email address of the user at the point in time when the experiment was performed. Writing the most permanently used email is recommended. Globally unique identifier of the user as offered by services like ORCID or ResearcherID. If this field is field the specific service should also be written in orcid_platform Name of the OrcID or ResearcherID where the account under orcid is registered. (Business) (tele)phone number of the user at the point in time when the experiment was performed. Which role does the user have in the place and at the point in time when the experiment was performed? Technician operating the microscope. Student, postdoc, principle investigator, guest are common examples. Account name that is associated with the user in social media platforms. Name of the social media platform where the account under social_media_name is registered. Descriptive name or ideally (globally) unique persistent identifier. Hard link to a location in the hierarchy of the NeXus file where the data for default plotting are stored. Container to hold different coordinate systems conventions. A least a right-handed Cartesian coordinate system with base vectors named x, y, and z has to be specified. Each base vector of the coordinate system should be described with an NXtransformations instance. The simulated or characterized material volume element aka domain. At least one instance of geometry required either NXcg_grid, NXcg_polyhedron_set, or NXcg_point_set. This geometry group needs to contain details about the boundary conditions. A boundary to the volume element. Either an instance of NXcg_hexahedron_set or of NXcg_ellipsoid_set. How many distinct boundaries are distinguished. Value required equal to n_b. Name of the boundaries. E.g. left, right, front, back, bottom, top, The boundary conditions for each boundary: 0 - undefined 1 - open 2 - periodic 3 - mirror 4 - von Neumann 5 - Dirichlet Collection of microstructural data observed/simulated. Integer which specifies the first index to be used for distinguishing snapshots. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if the identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Summary quantities which are the result of some post-processing of the snapshot data (averaging, integrating, interpolating). Frequently used descriptors from continuum mechanics and thermodynamics can be used here. A few examples are given. Each descriptor is currently modelled as an instance of an NXprocess because it is relevant to understand how the descriptors are computed. Measured or simulated physical time stamp for this snapshot. Not to be confused with wall-clock timing or profiling data. Iteration or increment counter. Conceptually distinguished object/feature in the ROI/ system with some relevance. Instances of NXms_feature_set can be nested to build a hierarchy of logically-related objects. A typical example for MD simulations is to have one ms_feature_set for the atoms which is the parent to another ms_feature_set for monomers/molecules/proteins which is then the parent to another ms_feature_set for the secondary, another feature_set for the tertiary, and the parent for another feature_set for the quaternary structure. Another typical example from materials engineering is to have one ms_feature_set for crystals (grains/phases) which serves as the parent to another ms_feature_set for interfaces between these crystals which then is the parent for another ms_feature_set to describe the triple junctions which is then the parent for the quadruple/higher-order junctions between which connect the triple lines. Another example from discrete dislocation dynamics could be to have one ms_feature_set for the dislocations (maybe separate sets for each dislocation type or family) which are then parents to other ms_feature_set which describe junctions between dislocations or features along the dislocation line network. Details about the orientation distribution function within the entire domain. With which method was the ODF approximated? TO BE DEFINED TO BE DEFINED Collection of texture components commonly referred to. Reference to or definition of a coordinate system with which the definitions are interpretable. Parameterized orientations. Name of each texture component, e.g. Cube, Dillamore, Y. The portion of orientation space integrated over to compute the volume fraction. The volume fraction of each texture component. Details about the disorientation distribution function within the entire domain. Details about the grain boundary character distribution within the entire domain. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXms_feature_set.nxdl.xml0000644000077000000000000004025014777236751032014 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Dimensionality Cardinality/number of members/features in the feature set. Number of types in the dictionary of human-readable types of features. Total number of parent identifier. Set of topological/spatial features in materials build from other features. Name (or link?) to another NXms_feature_set which defines features what are assumed as the parents/super_features of all members in this feature set. If depends_on is set to "." or this attribute is not defined in an instance of this application definition, assume that this feature_set instance represents the root feature_set of the feature tree/graph. What is the best matching description how dimensional the feature is. How many features/members are in this set? The keywords of the dictionary of human-readable types of features. Using terms from a community-agreed upon controlled vocabulary, e.g. atom, solute, vacancy, monomer, molecule, anti-site, crowd_ion, quadruple junction, triple line, disconnection, dislocation, kink, jog, stacking_fault, homo_phase_boundary, hetero_phase_boundary, surface, thermal_groove_root, precipitate, dispersoid, pore, crack is recommended. The integer identifier used to resolve of which type each feature is, i.e. the values of the dictionary of human-readable types of features. For each feature in the set specify the associated number of identifier to parent features as are resolvable via depends_on. This array enables to compute the array interval from which details for specific features can be extracted as if they would be stored in an own group. Concatenated array of parent identifier for each feature (in the sequence) according to identifier and how the identifier of features in the here described feature set are defined (implicitly from 0, to c-1 or via explicit identifier. Integer which specifies the first index to be used for distinguishing features. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if the identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Integer used to distinguish features for explicit indexing. Assumptions and parameter to arrive at geometric primitives to locate zero-dimensional/point-(like) features which are discretized/represented by points. Assumptions, parameters, and details how positional uncertainty of the geometry is quantified. Assumptions and parameters to arrive at geometric primitives to locate one-dimensional/line-like features which are discretized by polylines. Assumptions, parameters, and details how positional uncertainty of the geometry is quantified. Assumptions and parameters to arrive at geometric primitives to locate two-dimensional/interface features which are discretized by triangulated surface meshes. Assumptions, parameters, and details how positional uncertainty of the geometry is quantified. Assumptions and parameters to arrive at geometric primitives to locate three-dimensional/volumetric features which are discretized by triangulated surface meshes of polyhedra. Assumptions, parameters, and details how positional uncertainty of the geometry is quantified. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXms_score_config.nxdl.xml0000644000077000000000000004677114777236751032164 0ustar00rosborn Number of Bunge-Euler angle triplets for deformed grains. Number of Bunge-Euler angle triplets for recrystallization nuclei. Number of solitary unit domains to export. Application definition to control a simulation with the SCORE model. Version specifier of this application definition. Official NeXus NXDL schema with which this file was written. Ideally, a (globally persistent) unique identifier for referring to this analysis. Possibility for leaving a free-text description about this analysis. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. ISO 8601 formatted time code with local time zone offset to UTC information included when this configuration file was created. Relevant data to instantiate a starting configuration that is typically a microstructure in deformed conditions where stored (elastic) energy is stored in the form of crystal defects, which in the SCORE model are is considered as mean-field dislocation content. Which model should be used to generate a starting microstructure. Edge length of the cubic cells of each CA domain. Extend of each CA domain in voxel along the x, y, and z direction. Deformation of sheet material is assumed. The x axis is assumed pointing along the rolling direction. The y axis is assumed pointing along the transverse direction. The z axis is assumed pointing along the normal direction. Extent of each deformed grain along the x, y, and z direction when type is cuboidal. Average spherical diameter when type is poisson_voronoi. Set of Bunge-Euler angles to sample orientations randomly from. The EBSD dataset from which the initial microstructure is instantiated if initial_microstructure/type has value ebsd. Path and name of the EBSD dataset from which to generate the starting microstructure. SHA256 checksum of the file which contains the EBSD dataset. Size of the EBSD. The EBSD orientation mapping has to be on a regular grid of square-shaped pixels. Phenomenological model according to which it nuclei are placed into the domain and assumed growing. According to which model will the nuclei become distributed spatially. CSR means complete spatial randomness. Custom is implementation specific. GB places nuclei at grain boundaries. According to which model will the nuclei start to grow. According to which model will the nuclei get their orientation assigned. Set of Bunge-Euler angles to sample orientations of nuclei randomly from. (Mechanical) properties of the material which scale the amount of stored (elastic) energy in the ROI/system. Shear modulus at zero Kelvin. Magnitude at the Burgers vector at zero Kelvin. Melting temperature in degrees Celsius. Model for the assumed mobility of grain boundaries with different disorientation. Which type of fundamental model for the grain boundary mobility: For the Sebald-Gottstein model the following equation is used. For the Rollett-Holm model the following equation is used. Simulated evolution of the dislocation density as the stored (elastic) energy assumed stored in each grain. Which type of recovery model. Simulated reduction of the grain boundary speed due to the presence of dispersoids through which the total grain boundary area of the recrystallization front can be reduced. Which type of drag model. Support point of the linearized curve of simulated time matching a specific support point of the average dispersoid radius. Support point of the linearized curve of the average dispersoid radius. Simulated time temperature profile Support point of the linearized curve of simulated time matching a specific support point of the temperature. Support point of the linearized curve of the temperature. Criteria which enable to stop the simulation in a controlled manner. Whichever criterion is fulfilled first stops the simulation. Maximum recrystallized volume fraction. Maximum simulated physical time. Maximum number of iteration steps. Settings relevant for stable numerical integration. Maximum fraction equivalent to the migration of the fastest grain boundary in the system how much a cell may be consumed in a single iteration. Fraction of the total number of cells in the CA which should initially be allocated for offering cells in the recrystallization front. By how much more times should the already allocated memory be is increased to offer space for storing states of cells in the recrystallization front. Should the cache for cells in the recrystallization front be defragmented on-the-fly. Heuristic recrystallized volume target values at which the cache for cells in the recrystallization front will be defragmented on-the-fly. List of recrystallized volume target values at which a snapshot of the CA state should be exported for. Perform a statistical analyses of the results as it was proposed by M. Kühbach (solitary unit model ensemble approach). How many independent cellular automaton domains should be instantiated. Into how many time steps should the real time interval be discretized upon during post-processing the results with the solitary unit modeling approach. List of identifier for those domain which should be rendered. Identifier start from 0. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXms_score_results.nxdl.xml0000644000077000000000000010652214777236751032407 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Number of boundaries of the bounding box or primitive to domain. Number of parameter required for chosen orientation parameterization. Number of texture components identified. Dimensionality. Cardinality. Number of active cells in the (recrystallization) front. Number of grains in the computer simulation. Application definition for storing results of the SCORE cellular automaton. The SCORE cellular automaton model for primary recrystallization is an example of typical materials engineering applications used within the field of so-called Integral Computational Materials Engineering (ICME) whereby one can simulate the evolution of microstructures. Specifically the SCORE model can be used to simulate the growth of static recrystallization nuclei. The model is described in the literature: * `M. Kühbach et al. <https://doi.org/10.1016/j.actamat.2016.01.068>`_ * `C. Haase et al. <https://doi.org/10.1016/j.actamat.2015.08.057>`_ * `M. Diehl et al. <https://doi.org/10.1088/1361-651X/ab51bd>`_ An at least as strong as SHA256 hashvalue of the file that specifies the application definition. NeXus NXDL schema to which this file conforms. Ideally, a (globally) unique persistent identifier for referring to this computer simulation. The identifier is usually defined/issued by the facility, laboratory, or the principle investigator. The identifier enables to link experiments to e.g. proposals. Free-text description about the workflow (analysis/simulation). Users are strongly advised to detail the sample history in the respective field and fill rather as completely as possible the fields of this application definition rather than write details about the experiment into this free-text description field. ISO 8601 time code with local time zone offset to UTC information included when the characterization started. ISO 8601 time code with local time zone offset to UTC included when the characterization ended. Specify if the (characterization) results/data of this instance of an application definition are based on the results of a simulation or the results of a post-processing of measured data to describe a microstructure. The term microstructure is used to describe the spatial arrangement of crystal defects inside a sample/specimen without demanding necessarily that this structure is mainly at the micron length scale. Nanostructure and macrostructure are close synonyms. Material architecture is a narrow synonym. The path and name of the config file for this analysis. At least SHA256 strong hash of the specific config_file for tracking provenance. Path to the directory where the tool should store NeXus/HDF5 results of this analysis. If not specified results will be stored in the current working directory. A statement whether the SCORE executable managed to process the analysis or failed prematurely. This status is written to the results file after the end_time at which point the executable must not compute any analysis. Only when this status message is present and shows `success`, the user should consider the results. In all other cases it might be that the executable has terminated prematurely or another error occurred. Contact information and eventually details of at least one person involved in creating this result. This can be the principle investigator who performed this experiment. Adding multiple users if relevant is recommended. Given (first) name and surname of the user. Name of the affiliation of the user at the point in time when the experiment was performed. Postal address of the affiliation. Email address of the user at the point in time when the experiment was performed. Writing the most permanently used email is recommended. Globally unique identifier of the user as offered by services like ORCID or ResearcherID. If this field is field the specific service should also be written in orcid_platform Name of the OrcID or ResearcherID where the account under orcid is registered. (Business) (tele)phone number of the user at the point in time when the experiment was performed. Which role does the user have in the place and at the point in time when the experiment was performed? Technician operating the microscope. Student, postdoc, principle investigator, guest are common examples. Account name that is associated with the user in social media platforms. Name of the social media platform where the account under social_media_name is registered. Descriptive name or ideally (globally) unique persistent identifier. Hard link to a location in the hierarchy of the NeXus file where the data for default plotting are stored. Container to hold different coordinate systems conventions. A least a right-handed Cartesian coordinate system with base vectors named x, y, and z has to be specified. Each base vector of the coordinate system should be described with an NXtransformations instance. The simulated or characterized material volume element aka domain. At least one instance of geometry required either NXcg_grid, NXcg_polyhedron_set, or NXcg_point_set. This geometry group needs to contain details about the boundary conditions. A tight bounding box or sphere or bounding primitive about the grid. How many distinct boundaries are distinguished? Most grids discretize a cubic or cuboidal region. In this case six sides can be distinguished, each making an own boundary. Name of the boundaries. E.g. left, right, front, back, bottom, top, The field must have as many entries as there are number_of_boundaries. The boundary conditions for each boundary: 0 - undefined 1 - open 2 - periodic 3 - mirror 4 - von Neumann 5 - Dirichlet Collection of microstructural data observed/simulated. Integer which specifies the first index to be used for distinguishing snapshots. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if the identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Summary quantities which are the result of some post-processing of the snapshot data (averaging, integrating, interpolating). Frequently used descriptors from continuum mechanics and thermodynamics can be used here. A few examples are given. Each descriptor is currently modelled as an instance of an NXprocess because it is relevant to understand how the descriptors are computed. Evolution of the physical time. Evolution of the simulated temperature over time. Evolution of the recrystallized volume fraction over time. Measured or simulated physical time stamp for this snapshot. Not to be confused with wall-clock timing or profiling data. Simulated temperature. Iteration or increment counter. Grain identifier for each cell. Identifier of the OpenMP thread which processed this part of the grid. Details about those cells which in this time step represent the discretized recrystallization front. Which cells are currently in a halo region of threads. So-called mobility weight which is a scaling factor to control the mobility of the grain boundary which is assumed to sweep currently this volume. Grid coordinates of each cell in the recrystallization front. Grain identifier assigned to each cell in the recrystallization front. Grain identifier assigned to each nucleus which affected that cell in the recrystallization front. Relative volume transformed as a measure of infection progress. Identifier of the OpenMP thread processing each cell in the recrystallization front. Hint about the direction from which the cell was infected. Current grain-related quantities. Bunge-Euler angle triplets for each grain. Discrete volume of each grain accounting also for partially transformed cells. Current value for the dislocation density as a measure of the remaining stored energy in assumed crystal defects inside each grain. The difference between these values scales the driving force of grain boundary migration. Is the grain deformed. Is the grain recrystallized. Current recrystallized volume fraction. Currently evaluated actual recrystallized volume fraction. This takes into account partially recrystallized cells. Currently desired target recrystallized volume fraction at which the user requested to log a snapshot. Currently assumed globally applied Cauchy stress tensor on the ROI. Currently assumed globally applied Cauchy strain tensor on the ROI. Specify if it was different from the number_of_processes in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. Specify if it was different from the number_of_threads in the NXcs_profiling super class. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXms_snapshot.nxdl.xml0000644000077000000000000000423014777236751031343 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Base class for data on the state of the microstructure at a given time/iteration. Is this time for a measurement or a simulation. Measured or simulated physical time stamp for this snapshot. Not to be confused with wall-clock timing or profiling data. Iteration or increment counter. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXms_snapshot_set.nxdl.xml0000644000077000000000000000553314777236751032225 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. A collection of spatiotemporal microstructure data. Is this set describing a measurement or a simulation? Integer which specifies the first index to be used for distinguishing snapshots. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if the identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXopt.nxdl.xml0000644000077000000000000012713714777236751027623 0ustar00rosborn Variables used throughout the document, e.g. dimensions or parameters. Length of the spectrum array (e.g. wavelength or energy) of the measured data. Number of sensors used to measure parameters that influence the sample, such as temperature or pressure. Number of measurements (1st dimension of measured_data array). This is equal to the number of parameters scanned. For example, if the experiment was performed at three different temperatures and two different pressures N_measurements = 2*3 = 6. Number of detection angles of the beam reflected or scattered off the sample. Number of angles of incidence of the incident beam. Number of observables that are saved in a measurement. e.g. one for intensity, reflectivity or transmittance, two for Psi and Delta etc. This is equal to the second dimension of the data array 'measured_data' and the number of column names. An application definition for optical spectroscopy experiments. An application definition template for optical spectroscopy experiments. A general optical experiment consists of a light or excitation source, a beam path, a sample + its stage + its environment, and a detection unit. Examples are reflection or transmission measurements, photoluminescence, Raman spectroscopy, ellipsometry etc. An application definition describing a general optical experiment. Version number to identify which definition of this application definition was used for this entry/data. URL where to find further material (documentation, examples) relevant to the application definition. A (globally persistent) unique identifier of the experiment. (i) The identifier is usually defined by the facility or principle investigator. (ii) The identifier enables to link experiments to e.g. proposals. An optional free-text description of the experiment. However, details of the experiment should be defined in the specific fields of this application definition rather than in this experiment description. Specify the type of the optical experiment. Start time of the experiment. UTC offset should be specified. Contact information of at least the user of the instrument or the investigator who performed this experiment. Adding multiple users, if relevant, is recommended. Name of the user. Name of the affiliation of the user at the point in time when the experiment was performed. Street address of the user's affiliation. Email address of the user. Author ID defined by https://orcid.org/. Telephone number of the user. Properties of the experimental setup. This includes general information about the instrument (such as model, company etc.), information about the calibration of the instrument, elements of the beam path including the excitation or light source and the detector unit, the sample stage (plus the sample environment, which also includes sensors used to monitor external conditions) and elements of the beam path. Meta data describing the sample should be specified in ENTRY/SAMPLE outside of ENTRY/INSTRUMENT. The name of the instrument. The used version of the hardware if available. If not a commercial instrument use date of completion of the hardware. Name of the company which build the instrument. ISO8601 date when the instrument was constructed. UTC offset should be specified. Commercial or otherwise defined given name of the program that was used to measure the data, i.e. the software used to start and record the measured data and/or metadata. If home written, one can provide the actual steps in the NOTE subfield here. Either version with build number, commit hash, or description of a (online) repository where the source code of the program and build instructions can be found so that the program can be configured in such a way that result files can be created ideally in a deterministic manner. Website of the software. Commercial or otherwise defined name of the firmware that was used for the measurement - if available. Version and build number or commit hash of the software source code. Website of the software. Was a calibration performed? If yes, when was it done? If the calibration time is provided, it should be specified in ENTRY/INSTRUMENT/calibration/calibration_time. The calibration data and metadata should be described in a separate NeXus file with the link provided in 'calibration_link'. If calibtration status is 'calibration time provided', specify the ISO8601 date when calibration was last performed before this measurement. UTC offset should be specified. Link to the NeXus file containing the calibration data and metadata. Describes an arrangement of optical or other elements, e.g. the beam path between the light source and the sample, or between the sample and the detector unit (including the sources and detectors themselves). If a beam splitter (i.e. a device that splits the incoming beam into two or more beams) is part of the beam path, two or more NXbeam_path fields may be needed to fully describe the beam paths and the correct sequence of the beam path elements. Use as many beam paths as needed to describe the setup. Angle(s) of the incident beam vs. the normal of the bottom reflective (substrate) surface in the sample. Detection angle(s) of the beam reflected or scattered off the sample vs. the normal of the bottom reflective (substrate) surface in the sample if not equal to the angle(s) of incidence. Sample stage, holding the sample at a specific position in X,Y,Z (Cartesian) coordinate system and at an orientation defined by three Euler angles (alpha, beta, gamma). Specify the type of the sample stage. If there is no motorized stage, we should at least qualify where the beam hits the sample and in what direction the sample stands in a free-text description, e.g. 'center of sample, long edge parallel to the plane of incidence'. Specify external parameters that have influenced the sample, such as the surrounding medium, and varied parameters e.g. temperature, pressure, pH value, optical excitation etc. Describe what was the medium above or around the sample. The common model is built up from the substrate to the medium on the other side. Both boundaries are assumed infinite in the model. Here, define the name of the medium (e.g. water, air, UHV, etc.). Array of pairs of complex refractive indices n + ik of the medium for every measured spectral point/wavelength/energy. Only necessary if the measurement was performed not in air, or something very well known, e.g. high purity water. A sensor used to monitor an external condition influencing the sample, such as temperature or pressure. It is suggested to replace 'PARAMETER' by the type of the varied parameter defined in 'parameter_type'. The measured parameter values should be provided in 'values'. For each parameter, a 'PARAMETER(NXsensor)' field needs to exist. In other words, there are N_sensors 'PARAMETER(NXsensor)' fields. Indicates which parameter was changed. Its definition must exist below. The specified variable has to be N_measurements long, providing the parameters for each data set. If you vary more than one parameter simultaneously. If the measured parameter is not contained in the list `other` should be specified and the `parameter_type_name` should be provided. If the parameter_type is `other` a name should be specified here. Number of different parameter values at which the measurement was performed. For example, if the measurement was performed at temperatures of 4, 77 and 300 K, then number_of_parameters = 3. Vector containing the values of the varied parameter. Its length is equal to N_measurements. The order of the values should be as follows: * Order the sensors according to number_of_parameters starting with the lowest number. If number_of_parameters is equal for two sensors order them alphabetically (sensor/parameter name). * The first sensor's j parameters should be ordered in the following way. The first N_measurements/number_of_parameters entries of the vector contain the first parameter (a1), the second N_measurements/number_of_parameters contain the second parameter (a2) etc., so the vector looks like: [ a1,a1,...,a1, a2,a2,...,a2, ... aj,aj,...aj ] * The kth sensor's m parameters should be ordered in the following way: [ p1,...p1,p2,...,p2,...pm,...,pm, p1,...p1,p2,...,p2,...pm,...,pm, ... p1,...p1,p2,...,p2,...pm,...,pm ] * The last sensor's n parameters should be ordered in the following way: [ z1,z2,...,zn, z1,z2,...,zn, ... z1,z2,...,zn] For example, if the experiment was performed at three different temperatures (T1, T2, T3), two different pressures (p1, p2) and two different angles of incidence (a1, a2), then N_measurements = 12 and the order of the values for the various parameter vectors is: * angle_of_incidence: [a1,a1,a1,a1,a1,a1,a2,a2,a2,a2,a2,a2] * pressure: [p1,p1,p1,p2,p2,p2,p1,p1,p1,p2,p2,p2] * temperature: [T1,T2,T3,T1,T2,T3,T1,T2,T3,T1,T2,T3] For environmental measurements, the environment (liquid, vapor etc.) is enclosed in a cell, which has windows both in the direction of the source (entry window) and the detector (exit window) (looking from the sample). In case that the entry and exit windows are not the same type and do not have the same properties, use a second 'WINDOW(MXaperture)' field. The windows also add a phase shift to the light altering the measured signal. This shift has to be corrected based on measuring a known sample (reference sample) or the actual sample of interest in the environmental cell. State if a window correction has been performed in 'window_effects_corrected'. Reference data should be considered as a separate experiment, and a link to the NeXus file should be added in reference_data_link in measured_data. The window is considered to be a part of the sample stage but also beam path. Hence, its position within the beam path should be defined by the 'depends_on' field. Specify the position of the window in the beam path by pointing to the preceding element in the sequence of beam path elements. Was a window correction performed? If 'True' describe the window correction procedure in 'window_correction/procedure'. Was a window correction performed? If 'True' describe the window correction procedure in '' Describe when (before or after the main measurement + time stamp in 'date') and how the window effects have been corrected, i.e. either mathematically or by performing a reference measurement. In the latter case, provide the link to to the reference data in 'reference_data_link'. Link to the NeXus file which describes the reference data if a reference measurement for window correction was performed. Ideally, the reference measurement was performed on a reference sample and on the same sample, and using the same conditions as for the actual measurement with and without windows. It should have been conducted as close in time to the actual measurement as possible. The material of the window. If you specified 'other' as material, decsribe here what it is. Thickness of the window. Angle of the window normal (outer) vs. the substrate normal (similar to the angle of incidence). Properties of the sample, such as sample type, layer structure, chemical formula, atom types, its history etc. Information about the sample stage and sample environment should be described in ENTRY/INSTRUMENT/sample_stage. Descriptive name of the sample Specify the type of sample, e.g. thin film, single crystal etc. Qualitative description of the layer structure for the sample, starting with the top layer (i.e. the one on the front surface, on which the light incident), e.g. native oxide/bulk substrate, or Si/native oxide/thermal oxide/polymer/peptide. Chemical formula of the sample. Use the Hill system (explained here: https://en.wikipedia.org/wiki/Chemical_formula#Hill_system) to write the chemical formula. In case the sample consists of several layers, this should be a list of the chemical formulas of the individual layers, where the first entry is the chemical formula of the top layer (the one on the front surface, on which the light incident). The order must be consistent with layer_structure List of comma-separated elements from the periodic table that are contained in the sample. If the sample substance has multiple components, all elements from each component must be included in 'atom_types'. Ideally, a reference to the location or a unique (globally persistent) identifier (e.g.) of e.g. another file which gives as many as possible details of the material, its microstructure, and its thermo-chemo-mechanical processing/preparation history. In the case that such a detailed history of the sample is not available, use this field as a free-text description to specify details of the sample and its preparation. ISO8601 date with time zone (UTC offset) specified. Description of the substrate. Specify the sample orientation. Measured data, data errors, and varied parameters. If reference data were measured they should be considered a separate experiment and a link to its NeXus file should be added in reference_data_link. An identifier to correlate data to the experimental conditions, if several were used in this measurement; typically an index of 0-N. Select which type of data was recorded, for example intensity, reflectivity, transmittance, Psi and Delta etc. It is possible to have multiple selections. The enumeration list depends on the type of experiment and may differ for different application definitions. Spectral values (e.g. wavelength or energy) used for the measurement. An array of 1 or more elements. Length defines N_spectrum. Replace 'SPECTRUM' by the physical quantity that is used, e.g. wavelength. If applicable, change 'unit: NX_ANY' to the appropriate NXDL unit. If the unit of the measured data is not covered by NXDL units state here which unit was used. Resulting data from the measurement, described by 'data_type'. The first dimension is defined by the number of measurements taken, (N_measurements). The instructions on how to order the values contained in the parameter vectors given in the doc string of INSTRUMENT/sample_stage/environment_conditions/PARAMETER/values, define the N_measurements parameter sets. For example, if the experiment was performed at three different temperatures (T1, T2, T3), two different pressures (p1, p2) and two different angles of incidence (a1, a2), the first measurement was taken at the parameters {a1,p1,T1}, the second measurement at {a1,p1,T2} etc. If applicable, change 'unit: NX_ANY' to the appropriate NXDL unit. If the unit of the measured data is not covered by NXDL units state here which unit was used. Specified uncertainties (errors) of the data described by 'data_type' and provided in 'measured_data'. If applicable, change 'unit: NX_ANY' to the appropriate NXDL unit. If the unit of the measured data is not covered by NXDL units state here which unit was used. List of links to the values of the sensors. Add a link for each varied parameter (i.e. for each sensor). Link to the NeXus file which describes the reference data if a reference measurement was performed. Ideally, the reference measurement was performed using the same conditions as the actual measurement and should be as close in time to the actual measurement as possible. Commercial or otherwise defined given name of the program that was used to generate the result file(s) with measured data and/or metadata (in most cases, this is the same as INSTRUMENT/software). If home written, one can provide the actual steps in the NOTE subfield here. Either version with build number, commit hash, or description of a (online) repository where the source code of the program and build instructions can be found so that the program can be configured in such a way that result files can be created ideally in a deterministic manner. Website of the software. A plot of the multi-dimensional data array provided in ENTRY/data/measured_data. Spectrum, i.e. x-axis of the data (e.g. wavelength, energy etc.) Parameters that are derived from the measured data. Light loss due to depolarization as a value in [0-1]. Jones quality factor. Reflectivity. Transmittance. Commercial or otherwise defined given name of the program that was used to generate or calculate the derived parameters. If home written, one can provide the actual steps in the NOTE subfield here. Either version with build number, commit hash, or description of a (online) repository where the source code of the program and build instructions can be found so that the program can be configured in such a way that result files can be created ideally in a deterministic manner. A default view of the data provided in ENTRY/data_collection/measured_data. This should be the part of the data set which provides the most suitable representation of the data. Spectrum, i.e. x-axis of the data (e.g. wavelength, energy etc.) ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXoptical_system_em.nxdl.xml0000644000077000000000000000742114777236751032532 0ustar00rosborn A container for qualifying an electron optical system. Citing the JEOL TEM glossary this is *an effective distance from a specimen to a plane where an observed diffraction pattern is formed*. The factor of enlargement of the apparent size, not physical size, of an object. The defocus aberration constant oftentimes taken as the C_1_0 which is described in more details in NXaberration. Citing the JEOL TEM glosssary this is the value *when a cone shaped, convergent electron beam illuminates a specimen, the semi-angle of the cone is termed convergence angle.* The extent of the observable parts of the specimen given the current magnification and other settings of the instrument. Citing `Globalsino <https://www.globalsino.com/EM/page4586.html>`_ this is *a distance between the specimen and the lower pole piece in SEM system*. Beam current as measured relevant for the illumination of the specimen. Users should specify further details like how the beam current was measured using the beam_current_description field. Specify further details how the beam current was measured or estimated. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXorientation_set.nxdl.xml0000644000077000000000000001766614777236751032234 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. The dimensionality of the reference space/coordinate system. The cardinality of the set, i.e. the number of orientations. Number of parameters for the chosen parameterization. Details about individual orientations of a set of objects. For a more detailed insight into the discussion of parameterizing orientations in materials science see: * https://doi.org/10.1016/j.matchar.2016.04.008 * https://doi.org/10.1088/0965-0393/23/8/083501 * https://doi.org/10.1007/978-3-662-09156-2 group-theory of rotations * https://doi.org/10.1016/C2013-0-11769-2 the classical book of H.-J. Bunge Reference to or definition of a coordinate system with which the definitions are interpretable. A link or reference to the objects whose identifier are referred to in identifier to resolve which row tuple is the orientation of each object by reading orientations. Integer which specifies which orientation (row of array orientation) matches to which object.e first index to be used for distinguishing hexahedra. Identifiers are defined either implicitly or explicitly. For implicit indexing the identifiers are defined on the interval [identifier_offset, identifier_offset+c-1]. For explicit indexing the identifier array has to be defined. The identifier_offset field can for example be used to communicate if the identifiers are expected to start from 1 (referred to as Fortran-/Matlab-) or from 0 (referred to as C-, Python-style index notation) respectively. Integer used to distinguish how a row in orientation describes a specific object with an explicit identifier that can be queried via inspecting the list of available objects in objects. The rational behind having such a more complicated pattern is that not all objects referred when following the link in objects may still exists or are still tracked when the orientation set was characterized. This design enables to also use NXorientation_set in situations where the orientation of objects change as a function in time. Parameterized orientations. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXpeak.nxdl.xml0000644000077000000000000000702514777236751027732 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Number of support points Description of peaks, their functional form or measured support. Human-readable identifier to specify which concept/entity the peak represents/identifies. Is the peak described analytically via a functional form or is it empirically defined via measured/reported intensity/counts as a function of an independent variable. If the functional form is not empirical or gaussian, users should enter other for the peak_model and add relevant details in the NXcollection. In the case of an empirical description of the peak and its shoulders, this array holds the position values for the independent variable. In the case of an empirical description of the peak and its shoulders, this array holds the intensity/count values at each position. In the case of an analytical description (or if peak_model is other) this collection holds parameter of (and eventually) the functional form. For example in the case of Gaussians mu, sigma, cut-off values, and background intensity are relevant parameter. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXpolarizer_opt.nxdl.xml0000644000077000000000000002374414777236751031711 0ustar00rosborn Size of the wavelength array for which the refractive index of the material and/or coating is given. Size of the wavelength array for which the reflectance or transmission of the polarizer is given. An optical polarizer. Information on the properties of polarizer is provided e.g. [here](https://www.rp-photonics.com/polarizers.html). Type of the polarizer (e.g. dichroic, linear, circular etc.) If you selected 'other' in type specify what it is. Angle of the polarizer. Acceptance angle of the polarizer (range). Describe the geometry (shape, dimension etc.) of the device. Specify the dimensions in 'SHAPE/size'. A sketch of the device should be provided in the 'sketch(NXdata)' field to clarify (i) the shape and dimensions of the device, and (ii) the input and outputs (i.e. the direction of the incoming and outcoming (split) beams). Describe the shape (plate, cube, wedged, prism etc.). If you chose 'other' in 'shape' describe what it is. Sketch of thedevice showing its geometry. The paths of the incoming and outgoing beam should be illustrated and labelled (0 for the incoming beam, and 1, 2,..., N_outputs for the outputs). Physical extent of the device. The device might be made up of one or more objects (NX_objects). The meaning and location of the axes used will vary according to the value of the 'shape' variable. 'N_shapepar' defines how many parameters: * For 'cube' the parameters are (width, length). * For 'cylinder' the parameters are (diameter, length). * For 'plate' the parameters are (width, height, length). * For 'prism' the parameters are (width, height, length). * For 'wedged' the parameters are (width, height, shortest length). The wedge angle should be provided in 'SHAPE/wedge_angle'. * For 'other' the parameters may be (A, B, C, ...) with the labels defined in the sketch plotted in 'SHAPE/sketch'. Wedge angle if 'shape' is 'wedged'. Wavelength range for which the polarizer is designed. Enter the minimum and maximum wavelength (lower and upper limit) of the range. Properties of the substrate material of the polarizer. If the device has a coating specify the coating material and its properties in 'coating'. Specify the substrate material of the polarizer. Thickness of the polarizer substrate. Complex index of refraction of the polarizer material. Specify at given spectral values (wavelength, energy, wavenumber etc.). If the device has a coating describe the material and its properties. Some basic information can be found e.g. [here] (https://www.opto-e.com/basics/reflection-transmission-and-coatings). If the back and front side of the polarizer are coated with different materials, you may define two coatings (e.g. COATING1 and COATING2). Specify the coating type (e.g. dielectric, anti-reflection (AR), multilayer coating etc.). Describe the coating material (e.g. MgF2). Thickness of the coating. Complex index of refraction of the coating. Specify at given spectral values (wavelength, energy, wavenumber etc.). Extinction ratio (maximum to minimum transmission). Reflection of the polarizer at given wavelength values. Transmission of the polarizer at given wavelength values. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXprogram.nxdl.xml0000644000077000000000000000433014777236751030455 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Base class to describe a software tool or library. Given name of the program. Program can be a commercial one a script, or a library or a library component. Program version plus build number, or commit hash. Description of an ideally ever persistent resource where the source code of the program or this specific compiled version of the program can be found so that the program yields repeatably exactly the same numerical and categorical results. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXpulser_apm.nxdl.xml0000644000077000000000000001640114777236751031157 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Total number of ions collected. Metadata for laser- and/or voltage-pulsing in atom probe microscopy. How is field evaporation physically triggered. Frequency with which the high voltage or laser pulser fires. Fraction of the pulse_voltage that is applied in addition to the standing_voltage at peak voltage of a pulse. If a standing voltage is applied, this gives nominal pulse fraction (as a function of standing voltage). Otherwise this field should not be present. In laser pulsing mode the values will be zero so the this field is recommended. However, for voltage pulsing mode it is highly recommended that users report the pulsed_voltage. Absolute number of pulses starting from the beginning of the experiment. Direct current voltage between the specimen and the (local electrode) in the case of local electrode atom probe (LEAP) instrument. The standing voltage applied to the sample, relative to system ground. Atom probe microscopes use controlled laser, voltage, or a combination of pulsing strategies to trigger the excitation and eventual field evaporation/emission of an ion during an experiment. Given name/alias. Nominal wavelength of the laser radiation. Nominal power of the laser source while illuminating the specimen. Average energy of the laser at peak of each pulse. Details about specific positions along the focused laser beam which illuminates the (atom probe) specimen. Track time-dependent settings over the course of the measurement how the laser beam in tip space/reconstruction space laser impinges on the sample, i.e. the mean vector is parallel to the laser propagation direction. Track time-dependent settings over the course of the measurement where the laser beam exits the focusing optics. Track time-dependent settings over the course of the measurement where the laser hits the specimen. Affine transformations which describe the geometry how the laser focusing optics/pinhole-attached coordinate system is defined, how it has to be transformed so that it aligns with the specimen coordinate system. A right-handed Cartesian coordinate system, the so-called laser space, should be assumed, whose positive z-axis points into the direction of the propagating laser beam. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXpump.nxdl.xml0000644000077000000000000000365514777236751030000 0ustar00rosborn Device to reduce an atmosphere to a controlled remaining pressure level. Principle type of the pump. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXquadric.nxdl.xml0000644000077000000000000000604214777236751030440 0ustar00rosborn definition of a quadric surface. Ten real values of the matrix that defines the quadric surface in projective space. Ordered Q11, Q12, Q13, Q22, Q23, Q33, P1, P2, P3, R. Takes a units attribute of dimension reciprocal length. R is scalar. P has dimension reciprocal length, and the given units. Q has dimension reciprocal length squared, and units the square of those given. An optional description of the form of the quadric surface: Path to an :ref:`NXtransformations` that defining the axis on which the orientation of the surface depends. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXquadrupole_magnet.nxdl.xml0000644000077000000000000000413314777236751032523 0ustar00rosborn definition for a quadrupole magnet. extended description of the magnet. define position of beamline element relative to production target current set on supply. current read from supply. voltage read from supply. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXreflectron.nxdl.xml0000644000077000000000000000461714777236751031161 0ustar00rosborn Device for reducing flight time differences of ions in ToF experiments. For atom probe the reflectron can be considered an energy_compensation device, which can e.g. be realized technically as via a Poschenrieder lens (see US patent 3863068 or US patents for the reflectron 6740872, or the curved reflectron 8134119 design). Affine transformation(s) which detail where the reflectron is located relative to e.g. the origin of the specimen space reference coordinate system. This group can also be used for specifying how the reflectron is rotated relative to the specimen axis. The purpose of these more detailed instrument descriptions is to support the creation of a digital twin of the instrument for computational science. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXregion.nxdl.xml0000644000077000000000000001710214777236751030272 0ustar00rosborn These symbols will denote how the shape of the parent group's data field, .. math:: (D_0, ..., D_{\mathbf{O}-1}, d_0, ..., d_{\mathbf{R}-1}) could be split into a left set of **O** outer dimensions, :math:`\boldsymbol{D}`, and a right set of **R** region dimensions, :math:`\boldsymbol{d}`, where the data field has rank **O** + **R**. Note **O** :math:`>= 0`. Outer rank Region rank Geometry and logical description of a region of data in a parent group. When used, it could be a child group to, say, :ref:`NXdetector`. This can be used to describe a subset of data used to create downsampled data or to derive some data from that subset. Note, the fields for the rectangular region specifiers follow HDF5’s dataspace hyperslab parameters (see https://portal.hdfgroup.org/display/HDF5/H5S_SELECT_HYPERSLAB). Note when **block** :math:`= 1`, then **stride** :math:`\equiv` **step** in Python slicing. For example, a ROI sum of an area starting at index of [20,50] and shape [220,120] in image data:: detector:NXdetector/ data[60,256,512] region:NXregion/ @region_type = "rectangular" parent = "data" start = [20,50] count = [220,120] statistics:NXdata/ @signal = "sum" sum[60] the ``sum`` dataset contains the summed areas in each frame. Another example, a hyperspectral image downsampled 16-fold in energy:: detector:NXdetector/ data[128,128,4096] region:NXregion/ @region_type = "rectangular" parent = "data" start = [2] count = [20] stride = [32] block = [16] downsampled:NXdata/ @signal = "maximum" @auxiliary_signals = "copy" maximum[128,128,20] copy[128,128,320] the ``copy`` dataset selects 20 16-channel blocks that start 32 channels apart, the ``maximum`` dataset will show maximum values in each 16-channel block in every spectra. This is ``rectangular`` to describe the region as a hyper-rectangle in the index space of its parent group's data field. The name of data field in the parent group or the path of a data field relative to the parent group (so it could be a field in a subgroup of the parent group) The name of an optional mask field in the parent group with rank :math:`\boldsymbol{R}` and dimensions :math:`\boldsymbol{d}`. For example, this could be ``pixel_mask`` of an :ref:`NXdetector`. The starting position for region in detector data field array. This is recommended as it also defines the region rank. If omitted then defined as an array of zeros. The number of blocks or items in the hyperslab selection. If omitted then defined as an array of dimensions that take into account the other hyperslab selection fields to span the parent data field's shape. An optional field to define striding used to downsample data. If omitted then defined as an array of ones. An optional field to define the block size used to copy or downsample data. In the :math:`i`-th dimension, if :math:`\mathbf{block}[i] < \mathbf{stride}[i]` then the downsampling blocks have gaps between them; when ``block`` matches ``stride`` then the blocks are contiguous; otherwise the blocks overlap. If omitted then defined as an array of ones. An optional field to define a divisor for scaling of reduced data. For example, in a downsampled sum, it can reduce the maximum values to fit in the domain of the result data type. In an image that is downsampled by summing 2x2 blocks, using :math:`\mathrm{scale}=4` allows the result to fit in the same integer type dataset as the parent dataset. If omitted then no scaling occurs. An optional group containing data copied/downsampled from parent group’s data. Its dataset name must reflect how the downsampling is done over each block. So it could be a reduction operation such as sum, minimum, maximum, mean, mode, median, etc. If downsampling is merely copying each block then use "copy" as the name. Where more than one downsample dataset is written (specified with ``@signal``) then add ``@auxiliary_signals`` listing the others. In the copy case, the field should have a shape of :math:`(D_0, ..., D_{\mathbf{O}-1}, \mathbf{block}[0] * \mathbf{count}[0], ..., \mathbf{block}[\mathbf{R}-1] * \mathbf{count}[\mathbf{R}-1])`, otherwise the expected shape is :math:`(D_0, ..., D_{\mathbf{O}-1}, \mathbf{count}[0], ..., \mathbf{count}[\mathbf{R}-1])`. The following figure shows how blocks are used in downsampling: .. figure:: region/NXregion-example.png :width: 60% A selection with :math:`\mathbf{start}=2, \mathbf{count}=4, \mathbf{stride}=3, \mathbf{block}=2` from a dataset with shape [13] will result in the ``reduce`` dataset of shape [4] and a ``copy`` dataset of shape [8]. An optional group containing any statistics derived from the region in parent group’s data such as sum, minimum, maximum, mean, mode, median, rms, variance, etc. Where more than one statistical dataset is written (specified with ``@signal``) then add ``@auxiliary_signals`` listing the others. All data fields should have shapes of :math:`\boldsymbol{D}`. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXscanbox_em.nxdl.xml0000644000077000000000000000437414777236751031134 0ustar00rosborn Scan box and coils which deflect an electron beam in a controlled manner. In electron microscopy, the scan box is instructed by the microscope control software. This component directs the probe to controlled locations according to a scan scheme and plan. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXsensor_scan.nxdl.xml0000644000077000000000000002273414777236751031333 0ustar00rosborn Variables used to set a common size for collected sensor data. The number of scan points measured in this scan. Application definition for a generic scan using sensors. In this application definition, times should be specified always together with an UTC offset. Define the program that was used to generate the results file(s) with measured data and metadata. Commercial or otherwise defined given name of the program (or a link to the instrument software). Either version with build number, commit hash, or description of an (online) repository where the source code of the program and build instructions can be found so that the program can be configured in such a way that result files can be created ideally in a deterministic manner. Website of the software. Contact information of at least the user of the instrument or the investigator who performed this experiment. Adding multiple users if relevant is recommended. Name of the user. Name of the affiliation of the user at the point in time when the experiment was performed. Full address (street, street number, ZIP, city, country) of the user's affiliation. Email address of the user. Author ID defined by https://orcid.org/. Official telephone number of the user. Describes an environment setup for the experiment. All the setting values of the independently scanned controllers are listed under corresponding NXsensor groups. Similarly, seperate NXsensor groups are used to store the readings from each measurement sensor. For example, in a temperature-dependent IV measurement, the temperature and voltage must be present as independently scanned controllers and the current sensor must also be present with its readings. Plot of measured signal as a function of the timestamp of when they have been acquired is also possible. For each point in the scan space, either the nominal setpoint of an independently scanned controller or a representative average value of a measurement sensor is registered. The length of each sensor's data value array stored in this group should be equal to the number of scan points probed in this scan. For every scan point [N], the corresponding sensor value can be picked from index [N]. This allows the scan to be made in any order as the user describes above in the experiment. We get matching values simply using the index of the scan point. Timestamp for when the values provided in the value field were registered. Individual readings can be stored with their timestamps under value_log. This is to timestamp the nominal setpoint or average reading values listed above in the value field. Free-text describing the data acquisition control: an internal sweep using the built-in functionality of the controller device, or a set/wait/read/repeat mechanism. ISO8601 datum when calibration was last performed before this measurement. UTC offset should be specified. A list of names of NXsensor groups used as independently scanned controllers. A list of names of NXsensor groups used as measurement sensors. A scan specific representation of the measured signals as a function of the independently controlled environment settings. Plot of every measured signal as a function of the timestamp of when they have been acquired is also possible. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXseparator.nxdl.xml0000644000077000000000000000524114777236751031010 0ustar00rosborn definition for an electrostatic separator. extended description of the separator. define position of beamline element relative to production target current set on magnet supply. current read from magnet supply. voltage read from magnet supply. current set on HT supply. current read from HT supply. voltage read from HT supply. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXsimilarity_grouping.nxdl.xml0000644000077000000000000001615014777236751033111 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Cardinality of the set. Number of numerical labels per object. Number of categorical labels per object. Total number of similarity groups aka features, objects, clusters. Metadata to the results of a similarity grouping analysis. Similarity grouping analyses can be supervised segmentation or machine learning clustering algorithms. These are routine methods which partition the member of a set of objects/geometric primitives into (sub-)groups, features of different type. A plethora of algorithms have been proposed which can be applied also on geometric primitives like points, triangles, or (abstract) features aka objects (including categorical sub-groups). This base class considers metadata and results of one similarity grouping analysis applied to a set in which objects are either categorized as noise or belonging to a cluster. As the results of the analysis each similarity group, here called feature aka object can get a number of numerical and/or categorical labels. Number of members in the set which is partitioned into features. How many numerical labels does each feature have. How many categorical labels does each feature have. Which identifier is the first to be used to label a cluster. The value should be chosen in such a way that special values can be resolved: * identifier_offset-1 indicates an object belongs to no cluster. * identifier_offset-2 indicates an object belongs to the noise category. Setting for instance identifier_offset to 1 recovers the commonly used case that objects of the noise category get values to -1 and unassigned points to 0. Numerical identifier have to be strictly increasing. Matrix of numerical label for each member in the set. For classical clustering algorithms this can for instance encode the cluster_identifier. Matrix of categorical attribute data for each member in the set. In addition to the detailed storage which members was grouped to which feature/group summary statistics are stored under this group. Total number of members in the set which are categorized as unassigned. Total number of members in the set which are categorized as noise. Total number of clusters (excluding noise and unassigned). Array of numerical identifier of each feature (cluster). Array of number of members for each feature. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXslip_system_set.nxdl.xml0000644000077000000000000000646214777236751032244 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Number of slip systems. Base class for describing a set of crystallographic slip systems. Array of Miller indices which describe the crystallographic plane. Array of Miller indices which describe the crystallographic direction. For each slip system a marker whether the specified Miller indices refer to the specific slip system or the set of crystallographic equivalent slip systems of the respective family of slip systems. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXsnsevent.nxdl.xml0000644000077000000000000003235114777236751030657 0ustar00rosborn This is a definition for event data from Spallation Neutron Source (SNS) at ORNL. Details of all logs, both from cvinfo file and from HistoTool (frequency and proton_charge). Motor logs from cvinfo file. Command string for event2nxl. Official NXDL schema after this file goes to applications. Detector calibration id from DAS. expect ``signal=2 axes="x_pixel_offset,y_pixel_offset``" Six out of nine rotation parameters. Six out of nine rotation parameters. Six out of nine rotation parameters. expect ``signal=1 axes="time_of_flight"`` Descriptive name of sample ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXsnshisto.nxdl.xml0000644000077000000000000003406014777236751030663 0ustar00rosborn This is a definition for histogram data from Spallation Neutron Source (SNS) at ORNL. Details of all logs, both from cvinfo file and from HistoTool (frequency and proton_charge). Motor logs from cvinfo file. Command string for event2histo_nxl. Official NXDL schema after this file goes to applications. Detector calibration id from DAS. Six out of nine rotation parameters. Original specification called for NXchopper, which is not a valid NeXus base class. Select either NXdisk_chopper or NXfermi_chopper, as appropriate. Original specification called for NXchopper, which is not a valid NeXus base class. Select either NXdisk_chopper or NXfermi_chopper, as appropriate. Six out of nine rotation parameters. Six out of nine rotation parameters. Descriptive name of sample ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXsolenoid_magnet.nxdl.xml0000644000077000000000000000412514777236751032157 0ustar00rosborn definition for a solenoid magnet. extended description of the magnet. define position of beamline element relative to production target current set on supply. current read from supply. voltage read from supply. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXsolid_geometry.nxdl.xml0000644000077000000000000000354114777236751032036 0ustar00rosborn the head node for constructively defined geometry Instances of :ref:`NXquadric` making up elements of the geometry. Instances of :ref:`NXoff_geometry` making up elements of the geometry. The geometries defined, made up of instances of :ref:`NXquadric` and :ref:`NXoff_geometry`. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXspatial_filter.nxdl.xml0000644000077000000000000000737714777236751032026 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Number of ellipsoids. Number of hexahedra. Number of cylinders. Spatial filter to filter entries within a region-of-interest based on their position. Qualitative statement which specifies which spatial filtering with respective geometric primitives or bitmask is used. These settings are possible: * entire_dataset, no filter is applied, the entire dataset is used. * union_of_primitives, a filter with (rotated) geometric primitives. All ions in or on the surface of the primitives are considered while all other ions are ignored. * bitmasked_points, a boolean array whose bits encode with 1 which ions should be included. Those ions whose bit is set to 0 will be excluded. Users of python can use the bitfield operations of the numpy package to define such bitfields. Conditions: In the case that windowing_method is entire_dataset all entries are processed. In the case that windowing_method is union_of_primitives, it is possible to specify none or all types of primitives (ellipsoids, cylinder, hexahedra). If no primitives are specified the filter falls back to entire_dataset. In the case that windowing_method is bitmask, the bitmask has to be defined; otherwise the filter falls back to entire dataset. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXspectrum_set.nxdl.xml0000644000077000000000000001373414777236751031533 0ustar00rosborn Number of pixel in the slow direction. Number of pixel in the fast direction. Number of energy bins. Container for reporting a set of spectra. Details how spectra were processed from the detector readings. Resolvable data artifact (e.g. filename) from which the all values in the NXdata instances in this NXspectrum_set were loaded during parsing. An at least as strong as SHA256 hashvalue of the data artifact which source represents digitally to support provenance tracking. Imaging (data collection) mode of the instrument during acquisition of the data in this NXspectrum_set instance. Link or name of an NXdetector instance with which the data were collected. Collected spectra for all pixels of a rectangular region-of-interest. This representation supports rectangular scan pattern. Counts Coordinate along y direction Coordinate along x direction Energy Accumulated counts over all pixels of the region-of-interest. This representation supports rectangular scan pattern. Counts Energy ././@PaxHeader0000000000000000000000000000022600000000000010215 xustar00111 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXspectrum_set_em_eels.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXspectrum_set_em_eels.nxdl.xm0000644000077000000000000001651114777236751033044 0ustar00rosborn Number of pixel per EELS mapping in the slow direction. Number of pixel per EELS mapping in the fast direction. Number of electron energy loss bins. Container for reporting a set of electron energy loss (EELS) spectra. Virtually the most important case is that spectra are collected in a scanning microscope (SEM or STEM) for a collection of points. The majority of cases use simple d-dimensional regular scan pattern, such as single point, line profiles, or (rectangular) surface mappings. The latter pattern is the most frequently used. For now the base class provides for scans for which the settings, binning, and energy resolution is the same for each scan point. Details how EELS spectra were processed from the detector readings. Typically the name of the input, (vendor) file from which all the NXdata instances in this NXspectrum_set_em_eels were loaded during parsing to represent them in e.g. databases. An at least as strong as SHA256 hashvalue of the dataset/file which represents the source digitally to support provenance tracking. Commercial or otherwise given name to the program which was used to process detector data into the EELS spectra stack and summary. Program version plus build number, commit hash, or description of an ever persistent resource where the source code of the program and build instructions can be found so that the program can be configured in such a manner that the result file is ideally recreatable yielding the same results. Collected EELS spectra for all pixels of a rectangular region-of-interest. This representation supports rectangular scan pattern. Counts for one spectrum per each pixel. EELS counts Pixel center of mass position y-coordinates. Coordinate along y direction. Pixel center of mass position x-coordinates. Coordinate along x direction. Pixel center of mass energy loss bins. Coordinate along energy loss axis. Accumulated EELS spectrum over all pixels of a rectangular region-of-interest. This representation supports rectangular scan pattern. Counts for specific energy losses. Counts electrons with an energy loss within binned range. Pixel center of mass energy loss bins. Coordinate along energy loss axis. ././@PaxHeader0000000000000000000000000000022600000000000010215 xustar00111 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXspectrum_set_em_xray.nxdl.xml 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXspectrum_set_em_xray.nxdl.xm0000644000077000000000000003131214777236751033073 0ustar00rosborn Number of pixel per X-ray mapping in the slow direction Number of pixel per X-ray mapping in the fast direction Number of X-ray photon energy (bins) Number of identified elements Number of peaks Container for reporting a set of energy-dispersive X-ray spectra. Virtually the most important case is that spectra are collected in a scanning microscope (SEM or STEM) for a collection of points. The majority of cases use simple d-dimensional regular scan pattern, such as single point, line profiles, or (rectangular) surface mappings. The latter pattern is the most frequently used. For now the base class provides for scans for which the settings, binning, and energy resolution is the same for each scan point. `IUPAC instead of Siegbahn notation <https://doi.org/10.1002/xrs.1300200308>`_ should be used. Details how X-ray spectra were processed from the detector readings. Typically the name of the input, (vendor) file from which all the NXdata instances in this NXspectrum_set_em_xray were loaded during parsing to represent them in e.g. databases. An at least as strong as SHA256 hashvalue of the dataset/file which represents the source digitally to support provenance tracking. Commercial or otherwise given name to the program which was used to process detector data into the X-ray spectra stack and summary. Program version plus build number, commit hash, or description of an ever persistent resource where the source code of the program and build instructions can be found so that the program can be configured in such a manner that the result file is ideally recreatable yielding the same results. Collected X-ray spectra for all pixels of a rectangular region-of-interest. This representation supports rectangular scan pattern. X-ray photon counts Coordinate along y direction. Coordinate along x direction. Photon energy. Accumulated X-ray spectrum over all pixels of a rectangular region-of-interest. This representation supports rectangular scan pattern. X-ray photon counts Photon energy Details about computational steps how peaks were indexed as elements. Given name of the program that was used to perform this computation. Program version plus build number, commit hash, or description of an ever persistent resource where the source code of the program and build instructions can be found so that the program can be configured in such a manner that the result file is ideally recreatable yielding the same results. Name and location of each X-ray line which was indexed as a known ion. For each ion an NXion instance should be created which specifies the origin of the signal. For each ion also the relevant IUPAC notation X-ray lines should be specified. IUPAC notation identifier of the line which the peak represents. This can be a list of IUPAC notations for (the seldom) case that multiple lines are group with the same peak. List of the names of identified elements. Individual element-specific EDX/EDS/EDXS/SXES mapping A composition map is an image whose intensities for each pixel are the accumulated X-ray quanta *under the curve(s)* of a set of peaks. Given name of the program that was used to perform this computation. Program version plus build number, commit hash, or description of an ever persistent resource where the source code of the program and build instructions can be found so that the program can be configured in such a manner that the result file is ideally recreatable yielding the same results. A list of strings of named instances of NXpeak from indexing whose X-ray quanta where accumulated for each pixel. Human-readable, given name to the image. Individual element-specific maps. Individual maps should each be a group and be named according to element_names. Accumulated photon counts for observed element. Coordinate along y direction. Coordinate along x direction. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXspin_rotator.nxdl.xml0000644000077000000000000000523314777236751031534 0ustar00rosborn definition for a spin rotator. extended description of the spin rotator. define position of beamline element relative to production target current set on magnet supply. current read from magnet supply. voltage read from magnet supply. current set on HT supply. current read from HT supply. voltage read from HT supply. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXspindispersion.nxdl.xml0000644000077000000000000000560314777236751032063 0ustar00rosborn Subclass of NXelectronanalyser to describe the spin filters in photoemission experiments. Type of spin detector, VLEED, SPLEED, Mott, etc. Figure of merit of the spin detector Effective Shermann function, calibrated spin selectivity factor Energy of the spin-selective scattering Angle of the spin-selective scattering Name of the target Preparation procedure of the spin target Date of last preparation of the spin target Deflectors in the spin dispersive section Individual lenses in the spin dispersive section ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXstage_lab.nxdl.xml0000644000077000000000000002022414777236751030727 0ustar00rosborn A stage lab can be used to hold, align, orient, and prepare a specimen. Modern stages are multi-functional devices. Many of which offer a controlled environment around (a part) of the specimen. Stages enable experimentalists to apply stimuli. A stage_lab is a multi-purpose/-functional tools which can have multiple actuators, sensors, and other components. With such stages comes the need for storing various (meta)data that are generated while manipulating the sample. Modern stages realize a hierarchy of components: For example the specimen might be mounted on a multi-axial tilt rotation holder. This holder is fixed in the support unit which connects the holder to the rest of the microscope. In other examples, taken from atom probe microscopy, researchers may work with wire samples which are clipped into a larger fixing unit for convenience and enable for a more careful specimen handling. This fixture unit is known in atom probe jargon as a stub. Stubs in turn are positioned onto pucks. Pucks are then loaded onto carousels. A carousel is a carrier unit with which eventually entire sets of specimens can be moved in between parts of the microscope. An NXstage_lab instance reflects this hierarchical design. The stage is the root of the hierarchy. A stage carries the holder. In the case that it is not practical to distinguish these two layers, the holder should be given preference. Some examples for stage_labs in applications: * A nanoparticle on a copper grid. The copper grid is the holder. The grid itself is fixed to the stage. * An atom probe specimen fixed in a stub. In this case the stub can be considered the holder, while the cryostat temperature control unit is a component of the stage. * Samples with arrays of specimens, like a microtip on a microtip array is an example of a three-layer hierarchy commonly employed for efficient sequential processing of atom probe experiments. * With one entry of an application definition only one microtip should be described. Therefore, the microtip is the specimen, the array is the holder and the remaining mounting unit that is attached to the cryo-controller is the stage. * For in-situ experiments with e.g. chips with read-out electronics as actuators, the chips are again placed in a larger unit. * Other examples are (quasi) in-situ experiments where experimentalists anneal or deform the specimen via e.g. in-situ tensile testing machines which are mounted on the specimen holder. To cover for an as flexible design of complex stages, users should nest multiple instances of NXstage_lab objects according to their needs to reflect the differences between what they consider as the holder and what they consider is the stage. Instances should be named with integers starting from 1 as the top level unit. In the microtip example stage_lab_1 for the stage, stage_lab_2 for the holder (microtip array), stage_lab_3 for the microtip specimen, respectively. The depends_on keyword should be used with relative or absolute naming inside the file to specify how different stage_lab instances build a hierarchy if this is not obvious from numbered identifiers like the stage_lab_1 to stage_lab 3 example. The lower it is the number the higher it is the rank in the hierarchy. For specific details and inspiration about stages in electron microscopes: * `Holders with multiple axes <https://www.nanotechnik.com/e5as.html>`_ * `Chip-based designs <https://www.protochips.com/products/fusion/fusion-select-components/>`_ * `Further chip-based designs <https://www.nanoprobetech.com/about>`_ * `Stages in transmission electron microscopy <https://doi.org/10.1007/978-3-662-14824-2>`_ (page 103, table 4.2) * `Further stages in transmission electron microscopy <https://doi.org/10.1007/978-1-4757-2519-3>`_ (page 124ff) * `Specimens in atom probe <https://doi.org/10.1007/978-1-4614-8721-0>`_ (page 47ff) * `Exemplar micro-manipulators <https://nano.oxinst.com/products/omniprobe/omniprobe-200>`_ Principal design of the stage. Exemplar terms could be side_entry, top_entry, single_tilt, quick_change, multiple_specimen, bulk_specimen, double_tilt, tilt_rotate, heating_chip, atmosphere_chip, electrical_biasing_chip, liquid_cell_chip Should be defined by the application definition. Should be defined by the application definition. Should be defined by the application definition. Should be defined by the application definition. Voltage applied to the stage to decelerate electrons. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXsubsampling_filter.nxdl.xml0000644000077000000000000000426114777236751032702 0ustar00rosborn The symbols used in the schema to specify e.g. dimensions of arrays. Settings of a filter to sample entries based on their value. Triplet of the minimum, increment, and maximum value which will be included in the analysis. The increment controls which n-th entry to take. Take as an example a dataset with 100 entries (their indices start at zero) and the filter set to 0, 1, 99. This will process each entry. 0, 2, 99 will take each second entry. 90, 3, 99 will take only each third entry beginning from entry 90 up to 99. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXsubstance.nxdl.xml0000644000077000000000000001357514777236751031010 0ustar00rosborn A form of matter with a constant, definite chemical composition. Examples can be single chemical elements, chemical compunds, or alloys. For further information, see https://en.wikipedia.org/wiki/Chemical_substance. User-defined chemical name of the substance Molecular mass of the substance The chemical formula specified using CIF conventions. Abbreviated version of CIF standard:107 This is the *Hill* system used by Chemical Abstracts. * Only recognized element symbols may be used. * Each element symbol is followed by a 'count' number. A count of '1' may be omitted. * A space or parenthesis must separate each cluster of (element symbol + count). * Where a group of elements is enclosed in parentheses, the multiplier for the group must follow the closing parentheses. That is, all element and group multipliers are assumed to be printed as subscripted numbers. * Unless the elements are ordered in a manner that corresponds to their chemical structure, the order of the elements within any group or moiety depends on whether or not carbon is present. * If carbon is present, the order should be: - C, then H, then the other elements in alphabetical order of their symbol. - If carbon is not present, the elements are listed purely in alphabetic order of their symbol. Unique CAS REGISTRY URI. For further information, see https://www.cas.org/. Numeric CAS REGISTRY number associated with this identifier. CAS REGISTRY name associated with this identifier. CAS REGISTRY image Standard string InChi identifier" (as per v1.02). The InChI identifier expresses chemical structures in terms of atomic connectivity, tautomeric state, isotopes, stereochemistry and electronic charge in order to produce a string of machine-readable characters unique to the respective molecule. For further information, see https://iupac.org/who-we-are/divisions/division-details/inchi/. Condensed, 27 character InChI key. Hashed version of the full InChI (using the SHA-256 algorithm). Name according to the IUPAC system (standard). For further information, see https://iupac.org/. Identifier in the SMILES (Simplified Molecular Input Line Entry System) system For further information, see https://www.daylight.com/smiles/. Canonical version of the SMILES identifier Standard PubChem identifier (CID). The PubChem Compound Identifier (CID) is a unique numerical identifier assigned to a compound in the PubChem database, which contains information on the biological activities of small molecules. The CID allows users to access detailed data about compounds, including their chemical structure, molecular formula, and biological properties. For further information, see https://pubchem.ncbi.nlm.nih.gov/. CAS REGISTRY name associated with this identifier. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXtransmission.nxdl.xml0000644000077000000000000003542614777236751031551 0ustar00rosborn Variables used throughout the experiment Number of wavelength points Number of scans Application definition for transmission experiments This application definition An application definition for transmission. Version number to identify which definition of this application definition was used for this entry/data. URL where to find further material (documentation, examples) relevant to the application definition. Start time of the experiment. Unique identifier of the experiment, such as a (globally persistent) unique identifier. * The identifier is usually defined by the facility or principle investigator. * The identifier enables to link experiments to e.g. proposals. An optional free-text description of the experiment. However, details of the experiment should be defined in the specific fields of this application definition rather than in this experiment description. Commercial or otherwise defined given name to the program that was used to generate the result file(s) with measured data and metadata. Version number of the program that was used to generate the result file(s) with measured data and metadata. Website of the software Contact information of at least the user of the instrument or the investigator who performed this experiment. Adding multiple users if relevant is recommended. Name of the user. Name of the affiliation of the user at the point in time when the experiment was performed. Street address of the user's affiliation. Email address of the user. Author ID defined by reasearch id services, e.g. orcid (https://orcid.org/). Telephone number of the user. Manufacturer of the instrument. Common beam mask to shape the incident beam The height of the common beam in percentage of the beam If true, the incident beam is depolarized. Polarizer value inside the beam path Attenuator in the reference beam Attenuator in the sample beam Wavelength value(s) used for the measurement. An array of 1 or more elements. Length defines N_wavelenghts Overall spectral resolution of this spectrometer. If several gratings are employed the spectral resoultion should rather be specified for each grating inside the NXgrating group of this spectrometer. Diffraction grating, as could be used in a monochromator. If two or more gratings were used, define the angular dispersion and the wavelength range (min/max wavelength) for each grating and make sure that the wavelength ranges do not overlap. The dispersion should be defined for the entire wavelength range of the experiment. Dispersion of the grating in nm/mm used. The blaze wavelength of the grating used. Overall spectral resolution of the instrument when this grating is used. Wavelength range in which this grating was used Wavelength range in which this detector was used Detector type Response time of the detector Detector gain Slit setting used for measurement with this detector An array of relative scan start time points. Resulting data from the measurement. The length of the 2nd dimension is the number of time points. If it has length one the time_points may be empty. The lamp used for illumination The type of lamp, e.g. halogen, D2 etc. The spectrum of the lamp used Wavelength range in which the lamp was used Properties of the sample measured A default view of the data emitted intensity vs. wavelength. From measured_data plot intensity and wavelength. We recommend to use wavelength as a default attribute, but it can be replaced by any suitable parameter along the X-axis. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXwaveplate.nxdl.xml0000644000077000000000000001572514777236751031010 0ustar00rosborn Size of the wavelength array for which the refractive index of the material and/or coating is given. Number of discrete wavelengths for which the waveplate is designed. If it operates for a range of wavelengths then N_wavelengths = 2 and the minimum and maximum values of the range should be provided. A waveplate or retarder. Type of waveplate (e.g. achromatic waveplate or zero-order waveplate). If you selected 'other' in type describe what it is. Specify the retardance of the waveplate (e.g. full-wave, half-wave (lambda/2), quarter-wave (lambda/4) plate). Discrete wavelengths for which the waveplate is designed. If the waveplate operates over an entire range of wavelengths, enter the minimum and maximum values of the wavelength range (in this case N_wavelengths = 2). Diameter of the waveplate. Clear aperture of the device (e.g. 90% of diameter for a disc or 90% of length/height for square geometry). Describe the material of the substrate of the wave plate in substrate/substrate_material and provide its index of refraction in substrate/index_of_refraction_substrate, if known. Specify the material of the wave plate. If the device has a coating it should be described in coating/coating_material. Thickness of the wave plate substrate. Complex index of refraction of the wave plate substrate. Specify at given wavelength (or energy, wavenumber etc.) values. Is the wave plate coated? If yes, specify the type and material of the coating and the wavelength range for which it is designed. If known, you may also provide its index of refraction. Specify the coating type (e.g. dielectric, anti-reflection (AR), multilayer coating etc.). Specify the coating material. Thickness of the coating. Wavelength range for which the coating is designed. Enter the minimum and maximum values of the wavelength range. Complex index of refraction of the coating. Specify at given spectral values (wavelength, energy, wavenumber etc.). Average reflectance of the waveplate in percentage. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/NXxpcs.nxdl.xml0000644000077000000000000006561214777236751027775 0ustar00rosborn The symbol(s) listed here will be used below to coordinate datasets with the same shape. Number of points X-ray Photon Correlation Spectroscopy (XPCS) data (results). The purpose of ``NXxpcs`` is to document and communicate an accepted vernacular for various XPCS results data in order to support development of community software tools. The definition presented here only represents a starting point and contains fields that a common software tool should support for community acceptance. Additional fields may be added to XPCS results file (either formally or informally). It is expected that this XPCS data will be part of multi-modal data set that could involve e.g., :ref:`NXcanSAS` or 1D and/or 2D data. Official NeXus NXDL schema to which this file conforms **Locally** unique identifier for the experiment (a.k.a. run or scan). * For bluesky users, this is the run's `"scan_id"`. * For SPEC users, this is the scan number (``SCAN_N``). (optional) UUID identifier for this entry. See the `UUID standard <https://www.rfc-editor.org/rfc/rfc4122.html>`__ (or `wikipedia <https://en.wikipedia.org/wiki/Universally_unique_identifier>`__) for more information. * For `bluesky <https://blueskyproject.io/>`__ users, this is the run's `"uid"` and is expected for that application. * Typically, `SPEC <https://certif.com/content/spec/>`__ users will not use this field without further engineering. Scan number (must be an integer). NOTE: Link to collection_identifier. Starting time of experiment, such as "2021-02-11 11:22:33.445566Z". Ending time of experiment, such as "2021-02-11 11:23:45Z". The results data captured here are most commonly required for high throughput, equilibrium dynamics experiments. Data (results) describing on-equilibrium dynamics consume more memory resources so these data are separated. Two-dimensional summation along the frames stack. sum of intensity v. time (in the units of "frames") Two-dimensional average along the frames stack. average intensity v. time (in the units of "frames") normalized intensity auto-correlation function, see Lumma, Rev. Sci. Instr. (2000), Eq 1 .. math:: g_2(\boldsymbol Q,t) = \frac{ \langle I(\boldsymbol Q,t\prime) I(\boldsymbol Q,t\prime + t) \rangle }{ \langle I(\boldsymbol Q,t\prime)\rangle^2 }; t > 0 Typically, :math:`g_2` is a quantity calculated for a group of pixels representing a specific region of reciprocal space. These groupings, or bins, are generically described as :math:`q`. Some open-source XPCS libraries refer to these bins as "rois", which are not to be confused with EPICS AreaDetector ROI. See usage guidelines for q_lists and roi_maps within a mask. [#]_ In short, :math:`g_2` should be ordered according to the roi_map value. In principle, any format is acceptable if the data and its axes are self-describing as per NeXus recommendations. However, the data is preferred in one of the following two formats: * iterable list of linked files (or keys) for each :math:`g_2` with 1 file (key) per :math:`q`, where `q` is called by the nth roi_map value * 2D array [#]_ with shape (:math:`g_2`, :math:`q`), where `q` is represented by the nth roi_map value, not the value `q` value Note it is expected that "g2" and all quantities following it will be of the same length. Other formats are acceptable with sufficient axes description. See references below for related implementation information: .. [#] mask: ``NXxpcs:/entry/instrument/masks-group`` .. [#] NeXus 2-D data and axes: https://manual.nexusformat.org/classes/base_classes/NXdata.html#nxdata storage_mode describes the format of the data to be loaded We encourage the documentation of other formats not represented here. * one array representing entire data set ("one_array") * data exchange format with each key representing one ``q`` by its corresponding roi_map value ("data_exchange_keys") error values for the :math:`g_2` values. The derivation of the error is left up to the implemented code. Symmetric error will be expected (:math:`\pm` error). The data should be in the same format as ``g2``. unnormalized intensity auto-correlation function. Specifically, ``g2`` without the denominator. The data should be in the same format as ``g2``. delay_difference (also known as delay or lag step) This is quantized difference so that the "step" between two consecutive frames is one frame (or step ``= dt = 1 frame``) It is the "quantized" delay time corresponding to the ``g2`` values. The unit of delay_differences is ``NX_INT`` for units of frames (i.e., integers) preferred, refer to :ref:`NXdetector` for conversion to time units. The data (results) in this section are based on the two-time intensity correlation function derived from a time series of scattering images. two-time correlation of speckle intensity for a given q-bin or roi (represented by the nth roi_map value) See Fluerasu, Phys Rev E (2007), Eq 1 and Sutton, Optics Express (2003) for an early description applied to X-ray scattering: .. math:: C(\boldsymbol Q, t_1, t_2) = \frac{ \langle I(\boldsymbol Q, t_1)I(\boldsymbol Q, t_2)\rangle }{ \langle I(\boldsymbol Q,t_1)\rangle \langle I(\boldsymbol Q,t_2)\rangle } in which time is quantized by frames. In principle, any data format is acceptable if the data and its axes are self-describing as per NeXus recommendations. However, the data is preferred in one of the following two formats: * iterable list of linked files (or keys) for each q-bin called by the nth roi_map value. data for each bin is a 2D array * 3D array with shape (frames, frames, q) or (q, frames, frames), where :math:`q` is represented by the nth roi_map value, not the value `q` value The computation of this result can be customized. These customizations can affect subsequently derived results (below). The following attributes will be used to manage the customization. * Other normalization methods may be applied, but the method will not be specified in this definition. Some of these normalization methods result in a baseline value of ``0``, not ``1``. * The various software libraries use different programming languages. Therefore, we need to specify the ``time = 0`` origin location of the 2D array for each :math:`q`. * A method to reduce data storage needs is to only record half of the 2D array by populating array elements above or below the array diagonal. storage_mode describes the format of the data to be loaded We encourage the documention of other formats represented here. baseline is the expected value of a full decorrelation The baseline is a constant value added to the functional form of the auto-correlation function. This value is required. time_origin_location is the location of the origin populated_elements describe the elements of the 2D array that are populated with data frame weighted average along the diagonal direction in ``two_time_corr_func`` The data format and description should be consistent with that found in "/NXxpcs/entry/data/g2" * iterable list of linked files for each :math:`g_2` with 1 file per :math:`q` * 2D array with shape (:math:`g_2`, :math:`q`) Note that delay_difference is not included here because it is derived from the shape of extracted :math:`g_2` because all frames are considered, which is not necessarily the case for :math:`g_2`. The computation of this result can be customized. The customization can affect the fitting required to extract quantitative results. The following attributes will be used to manage the customization. first_point_for_fit describes if the first point should or should not be used in fitting the functional form of the dynamics to extract quantitative time-scale information. The first_point_for_fit is True ("1") or False ("0"). This value is required. error values for the :math:`g_2` values. The derivation of the error is left up to the implemented code. Symmetric error will be expected (:math:`\pm` error). subset of frame weighted average along the diagonal direction in ``two_time_corr_func`` Time slicing along the diagonal can be very sophisticated. This entry currently assumes equal frame-binning. The data formats are highly dependent on the implantation of various analysis libraries. In principle, any data format is acceptable if the data and its axes are self describing as per NeXus recommendations. However, the data is preferred in one of the following two formats: * iterable list of linked files (or keys) for each partial :math:`g_2` of each q-bin represented by the roi_map value * 3D array with shape (:math:`g_2`, :math:`q`, nth_partial) Note that delay_difference is not included here because it is derived from the shape of extracted :math:`g_2`. error values for the :math:`g_2` values. The derivation of the error is left up to the implemented code. Symmetric error will be expected (:math:`\pm` error). XPCS instrument Metadata. Objects can be entered here directly or linked from other objects in the NeXus file (such as within ``/entry/instrument``). Incident beam line energy (either keV or eV). Spread of incident beam line energy (either keV or eV). This quantity is otherwise known as the energy resolution, which is related to the longitudinal coherence length. Terse description of the incident beam polarization. The value can be plain text, such as ``vertical``, ``C+``, ``circular left``. Size (2-D) of the beam at this position. XPCS data is typically produced by area detector (likely EPICS AreaDetector) as a stack of 2D images. Sometimes this data is represented in different ways (sparse arrays or photon event list), but this detail is left to the analysis software. Therefore, we only include requirements based on full array data. We note that the image origin (pixel coordinates (0,0)) are found at the top left of a single 2D image array. This is the standard expected by Coherent X-ray Imaging Data Bank. [#]_ See CXI version 1.6 and Maia, Nature Methods (2012). This seems to be consistent with matplotlib and the practiced implementation of EPICS AreaDetector. However, some exceptions may exists in the CXI documentation (See Fig 11 vs Fig 12). Additionally, not all :ref:`NXdetector` dependencies are inherited from AreaDetector or other control systems. ``frame_time`` is used to convert ``delay_difference`` to seconds. ``frame_time`` field could be missing from AreaDetector or may either be `acquire_period` or `acquire_time`, depending on the detector model and the local implementation. .. [#] Coherent X-ray Imaging Data Bank: https://cxidb.org/cxi.html Detector name. Distance between sample and detector. Exposure time of frames, s. Exposure period (time between frame starts) of frames, s Position of beam center, x axis, in detector's coordinates. Position of beam center, y axis, in detector's coordinates. Length of pixel in x direction. Length of pixel in y direction. Data masks or mappings to regions of interest (roi) for specific :math:`Q` values Fields in this ``masks`` group describe regions of interest in the data by either a mask to select pixels or to associate a *map* of rois with a (one-dimensional) *list* of values. "roi_maps" provide for representation of pixel binning that are arbitrary and irregular, which is geometry scattering agnostic and most flexible. The maps work as a labeled array for N rois. "Dynamic" represents quantities directly related to XPCS and NXxcps/entry/data and NXxpcs/entry/two_time. "Static" refers to finer binning used for computation not strictly used for the final XPCS results. Implementation of _static_ binning is left for individual libraries to document. We encourage usage of :ref:`NXcanSAS` to represent standard SAXS results or development of new NeXus definitions for GI-SAXS or other reciprocal space intensity mapping. roi index array or labeled array The values of this mask index (or map to) the :math:`Q` value from the the ``dynamic_q_list`` field. Not that the value of ``0`` represents in-action. XPCS computations are performed on all pixels with a value > 0. The ``units`` attribute should be set to ``"au"`` indicating arbitrary units. 1-D list of :math:`Q` values, one for each roi index value. List order is determined by the index value of the associated roi map starting at ``1``. The only requirement for the list is that it may be iterable. Some expected formats are: * iterable list of floats (i.e., :math:`Q(r)`) * iterable list of tuples (i.e., :math:`Q(r)`, :math:`\varphi`), but preferable use the seperate :math:`\varphi` field below * iterable list of tuples (e.g., (H, K, L); (qx, qy, qz); (horizontal_pixel, vertical_pixel)) * iterable list of integers (for Nth roi_map value) or strings This format is chosen because results plotting packages are not common and simple I/O is required by end user. The lists can be accessed as lists, arrays or via keys Array of :math:`\varphi` value for each pixel. List order is determined by the index value of the associated roi map starting at ``1``. roi index array. The values of this mask index the :math:`|Q|` value from the the ``static_q_list`` field. The ``units`` attribute should be set to ``"au"`` indicating arbitrary units. 1-D list of :math:`|Q|` values, 1 for each roi. Sample temperature setpoint, (C or K). Sample temperature actual, (C or K). Any other notes. NAME: The NeXus convention, to use all upper case to indicate the name (here ``NOTE``), is left to the file writer. In our case, follow the suggested name pattern and sequence: note_1, note_2, note_3, ... Start with ``note_1`` if the first one, otherwise pick the next number in this sequence. Describe the computation process that produced these results. ././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.8796844 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/container/0000755000077000000000000000000015060352601027007 5ustar00rosborn././@PaxHeader0000000000000000000000000000023500000000000010215 xustar00118 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/container/ComplexContainerBeampath.png 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/container/ComplexContainerBeam0000644000077000000000000001566114777236751033027 0ustar00rosbornPNG  IHDR}{sBIT|d pHYsgRtEXtSoftwarewww.inkscape.org<.IDATx{XTǿsap\P d& ʩ̣)+yKvJ;OuαNN'ĎSbV Ira.3f3b}g^oo!pdd2O>q0h 1Lؿ?ѣGvӡeoM6aѢExWY%8|0{1,]+.2Cڵk Z9r?k7:\df8<.,vFA}}=co۷oG]]k7:\d;=>xy$2c{eJ|Wu cfL`"2 )h4dJdffB`$CE@e{aPb 5\d ''F?,[G… (++cE466رc7x:^^|t!PFsԩS>hDrr uu^te P]HʦMP^^wiɥKG9ݯ7mۆ `ٲe9pҰh"EKh.nr@pDH`ѢEV.H&L@JJ mۆ͛7+jzB7_/#\ܤxQ^^tW֯_p<쳸zڃVCq:*ذavލ4L6@lܸnBZZ<!we.pp+W@P.,"(,,IJewyG50i$,^[GAyY_\.nRTT>vkDPst -- 1U+o &&/ T/~ppEE@VV<ŋ#1ѽ ,h4bƍX,xW :~ppzT#Od@cc#׿˗/Wܞ+ƌddffɓL}lNŌ=L}7?6j o޼gϞҥKxWh+cu!p70odҁzXxV3gb޽8x kw@n{(>m*^~=.]^z ݻwWV{Xr%zGD&".n H3TJ"$$>vK1{l>|yݾ"mIEAAf̘QV̙3e~t5vk WZ>iRO :#m_{xޮڵ=<xEEu fEDx`p9Pkyu_ӱ?,zǍ뎡C}۰:23o磽̝ ߄kc{珐(9W%"#^HIqypT0g 61F4L%SO9/3iqxTsg^ 0GI^`=ܹcL8vԪaҤv"`2PV&_[W'}MZ4ZL[/~JU7zy:P[c)I p~m+/ !64_{qqUݺIf{?:[:56TU5J\*0\E?3fN<Ǻ}m/49Oܠ-VGOfS̏ ސ!|t <Ҕ[PN(A!0LPr!&64_7=\ܠ[75I!M_~܂hŪq"FNL 2mi`on{:u6vpooijtkt@eV[M~ ) @ !t\ePmU'ZPS0!*2gmEu~4nOAaIEDD@ҢMF7?['A}Zs^>n 53k<ΟOΟ1D`Ҥ@Loe࿞qonՖj,YM#"dD|AOMð N38q ͓>̟#FcԨŨ Ò%w!TV /BqqzXs  b2=[?/i[R~v1vcƌr뜏ѣ?nЖtT$%٦!::[n36mxǙ!5OE t%VD?v˅ G!11qqiSgGtgkE+|Xp!"##zjܺuKQ[aŊZxX4pp֦كJG+WDEE֬Y?O?ɓvE h_Iz 5f͚!CFiiZc xD$\7=\`0 0(W'X5D@ojjjHk=zYYYHMMŽ:ިM)<\Q\IhCt@ 99<{=>|XwbX0w\FZSDDcO<.nw"Jw $##FO>$L֧͋/<^ѪۗB}(EM kCJn:oS1ׯz-\x=jv`߾}x0a,YDUۭQVtA'EMвZ̟?III;TYQQs{ȀFn HEMPX~!`(no…(..ƻヒ>}o‚F %?\D/DE: >eeeߌضmRRR0k,EmCeq lV+p&gDFFn\t?t@ %%HMMU΄ S*j]Jp8pppONU6bGXU O:@BBzU,8"9ǡ@jEqoY6̑&?'Æ 3]E$$$s;s`Mŵ머v:qEAӡ 6[<`O~uggEbȐ!#.)h.\\dtӸyymkկwEBBQUr=BCY=z+s{@LLj6M& D2_K&O:N||<ӑQS_54(!6 sO qIA ޙj@UHNNhÓ&N9ǹxW|[N˲e*UӤ ;\X~`rrjw vVѣG0ֆՂ]>2v@||<,\x:߿?Yp!<ݡx:[7Jqy^$FC=ш#"<`G,F$%%vSE@|}}#9vٺFc7{\dbƌ g;Щ\ԧ Ɣ)S}HJJn"` RS-E@&F#{Tg碬*<`ѭ;3N" #M)A`@ŵpNQUyн;nk}=ޖBO ƣ(8n[̵|`ɬ]Tp'x@ Hy1x{{vSE@f&N n" 3E@]Ǝ~3g ƍڕ.Abb"oq@,h!<p8\8.Epp8\8.Epp8\8.Epp8\8._Oෂ ݻ{:>46/@D뫾v"PX X,@~>з/k8yW5 *   nݔo6oddWiҥ+ \ > Չ̛ZFA L\Nɶmٞ>(.n{G 44CЏ5!/ȞFBBE=ٵKrr wm_'d*eBHm-!II}yBnPW̟/]sQ^-<Z 1xC2w.!˗J]wʒ~I !{Ǐ!d:B$IK]+}mtF/{7!z5!!!c S)쯃"pP@UULxrXt{$஻ێ+n;'}z=0st1c_~W>g^Lwr$ϳ^/ohEX{ȹs@y9ݎ||\{VҨ[55F#}.]7aI)fq[)m=j$ %wK̄vaaTTpZBRRD BZy6!4&dzBbcSc~~Ϝfً3Вk9t]X,4HNu"mKK [XyE@.*+틃xVh)٬_~I?>Lc_JHϞ#G(NXDa:ѿ!C~t@Qf<୷o| NH-k_KJ>Z-`A|Hq6=/AE#EKfAhCT[Z2l]TƇAh}E}=`u"#;vKoָpxy46e2p逻|)裢w# N+(+ZZ;b}/Eu55 O/ФQ+*={*x$YYSOQceW(-;wOrƱc\6@v=/2{6i"“`{-\TU_B`"텔UƧ`İ"lDT!.9)._BW7'h!M ÇӞd|Ybɾ}##]Om=*J'^ SaСtѣ4=: rsMW&Oܹz|ji;n|>g0;1QT$UU4f#yHk@}s3i O,p=G^_Fz%Y"%(+#d}8SƇ`U,t ڹ0y"|t=ȵ0OY ζZoBB!(E<݀iK#TOeP:={o9ҩkg2?^YwcIENDB`././@PaxHeader0000000000000000000000000000023400000000000010214 xustar00117 path=nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/container/ComplexExampleContainer.png 17 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/container/ComplexExampleContai0000644000077000000000000006101714777236751033045 0ustar00rosbornPNG  IHDR[LsBIT|d pHYs' tEXtSoftwarewww.inkscape.org< IDATxw|TUgf2Lz' Ii@kAwt XֺXVņ+^UlZQTD$tmPHϴL{d; ~>0ܛC̓{p ///Q)..FxxxWwΑGWwZDjjjWw]ٳ999] ":O رcguu7Ւ%KzyWwz"""$cp """H2"""$cp """H2"""$cp """H2"""$cp """H2"""$cp """H2"""$ura 'bbI{FDԭ18PRP<0n]/xUPA-CLtx -  7_+Faρmۀ꺾uc 7?PU%ܾVo# غڬ[u%"6lnk4o,h7"z={Pԩ#F4~@:Nߔ)ɓ@e%`0o{da ""rbp#0Ppf~JJP ,37ܵ}""xŁL`^z5M.V\Q w=$iS~i2% Nh> ! 1xQ7@}/z=P]-T>@.>rAD 18PQVvH@h~ 918P』|A nq""8P }v-[n1}"">ƍB'W~ SB\~yap/:XDmҴ'Es\wp{ ;ID4 ˗[ :L,|) c#|4JOϮ/Q7@}R UќV ,[&\P(DDXjv@@= >,|x{Ç 7( mHTXXӧOcذaP0hQ@=VZZ&L 6݁#G gŪUPUUv9'QwɑDDD$I@DDD18d DDD$I@DDD18d DDD$I@DDD18d DDD$I@DDD18d DDD$I@DDD18d DDD$I@DDD18d DDD$I@DDD18d DDD$I@DDD18d DDD$I@DDD18d DDD$I@DDD18d DDD$I@DDD18d DDD$I@DDD18d DDD$I@DDD18d DDD$I@DDD18d]yvڅ?W_svh| y6Q ?nĉ~" yqVvƎYap "": p̬A|O>#矇#,r KJJνm DDDj!6oFVV *+ `Y4 DDDYS3~HMEj]ݵN@DD}کS ̬AFF bcQ֭꾽իKiS23kor>~.^@DD}[oa:$&1gN8p 55VlZZ(q}{/ aa [h^-[U/ep6Lۉ=]G{ع*\{mRR⋑#kuKf;w!3+~`ժDy &ƫ{718Q/Uؼ5رf00lep=W:uO>y ۶S#5ii~?ާFg08Qk w.aޒw@DDbǎ:l\df60tepHI.9`p "qy̬R)>HKk߁z."":kfdefsছBE,[ Lpܡ|55v~""jSvo 'DpoڵX,w8Fzz ڻ{N DDԦsU\?tfki;u5K__N{ DD}\UYY56O< 4~~| d6]U`p "sN0#3jp8\K. ^k4aCkѨ߳QsmGeK5 *JnI@Dԋ4P]m̙Am? ߁RSS*gT*ڽ}Mmm- +++}?<==ͽMMQvؾ]!>^28\qtl6 YWwS08P+/իld,Y3fv_cժUm{|>==7onǞQwpq}}:iiԾ=rs1W}Axb`p }+ 9soh7SyNnv uJK-.k"̝W\4? ΗX,xz_=?~7L&~X'5HJtV$Wv7W*V>> ]o,KuNڹ7t۫BnEv uюkUlZ*+bbp\{*rlc~=rr g>5p}ɀ_C@4HJRw˥HjMM}gb*+8vP?ޗ{; sM?~LBJ=]S,Pt7Ȧ>>g7`)/(CB:˱c&8aA஻qHMØ1>./SK6_Nzx!/ψG~Tgb\9 !A w󨢢l9PcgJa{28u ήGffRQ(*(z̍7@ЂJ%ƾ~}n󾇇 xaƌ@TS'鐾v5ipg'{w9SO9o{@Df:o= @ >t9n'1PVfAvvNXp )s &Nqyqqj(}j)  áCh(-E"as:_DM7@Dt.8v̄QE5+iꋔ?嶑r˗t#!AYB'2녇Q"-BSoSPu{7[ vm$'38IqYd)#Cߡ :ϱc&:dhjA3K|U"W]HHJ :ڋWgAļy۱%|8ר{_}5O@ rXNFCI L'N/q`wO+Qn>y}}Ճss/U $&j0h'btg7o6nq( I͆ҏ>8V[uZ˅I9.a?3m((0aP;+26C3~&IIj$&jЯe //N(#?y2  \/,A»iHr 23Gp+wɽ| +&^r~8av R")I#x°u1s [P(snsahsV t^|1n"08Qr:~f`J̜)vZݳV-V,4pa$~qg, )ID5έ9u JkEȵ,eeh(-P3, 2-*v;p bq 5UvHN>{ CP} GrW(dBj.9gNҗ(CC =! Dԣ5)l-uk <=(/$~~;_'c "=jɸX{"& IIǫY X=_/ ?~0zjʍk1u>}OOո@~y_$sXNF@Cq1lPx{C #?e G|>Nm͆<8^֕{s#.߳gEr<=6V(+T?sw(+`f8thxHL*&znD}MGa7D4. |UNRC'ҥKlw6͛7a׼slgXsw7?PjW3?<+C?sxZ()_pa.8w:||o? KujHLT#5rx P\}^Ñ#'#aJ;m[.pWb%#o^~v> '_enq>ww1#bpNJ;^ÞKr;acLطŪ΀z4DrE୷TqV+\ye;q"&Oy'f3f΄տ8V,XH]~38tH 2䜎 Q;kldP8D0mZ.wpw`ٲæ%qk0xp[AQc3<7Bfv>3fҥ \ ]ӦA_e}++UHG2=q$S ?}Z/ pa̠ [cAZl&>Ðo!85@P`_w~* o8l6z-O7,ڞݷ/jëԔ5 /02xy_u v;`4_[o={6G`Xi#FS-HN?&:vkbA3 7׈n ;$ѰXΫ';ɓXV QPiLǎl@D>ݴCff-(-$Z_`Rf..VjD0#^<ÆoZQ"luuꄄ>3\jsZ+Vȑ DJ/ Ɏ;ZԘoqKe2䁤$ =j-GUaO7-Ɏ[o CjPhi d2!oq&O!C\.$Ѯ-\QEGCTaxe߷3nv D}dǟ6pD/ҥWdH_%C.%v >Z5'N0F`VũKqHJ )I8^%~k׮bi@vv6+<17mvw Nv;W94:vhuy~>‚Ç @"-MAj~{t y8Gb9>*ֿuxHhŜ5 /.].!LA 7Pk>3R4ߑ-7+W=?Qg:Pۈ#z4~#^%A.=…5?]SxP;"l= Iup{8@iϝ ] WxĴndoD:jn| D=ֶ/kf (€P|8Pr ",h(-d<QjΝظqh[o íG\&߂Ɔ;+U2'0j?D V쇧W!9"=vDO?\X"X**ZspQzqep0|5dJ%Q{ʪե̬-w7!1Q b;5tF'p㍭kz`H DD !1q5S/8pU|ӱcv<+~v[5n1S#5-wطOK/vV 1Qɓ! Wf, QwW+4rgvM DRaG8=ra|Ă͛O;k|> Gõx$&jFd""w($&B6L`.,D?olLJȝ\jaLC/Q~[G)r n /{`޼Qb3OOG 72Mrh(0؃:"^)\x IDATAb.?] oo(aoDxTUYzu&b> TėmVmjEp v[>B}eowemJ +Wã??`6ܣ9HM|}6r -+px,V(}Q)@9ih 3 \=A%FV8#DA,ThvP jD@oHp-6nZؾ^`~lTE??EY0v-<խMF0/v,f̆(, s~?ڻǏ`0DeW$:lZY]O Y`%G["6tOLak)Vw׏]|q L.*:?}}-=ſdt<4.ߘ7lIJeE@7ڿ)]덂"l. q ࡇZ܂*epػ떕w7swdSVx {Qu(m2 F"OHhcZ<>cF/(êUŢqGOP{ގt>yۑWh>l@}V/k\OMZ}1\'XH[{N wyŖdFͱwxR!*J|־}0['5Z#E),4,ȑj7-opWc 0`t4[}{!"[Q({~܃-[YqX:˶ 1T3BMЂB/g/Ç Ê{2i" ɸr>p?XPD ?4eh@E6rp!-L ,_M?W.k&PZ ܸq>PeWyaժ5x]P{ _cN#Vy=bb[o{ai逸)owQV|d̝{s ZڹVkc:~31~q͛7znh4O>$z)i@ŏ?_&#b Ƚ ȑ2@I5Wo{#pU8p'(ߐB0~7 ۣ@ǫR"(J+tlsWAo$@l ([7 0-3sjaŇ8q # נjO8hB ERB߀^0]Kz  8 +ԌPC\2j`$LQ_A!:ر_ŰMzcTc@Yfh_99lf賳[=g7`>q'Pw(x >? ۞#@KK MT#C=e/#Ű`V=~:tv_&$"j[b鰻)ݜ`@}0݆"7D "2ob,|(0R)CbQQ*SVW86mee#,3$$DtެUUB3A jbM #>h A;@ڵGuy~fœOî] ʪzs%d2-CC3':GQ|KZ1:2mOX""ʑ2arI'i+67p?nMgEw_?38,Y 8zVcƴ3w@(M\a1c@ļHBD *D$8QX婉)G@[ψ Ϛ.\/D8DH&b޼Y3KC,2dIJeQTdNg]S.9|1*ԖYi5-+7u5O~Fe DK a*(D-^,)44?5.Qp8xhdf`ӦjS%@cx}w%B=UAގS9fҙ1`K`mp l QP`Ƈ`h .zm{̘;X&Q0< sQf D] ,?/le6۱}{23kQaȂH%R  t y,N;uP];H(~9uOkg>YѺE#.Rɑ懴4?Ȍ:(%RHN")E^R%5][P$L£X̞}!NJRK.AKD݃W\)?>cǞ PEr@Cج\4/G2غ|^ Gb2+4r\}]`%t:6n? C(kp8c*+Px; BMGʕ:ǖ}sodz(Wچe*BiUJy$yfs1rrey=1\Ym }/ц$+Mk):U(Cdd%6An݊r m`p ꁴ .u_ƶX8k)G"5qqmU(dŗ_X;?%,Ɂ5r(:teYm@BD&Qpl(zudd 0}zvƼ<.~_~S  `p lV`cpGy1{vy[n -aS>S:TʡT__\A帉·:>_{ G/ލ/hNfc#p Ģc/!yX}ddT#3myk.vFn(4ΎM(Q,%CyNŁ Y- ePr΅^rdsʐ x96@GT\ fc}*HIC``\ Ҁ!SEi9>;w#gǘ1@bŪI|zg[.8s&J{C"# ʐh z:r ;. D6̘lZ^: m h{{ɦkpͿ/>/,Gx'[Χ6_C x'a*(`.*¨[m CZ͠#ۿVaۗ*c;X1n\Mɀh/1#j:8}z1lp٪Xވ\QeRʟBmM7a.j9[x{C~* +~z'XLJ E.-vj?ݎwk$:UUg7zbOGgg&+ ~))@֧Y4AԮd4>< L8E\#″0}7BX'W=w::Y| `‚(֦֬55_"o344)v- GCNC۶ :##\6̝벩\.G@@&LЉ$:Gv|xx8`̘1nXd2 `_8 /г_{`xzӈ.p֦zu9Q# BZzmس>^3hvef67vuOzp39K%:wީCJRR|1i_8j7Vli0ؑkNgĄ kHHOOa{}f/Nh0gܸ:qͦX d׮ Qr(PW'ܾ੧Fjɓf盰uk-^~Yx,!A? s]'h1#Fxl#pQR__o.S;p u[nA믣ߐ{y<}߻r.28`J/ƿ<<KEԣ4cǶ)+Fu0D؏Bz,^wf/&LV{F*2$'k܆́s.ŦM'7b͚Aǝ.XrHE99FL;3OÛoBp9qe#77o6nqxSEFb?~ Y#,ݔKОFG}QnfߡCի -[ܽ_]*(0q/RSpሊEۂ8i` ,'Lj,aB!M*+~핔 //~ny5m=_'dA=@B M}|(a5?X҅n)_?hZ_pA}68Hq`zrr8yjW_{rRn1b@Z]'`*(@[o18Q%wsq҆ @ap =OWK. %eصÇ׊8rĀW^)DJpe">O[ѣ1zChxq67ߜhΝElGA T 0RQz懜1:+{&\h@D݋B V|u'ˁaI XP эxz0qx5GؾWt*TÍ7""N2qolѣFtF ,Բ7n7  j#i.4vGnZpVDʕ2cvvp"f֬5ZwBmK4Ә6͟,Tr Ő!+*)~ ^pyRR|1fLYevxAI?gxǷz^@=>2ٹzY+/ʪvM7->pj6u-[jEx"@|+ BP'JPv;'N'l$uk-6n~-vn2p0@;t( Bz?`+(@9j/Z@" M&V=ƇK0fveۨNg@XXyyxqffР R18EE+,e;zh$ 9//2^nFPĆ p饗^w ۞{9 ii~nߍ& Cuy$(7J7!C\ap^^}Ul&&1Q(}E7~Vaۅ'vnp(*F+0tS@Ip[.~0O\s:2?XeˎhwC]oodܡC|l3ϴن73%k7= \eZ⋁gxK]駛BCW3F؟~J{7^Q-ĉg7jnj!v%|u;vv6Or!!  /2T, ْ%M!"XJXިFx}maaI׿r90{6; Gk}$wcJ &ۃ?~QAN?T_ >P0Q[8|9'On'!+iz}/7 -o)%/_.,g[e_~K/.]8u >x9`T 0PXAM EEGwY{ 4HA\/[/웠*0~RRꋴ4SӠ88k~N-*7l@ڵi.tjҥCCs>+\uPKw/O4Ix*uձ'9 sn#t^y"0js֭waa`iu 88|-B** ~'+:aa>qƣGQpl8| ɑ}RmJa{f&` aĎu_~)!ɮ 0lPWa-Ʉͭ{N^vV1e?L KڷOmj]΀!9*֯ 1䓈?rUU G QwpX[EnF.me˄tEE~ IDATmi f}ǩS@v WxqaB(-6 ) ͍?V:[ 9OsX!ܐ08cd d_z)*U0}h{0zљƌ>TZ-(Sp.|}}իɉݍL ԭuW8SC4q цkҸe|3HOOo֚n6CL?ֈ8Vn@n,[&,q{07ӵ/8X|ߍ?CRxh7a: wYmTPǙISW@;t(Amp[.kC#;iBY•vָ7 >Z@w0UZz6םlYnR x c~6 }١C̙MW.e lJ9@xxӲ].p㍡ DFF523k%ѣ]nuMTQQۆÇ#e[3dylW3f0dP9z8]bb0gN8(.صeh7&M?ƚ󊎆\lF ;Ƽ<w.W3L3U}ƌqPE+o,+|#d2G|n;`S@v~^pGȑ$&v u=>UUM AZXXHx5-ĢEB-22jo_= Cs 3Je'ᗖ@+n6WPj|ƍ*:^f0N oo$380 M|3wTTgg`X`Tk7ocĘ 1kFd)5IJ4͗Ċ=͊"Rޛ 0aΙ3swS^=QTcW!s@EcbP#~.U(`+ l}| 1\A>i,_{͛[ZD˺604l?4Bckgo#0]o[#|dծ [SVfV;;c޽9h9Nصet; J:w0p%Z$Ej5JΟGٳoJ<~~/ HDf,]bll1Μ)ALn HK>} /YId2 鸳~nQ(p naa\Vޛ+j Cq#Р3߿?h w_ʪP\f1꣏p1$w_/6:׮!/ķ-{[&U кt5QqZ.D~~݈+ŋeM*Tw/]΅ܹsC@LͰap0E- ]ٛot3& 5˼ujE!!!ظq#Ղ`x\6 @DAV ߳ȑ.__(}|`%bi/srq(rLwo)uS=mwêo_5CWu 7wӦMKB VVx'G?+>Ç[~2C@I!lzH¾+ﻡTZ %%..r3<^=ep߿Jd2 7Hl]X{tӵP*?!ZvSD rWWQkvQ7ke2ݾqqHHdhʪBUA[ mbm-yy L)+툺* }~JXVCKK s$ 㣏1r]X7 S:bԦ-[2pw rv/رHN{xoڤDC]h޽{#n;|.όx~3\H*_d.4(ylp}Up0CQ'*DD􆽽 _~^H8;#?ٝ[c[Zj֫K;Xx1vDBF6{m$ J*z8M\rWW$.<~kwwۇCkBx,_jɋ/>;:| &OVadQՈ/Fll1pv6>&"""G궺o@BV\ŀ͎)+CeF^kD&[x8,lmmZwoݫdo0. * 胖o'ۜb㨑UoAedz/Z3ֹl$]]1h6DF"c&dnߎ^< &̩nu^Dt_d5Y\C9YYYH }?|M{7QH^o86ÿJ&c{(u  · 5ޑC6J%#W{;v`„ -s,!.@ x#FF8;p -BeSKC p Ø˗a9 r2#jp+#gZH ø%~[~R!!y8d<+ c0@QGڥj56; ԥ̟?ZE%)# }lucaHӱc(ZnX:޽ÃD={9/.3@Qh5Zfd>u9ӦMCl\,zmx$D*.9H; rCx[~6C {"%QYǩS ]:$+~>@]^W^yUCxa8)Q|D_$O2eJϪo_nX C ?oP":T&?BC,Ye)J[Xl9~IOzA*ҤWP͂D"APP֮]'Yy̙D=p_5SqT=HdlX@^Xfu%1>7n@1hP1bߏL޽{_p4F,QbxiN.u[:!, 9_~dXl)S8e \ב'XhUAH^tR;w%(((˗2oXzu:C?}^z 9-q|%!cFϣ2-m*LDu[>|8\\\]@" `kd6c~=r Df:z)Sw$F= nDD0@Q`p T'̭[ U08ua D1n3nD5y2bb0ر1p n<*RS]="!C@d?8ADbp  :> ^ip? J%T*U#]=T&a D$"j׿2@us D$1a2mc YI0q=z ~ڽND> <==EEEfZ 0[jjj vvv\"<+V0@uA bH* ƍCtt[ŋPTf:v 'O"%2۷#kN.c8< F;8Luc }6%%8Q  [ BRTܾ i*=bI'LgEErGDڜCPK.q}BNE{I8!qn NڝCPF= ' f Dl{bc : Ϊ "s8G8.cd pxXk//sWEDDȑ#jPfa Da4 r%uiYYYHJJ2w5Ů "p_l,T&!k]3Ϡ-sW[cp aD> 1x018Q0aQ@D18QS z`Qcp N~xc}b jcID^](9u )ȊB]p NJP jϪ)-EɓJO&?66A $V{VWχ䮮XXFd*"2oj(g: PUeG7WCr.>0~\#2*˱??S<YQQ8?d/X=,j~34@?9oo| D[˲ ?i.'ʕ&@o؀5ks  zA[Q4=}A@uQΝ ~*8-Dv@D]^'޽Q]XUދau,_~̙͛VV"05{.]DmS8e >Dׅ0r5kǏƍMP`7@P^!2"v ӧ׮N# mGNӦ%[y"3cWu[':%gvHJ@ۂm]AUz:dNNts3Z_oJNFeF !U( wvQaVeg3Mn.2mCLOl AgcHxPU?GW_ABA#p 5\_~AW_BC>%N!}&_2X{z}V)Qt8rASP^<kz̟oLuQ/Xo5:1%g c&Z׭A&7}`ꊚR$AW% +f *pPz~޹>BbiǎEp!LEr2N@Wv1UH E?Eǎ!1FgP08ղ7Ɖ=x-3<me%~4 edp bH T8.U s6H ܰ{k馋J3r;Mn. mZ؍quHml`#P]T(/cV/tA}@~RkkƢ :BM z EE*AAHIHPM~>Jϟ݄Ԕ…Ɂ-~NGgAӠ t; "&]]1q#"P/%K`?~@;3kxݍB wjQ~:L  Vo a{$uؒχ&/.Y(4ۓO32R,sP}7 ںUw"yŊ= Q3zGD`Cbߏ㌇.M 省[x8z>z̟|~~yMYzzo\}ѣf*$ Rkk( h4QT0"A%gϢ2-hشI-7 bT 񴮥8D&ĉp8^k֠GaDG]BU?,=zyf[y&$@͛(t ޽+& [ uԑ6[WPx{7[aQyEr2jjD.k^^DK" sryp7FB[of7ht)ghK]?7nDs..zn1u+[~/S;4&ݷn ҍ$1nf"&55dgCjmmplIrx^ I[ (9wb2\ Aə3aa5 ӧ#o>kҳۓ)QA?1aM@7DD hj ""nV/"M D 1855cbhdp~8ax(}|ZVyve ۤ,eٳ'ưap "2]E]mCnҳgQtG8`t+W[Ejje S6 TۢYDD.<2QMy26E'ONӦ BU7n-/>lDVϤH62FXf rӿ|9.Ϟ@Ddup3G<6>/_n:AAe/y7F?-i޵ Bux^ӁݫW زUYYZ_gYy{}9ơ085? ;;&/?%K .2UQr4~ D{\70W<[T|vwōё$(9{}իu'ʕ& bHMչsiT*;gÕz;68Ɓ 6Cb_̙4UU~=_kOOXBM5ݻ/] 0f΄\T޾ǍDzePA:1{ @`.))iUm$\)/GQL rjgT^Ho&S]\0dN\ӟἏܞx(x7X<<]4) I,V<R++HZF# (overlays NXentry) (overlays NXsubentry) (base class definition, NXentry or NXsubentry not found) : NX_CHAR [] , --> @ : ( base class application definition ) ././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.8799238 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/region/0000755000077000000000000000000015060352601026310 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/definitions/contributed_definitions/region/NXregion-example.png0000644000077000000000000001137214777236751032231 0ustar00rosbornPNG  IHDR pHYs+IDATxvJѢ~o O QQ)g9GNv %i?W{h02\.7' d02@_ :No}>?.E !<|?VqWXJ",<' t:5op)C#)tΖ0@J-%e) 0hH`a7ޖ7m|[9/Ua/B=s6V2!8s%ӆ C`0hse-LR T!e].CY{[ 0gnU0ę *y~0T#jo@.tѷUr,Rqur||us{s᫄!U-n\-7ϧua07KI!+*MϰnUz0tk#|0 *4}/_ a gck0nh{n5U^|l?vsOV_]|сm?ГnOxo?2WGRӫ;? 7Ӎny+ήG|SW^ ϧi:z? u׻ڟpHX9hL=ӻ?JZZg~H8uơ岲;~S ϟK]|eGEھ:0efGغ?7~҆n/6{Ƌ*Cf]0f^8siuCJIy}K6Oy%CU!gq3`9RRV [RiMi]yYCW{6\.jV/6徻g| aؤt>?9j6 +>b_A2bϥiMn5w_'ll"dYd-zҺx)䛿܅lm6Lsu;L?4(y=PYH*}~e?aifb<{ b|io'c2;d67ڰRF?9yz>Oކ0,L[? [4QXDyz>z0t^_1t51ƨ 6CKTaqNjms3Rm6 pFkTo* @y]ݪ$ p@x CmaJvgHwD֙T1AXmaMUB![B@%ު$ 58;M_holp,4ֆ /eN)koŰ oiFZ;˿RVޢ oQq7$2@Fa # d02@Fa # d02@Fa # d02@Fa # d02@Fa 3t)AKIY(amTt:y j<5pY C\4-6Dj6HCJ\GJ^|ks9WK^`ahƱw(rsλ7|6_'rU,XJjIՏ7|\m5\1pچ/Ϡw!W/ J3[viÖ˗oBKI r\v&jOh ^pOC疤 0JRJ\4IZ:RJwg% 𒻒vJ̿Gμޮ 06=uCq0P>⯷?ʹ=pbh^~; ߹qWm7i/j6p :cNkN3j!{°_ŗWV-oDCX5ϧiܵ^O;u$&QW?_0|ׅpaX}KJE7;= U/mIՁ' 3%s;;;BO1CZGJ0t˙/P0L>c8RoHIX9cj}]}+20 J~a.#Fi}#%a`A؃0Eb(u$ ,pivƊz^GJ0 ʉ0)a6ldWHIX9' ӆ-{)  a6dHIX0C$#%a`AqR " h ay10D 5:R!0aMVn)  c ' hc##%a`AH)9A?aܠHIXn8G%me4xdu$ ,w&Clme(7:R)CTcpe5:R,C<+ڐ ?#%a`A2D" l FHIX6s 1ކ\uҿmCv}z zaRX:G'L-%i@O Jx}"Db p$cdN aw_1a#OIupfOydb5 rLL /Dz׷脁, )X {ΤrDD!FkaJ! $ړ'0se~7$ au1D D{E  Lpt9At==LݜS]W===$2@F(%}Iɞ(Ξ2@)qnk㉳0PJU*wӢi;0PJUZ{:8{JJžR0J=O=]% dR|gOgOW a # ;{:8{JTyeO! d{J9@)q^㉳0PJx*a # g֞'Ξ2@)qVix*a # 'TaO)G(%wt .. NeXus - Neutron and X-ray Common Data Format Copyright (C) 2008-2024 NeXus International Advisory Committee (NIAC) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA For further information, see http://www.nexusformat.org Definitions of the basic data types and unit types allowed in NXDL instance files. A ``definition`` element is the ``group`` at the root of every NXDL specification. It may *only* appear at the root of an NXDL file and must only appear **once** for the NXDL to be *well-formed*. Used for allowed names of elements and attributes. Note: No ``-`` characters (among others) are allowed and you cannot start or end with a period (``.``). HDF4 had a 64 character limit on names (possibly including NULL) and the NAPI enforces this via the ``NX_MAXNAMELEN`` variable with a **64** character limit (which may be 63 on a practical basis if one considers a NULL terminating byte). (This data type is used internally in the NXDL schema to define a data type.) NOTE: In some languages, it may be necessary to add a ``^`` at the start and a ``$`` at the end of the regular expression to constrain the match to an entire line. Used for allowed names of NX class types (e.g. NXdetector). Note this is *not* the instance name (e.g. ``bank1``) which is covered by ``validItemName``. (This data type is used internally in the NXDL schema to define a data type.) This is a valid link target - currently it must be an absolute path made up of valid names with the ``/`` character delimiter. But we may want to consider allowing "``..``" (parent of directory) at some point. If the ``name`` attribute is helpful, then use it in the path with the syntax of *name:type* as in these examples:: /NXentry/NXinstrument/analyzer:NXcrystal/ef /NXentry/NXinstrument/monochromator:NXcrystal/ei /NX_other Must also consider use of ``name`` attribute in resolving ``link`` targets. (This data type is used internally in the NXDL schema to define a data type.) From the HDF5 documentation: *Note that relative path names in HDF5 do not employ the ``../`` notation, the UNIX notation indicating a parent directory, to indicate a parent group.* Thus, if we only consider the case of ``[name:]type``, the matching regular expression syntax is written: ``/[a-zA-Z_][\w_]*(:[a-zA-Z_][\w_]*)?)+``. Note that HDF5 also permits relative path names, such as: ``GroupA/GroupB/Dataset1`` but this is not permitted in the matching regular expression and not supported in NAPI. The presence of the ``deprecated`` attribute indicates to the data file validation process that an advisory message (specified as the content of the ``deprecated`` attribute) will be reported. Future versions of the NXDL file might not define (or even re-use) the component marked with this attribute. The value of the attribute will be printed in the documentation. Make it descriptive (limited to no line breaks). For example:: deprecated="as of release MAJOR.MINOR" Note: because ``deprecated`` is an attribute, the XML rules do not permit it to have any element content. This interprets the ``name`` attribute as: * ``"specified"`` = Exactly this name. Note that if no ``name`` and ``nameType`` are provided for a group, ``nameType="any"`` becomes the default. * ``"any"`` = Any name not already used in group. * ``"partial"`` = The capital letters are substitutable (empty string allowed) and the lower case letters (and other allowed symbols, such as ``_``) are not. In each case, all names in a NeXus data file must follow the naming :ref:`rules<Design-Naming>`. A ``definition`` is the root element of every NXDL definition. It may *only* appear at the root of an NXDL file and must only appear **once** for the NXDL to be *well-formed*. The ``definitionType`` defines the documentation, attributes, fields, and groups that will be used as children of the ``definition`` element. Could contain these elements: * ``attribute`` * ``doc`` * ``field`` * ``group`` * ``link`` Note that a ``definition`` element also includes the definitions of the ``basicComponent`` data type. (The ``definitionType`` data type is used internally in the NXDL schema to define elements and attributes to be used by users in NXDL specifications.) Note that the first line of text in a ``doc`` element in a ``definition`` is used as a summary in the manual. Follow the pattern as shown in the base class NXDL files. Use a ``symbols`` list to define each of the mnemonics that represent the length of each dimension in a vector or array. In addition to an optional ``symbols`` list, a ``definition`` may contain any of the items allowed in a ``group``. The ``name`` of this NXDL file (case sensitive without the file extension). The name must be unique amongst all the NeXus base class, application, and contributed definitions. For the class to be adopted by the NIAC, the first two letters must be "``NX``" (in uppercase). Any other use must *not* begin with "``NX``" in any combination of upper or lower case. Must be ``type="group"`` The ``extends`` attribute allows this definition to *subclass* from another NXDL, otherwise ``extends="NXobject"`` should be used. The ``restricts`` attribute is a flag to the data validation. When ``restricts="1"``, any non-standard component found (and checked for validity against this NXDL specification) in a NeXus data file will be flagged as an error. If the ``restricts`` attribute is not present, any such situations will produce a warning. (2014-08-19: deprecated since switch to GitHub version control) The identifier string from the subversion revision control system. This reports the time stamp and the revision number of this file. NXDL ``base`` definitions define the dictionary of terms to use for these components. All terms in a ``base`` definition are optional. NXDL ``application`` definitions define what is required for a scientific interest. All terms in an ``application`` definition are required. NXDL ``contributed`` definitions may be considered either base or applications. Contributed definitions must indicate their intended use, either as a base class or as an application definition. Only validate known groups; do not not warn about unknowns. The ``ignoreExtraGroups`` attribute is a flag to the process of validating NeXus data files. By setting ``ignoreExtraGroups="true"``, presence of any undefined groups in this class will not generate warnings during validation. Normally, validation will check all the groups against their definition in the NeXus base classes and application definitions. Any items found that do not match the definition in the NXDL will generate a warning message. The ``ignoreExtraGroups`` attribute should be used sparingly! Only validate known fields; do not not warn about unknowns. The ``ignoreExtraFields`` attribute is a flag to the process of validating NeXus data files. By setting ``ignoreExtraFields="true"``, presence of any undefined fields in this class will not generate warnings during validation. Normally, validation will check all the fields against their definition in the NeXus base classes and application definitions. Any items found that do not match the definition in the NXDL will generate a warning message. The ``ignoreExtraFields`` attribute should be used sparingly! Only validate known attributes; do not not warn about unknowns. The ``ignoreExtraAttributes`` attribute is a flag to the process of validating NeXus data files. By setting ``ignoreExtraAttributes="true"``, presence of any undefined attributes in this class will not generate warnings during validation. Normally, validation will check all the attributes against their definition in the NeXus base classes and application definitions. Any items found that do not match the definition in the NXDL will generate a warning message. The ``ignoreExtraAttributes`` attribute should be used sparingly! Prescribes the allowed values for ``definition`` ``type`` attribute. (This data type is used internally in the NXDL schema to define a data type.) A ``choice`` element is used when a named group might take one of several possible NeXus base classes. Logically, it must have at least two group children. NeXus base class that could be used here. The group will take the ``@name`` attribute defined by the parent ``choice`` element so do not specify the ``@name`` attribute of the group here. The name to be applied to the selected child group. None of the child groups should define a ``@name`` attribute. A group element refers to the definition of an existing NX object or a locally-defined component. Could contain these elements: * ``attribute`` * ``doc`` * ``field`` * ``group`` * ``link`` Note that a ``group`` element also includes the definitions of the ``basicComponent`` data type. (The ``groupType`` data type is used internally in the NXDL schema to define elements and attributes to be used by users in NXDL specifications.) A ``group`` may be contained within another ``group``. The ``type`` attribute *must* contain the name of a NeXus base class, application definition, or contributed definition. A particular scientific application may expect a name of a ``group`` element. It is helpful but not required to specify the ``name`` attribute in the NXDL file. It is suggested to always specify a ``name`` to avoid ambiguity. It is also suggested to derive the ``name`` from the type, using an additional number suffix as necessary. For example, consider a data file with only one ``NXentry``. The suggested default ``name`` would be ``entry``. For a data file with two or more ``NXentry`` groups, the suggested names would be ``entry1``, ``entry2``, ... Alternatively, a scientific application such as small-angle scattering might require a different naming procedure; two different ``NXaperture`` groups might be given the names ``beam_defining_slit`` and ``scatter_slit``. Minimum number of times this ``group`` is allowed to be present within its parent group. Note each ``group`` must have a ``name`` attribute that is unique among all ``group`` and ``field`` declarations within a common parent group. A synonym for optional, but with the recommendation that this ``group`` be specified. A value of "true" is equivalent to minOccurs=0 while a value of "false" is equivalent to minOccurs>0. Maximum number of times this ``group`` is allowed to be present within its parent ``group``. Note each ``group`` must have a ``name`` attribute that is unique among all ``group`` and ``field`` declarations within a common parent ``group``. A ``groupGroup`` defines the allowed children of a ``group`` specification. Describe the purpose of this ``group``. This documentation will go into the manual. The first line should summarize as a complete sentence with no line break. (The automatic documentation will pick just the first line as a summary.) Then a blank line should be added before any further documentation. Indentation should be consistent with rules for reStructured text. Use an ``attribute`` if additional information needs to be associated with a ``group``. Use a ``choice`` if a named group could be either of a defined list of base classes. A ``group`` may contain ``group``s. A ``group`` may contain ``field`` elements (datasets). Use a ``link`` to refer locally to information placed elsewhere else in the data storage hierarchy. The ``name`` attribute uniquely identifies the element in this ``group``. The ``target`` attribute (added automatically in a data file by the NAPI) identifies the original location of this data in the data storage hierarchy. In an NXDL specification, the ``target`` attribute indicates a link to be made by the software that writes the data file. The value, as written in the NXDL file, will be a suggestion of the path to the source of the link. For example:: The value of ``target`` is written using the NeXus class names since this is a suggestion and does not actually use the element names from a particular data file. A ``basicComponent`` defines the allowed name format and attributes common to all ``field`` and ``group`` specifications. (This data type is used internally in the NXDL schema to define elements and attributes to be used by users in NXDL specifications.) Describe this ``basicComponent`` and its use. This documentation will go into the manual. The ``name`` attribute is the identifier string for this entity. It is required that ``name`` must be unique within the enclosing ``group``. The name must match the regular expression defined by ``validItemName``. (Historical note: Originally, the rule (``validItemName``) was defined to allow only names that can be represented as valid variable names in most computer languages. ) A ``field`` declares a new element in the component being defined. A ``field`` is synonymous with the HDF4 SDS (Scientific Data Set) and the HDF5 *dataset* terms. Could contain these elements: * ``attribute`` * ``dimensions`` * ``doc`` * ``enumeration`` Note that a ``field`` element also includes the definitions of the ``basicComponent`` data type. (The ``fieldType`` data type is used internally in the NXDL schema to define elements and attributes to be used by users in NXDL specifications.) dimensions of a data element in a NeXus file attributes to be used with this field A field can specify which values are to be used String describing the engineering units. The string should be appropriate for the value. * If a unit is not provided by the list of NeXus unit categories, instead of providing a category, a field element can include an example of the units directly. * The example does not constrain the scale of the units. For example, if the unit is ``eV/mm``, the user could specify in a data file ``eV/cm``, or any other unit that is convertible to the example given. It is recommended that users and application developers check if their units and their unit examples adhere to the UDUNITS standard. [#]_ Conformance is not validated at this time. .. [#] https://www.unidata.ucar.edu/software/udunits/ Descriptive name for this field (may include whitespace and engineering units). Often, the long_name (when defined) will be used as the axis label on a plot. Presence of the ``signal`` attribute means this field is an ordinate. Integer marking this field as plottable data (ordinates). The value indicates the priority of selection or interest. Some facilities only use ``signal=1`` while others use ``signal=2`` to indicate plottable data of secondary interest. Higher numbers are possible but not common and interpretation is not standard. A field with a ``signal`` attribute should not have an ``axis`` attribute. NOTE: Use of the ``axes`` attribute for a *field* is discouraged. It is for legacy support. You should use the ``axes`` group attribute (such as in NXdata) instead. This attribute contains a string array that defines the independent data fields used in the default plot for all of the dimensions of the *signal* field (the *signal* field is the field in this group that is named by the ``signal`` attribute of this group). When there is only one item in the string array, it is acceptable to set the value to the one string. In such case, it is not necessary to make it an array of one string. Presence of the ``axes`` attribute means this field is an ordinate. NOTE: Use of this attribute is discouraged. It is for legacy support. You should use the ``axes`` group attribute (such as in NXdata) instead. Presence of the ``axis`` attribute means this field is an abscissa. The attribute value is an integer indicating this field as an axis that is part of the data set. The data set is a field with the attribute ``signal=1`` in the same group. The value can range from 1 up to the number of independent axes (abscissae) in the data set. A value of ``axis=1``" indicates that this field contains the data for the first independent axis. For example, the X axis in an XY data set. A value of ``axis=2`` indicates that this field contains the data for the second independent axis. For example, the Y axis in a 2-D data set. A value of ``axis=3`` indicates that this field contains the data for the third independent axis. For example, the Z axis in a 3-D data set. A field with an ``axis`` attribute should not have a ``signal`` attribute. Integer indicating the priority of selection of this field for plotting (or visualization) as an axis. Presence of the ``primary`` attribute means this field is an abscissa. Defines the type of the element as allowed by NeXus. See :ref:`here<Design-DataTypes>` and :ref:`elsewhere<nxdl-types>` for the complete list of allowed types. Defines the minimum number of times this ``field`` may be used. Its value is confined to zero or greater. Must be less than or equal to the value for the "maxOccurs" attribute. A synonym for optional, but with the recommendation that this ``field`` be specified. A value of "true" is equivalent to minOccurs=0 while a value of "false" is equivalent to minOccurs>0. Defines the maximum number of times this element may be used. Its value is confined to zero or greater. Must be greater than or equal to the value for the "minOccurs" attribute. A value of "unbounded" is allowed. The ``stride`` and ``data_offset`` attributes are used together to index the array of data items in a multi-dimensional array. They may be used as an alternative method to address a data array that is not stored in the standard NeXus method of "C" order. The ``stride`` list chooses array locations from the data array with each value in the ``stride`` list determining how many elements to move in each dimension. Setting a value in the ``stride`` array to 1 moves to each element in that dimension of the data array, while setting a value of 2 in a location in the ``stride`` array moves to every other element in that dimension of the data array. A value in the ``stride`` list may be positive to move forward or negative to step backward. A value of zero will not step (and is of no particular use). See https://support.hdfgroup.org/HDF5/Tutor/phypereg.html or *4. Dataspace Selection Operations* in https://portal.hdfgroup.org/display/HDF5/Dataspaces The ``stride`` attribute contains a comma-separated list of integers. (In addition to the required comma delimiter, whitespace is also allowed to improve readability.) The number of items in the list is equal to the rank of the data being stored. The value of each item is the spacing of the data items in that subscript of the array. The ``stride`` and ``data_offset`` attributes are used together to index the array of data items in a multi-dimensional array. They may be used as an alternative method to address a data array that is not stored in the standard NeXus method of "C" order. The ``data_offset`` attribute determines the starting coordinates of the data array for each dimension. See https://support.hdfgroup.org/HDF5/Tutor/phypereg.html or *4. Dataspace Selection Operations* in https://portal.hdfgroup.org/display/HDF5/Dataspaces The ``data_offset`` attribute contains a comma-separated list of integers. (In addition to the required comma delimiter, whitespace is also allowed to improve readability.) The number of items in the list is equal to the rank of the data being stored. The value of each item is the offset in the array of the first data item of that subscript of the array. This instructs the consumer of the data what the last dimensions of the data are. It allows plotting software to work out the natural way of displaying the data. For example a single-element, energy-resolving, fluorescence detector with 512 bins should have ``interpretation="spectrum"``. If the detector is scanned over a 512 x 512 spatial grid, the data reported will be of dimensions: 512 x 512 x 512. In this example, the initial plotting representation should default to data of the same dimensions of a 512 x 512 pixel ``image`` detector where the images where taken at 512 different pressure values. In simple terms, the allowed values mean: * ``scalar`` = 0-D data to be plotted * ``scaler`` = DEPRECATED, use ``scalar`` * ``spectrum`` = 1-D data to be plotted * ``image`` = 2-D data to be plotted * ``rgb-image`` = 3-D data to be plotted * ``rgba-image`` = 3-D data to be plotted * ``hsl-image`` = 3-D data to be plotted * ``hsla-image`` = 3-D data to be plotted * ``cmyk-image`` = 3-D data to be plotted * ``vertex`` = 3-D data to be plotted Any new group or field may expect or require some common attributes. .. Could contain these elements: * ``doc`` * ``enumeration`` (This data type is used internally in the NXDL schema to define elements and attributes to be used by users in NXDL specifications.) Description of this ``attribute``. This documentation will go into the manual. An enumeration specifies the values to be used. dimensions of an attribute with data value(s) in a NeXus file Name of the attribute (unique within the enclosing group). Type of the attribute. For ``group`` specifications, the class name. For ``field`` or ``attribute`` specifications, the NXDL field type. A synonym for optional, but with the recommendation that this attribute be specified. Is this attribute *optional* (if **true**) or *required* (if **false**)? A ``nonNegativeUnbounded`` allows values including all positive integers, zero, and the string ``unbounded``. (This data type is used internally in the NXDL schema to define a data type.) A link to another item. Use a link to avoid needless repetition of information. (This data type is used internally in the NXDL schema to define elements and attributes to be used by users in NXDL specifications.) Declares the absolute HDF5 address of an existing field or group. The target attribute is added for NeXus to distinguish the HDF5 path to the original dataset. Could contain these elements: * ``doc`` Matching regular expression:: (/[a-zA-Z_][\w_]*(:[a-zA-Z_][\w_]*)?)+ For example, given a ``/entry/instrument/detector/polar_angle`` field, link it into the ``NXdata`` group (at ``/entry/data/polar_angle``). This would be the NeXus data file structure:: /: NeXus/HDF5 data file /entry:NXentry /data:NXdata /polar_angle:NX_NUMBER @target="/entry/instrument/detector/polar_angle" /instrument:NXinstrument /detector:NXdetector /polar_angle:NX_NUMBER @target="/entry/instrument/detector/polar_angle" Group attribute that provides a URL to a group in another file. More information is described in the *NeXus Programmers Reference*. http://manual.nexusformat.org/_static/NeXusIntern.pdf NXDL allows for documentation on most elements using the ``doc`` element. The documentation is useful in several contexts. The documentation will be rendered in the manual. Documentation, is provided as tooltips by some XML editors when editing NXDL files. Simple documentation can be typed directly in the NXDL:: Descriptive name of sample This is suitable for basic descriptions that do not need extra formatting such as a bullet-list or a table. For more advanced control, use the rules of restructured text, such as in the :ref:`NXdetector` specification. Refer to examples in the NeXus base class NXDL files such as :ref:`NXdata`. Could contain these elements: * *any* (This data type is used internally in the NXDL schema to define elements and attributes to be used by users in NXDL specifications.) Note: For documentation of ``definition`` elements, the first line of text in a ``doc`` is used as a summary in the manual. Follow the pattern as shown in the base class NXDL files. Each ``symbol`` has a ``name`` and optional documentation. Please provide documentation that indicates what each symbol represents. For example:: number of reflecting surfaces number of wavelengths Describe the purpose of this list of ``symbols``. This documentation will go into the manual. When multiple ``field`` elements share the same dimensions, such as the dimension scales associated with plottable data in an ``NXdata`` group, the length of each dimension written in a NeXus data file should be something that can be tested by the data file validation process. Describe the purpose of the parent ``symbol``. This documentation will go into the manual. Mnemonic variable name for this array index symbol. An ``enumeration`` restricts the values allowed for a specification. Each value is specified using an ``item`` element, such as: ``<item value="Synchrotron X-ray Source" />``. Could contain these elements: * ``doc`` * ``item`` (This data type is used internally in the NXDL schema to define elements and attributes to be used by users in NXDL specifications.) :: source operating mode for storage rings for storage rings Enumerations can be closed or open. A closed enumeration is one where the list of values are the only ones allowed for a specification. An open enumeration is one where the list of values is incomplete and additional values other than those listed are allowed. Open enumerations should be used sparingly as the designer of the enumeration should try to find all possible values for a given field/attribute. In case an open enumeration is used and the data provider wants to declare that the provided value deliberately not from the given list of values, the data provider should, * for fields, set the attribute ``@custom=True``. * for attributes, set an additional attribute ``@my_attribute_custom=True``, where ``my_attribute`` is the name of the attribute with the open enumeration. Such attributes can be used deliberately to suppress warnings in NeXus validators. One of the prescribed values. Use the ``value`` attribute. Defines the value of one selection for an ``enumeration`` list. Each enumerated item must have a value (it cannot have an empty text node). Individual items can be documented but this documentation might not be printed in the *NeXus Reference Guide*. The value of ``value`` of an ``enumItem`` is defined as an attribute rather than a name. Is this an open enumeration? An open enumeration allows additional values not listed. dimensions of a data element in a NeXus file (This data type is used internally in the NXDL schema to define elements and attributes to be used by users in NXDL specifications.) Documentation might be necessary to describe how the parts of the ``dimensions`` element are to be used. Specify the parameters for each index of the ``dimensions`` element with a ``dim`` element. The number of ``dim`` entries should be equal to the ``rank`` of the array. For example, these terms describe a 2-D array with lengths (``nsurf``, ``nwl``): .. code-block:: xml :linenos: The ``value`` attribute is used by NXDL and also by the NeXus data file validation tools to associate and coordinate the same array length across multiple fields in a group. Number or symbol indicating which axis (subscript) is being described, ranging from 1 up to ``rank`` (rank of the data structure). For example, given an array ``A[i,j,k]``, ``index="1"`` would refer to the ``i`` axis (subscript). Integer length (number of values), or mnemonic symbol representing the length of this axis. Deprecated: 2016-11-23 telco (https://github.com/nexusformat/definitions/issues/330) The dimension specification is the same as that in the ``ref`` field, specified either by a relative path, such as ``polar_angle`` or ``../Qvec`` or absolute path, such as ``/entry/path/to/follow/to/ref/field``. Deprecated: 2016-11-23 telco (https://github.com/nexusformat/definitions/issues/330) The dimension specification is the same as the ``refindex`` axis within the ``ref`` field. Requires ``ref`` attribute to be present. Deprecated: 2016-11-23 telco (https://github.com/nexusformat/definitions/issues/330) The dimension specification is related to the ``refindex`` axis within the ``ref`` field by an offset of ``incr``. Requires ``ref`` and ``refindex`` attributes to be present. This dimension is required (true: default) or not required (false). The default value is ``true``. When ``required="false"`` is specified, all subsequent ``<dim`` nodes (with higher ``index`` value) **must** also have ``required="false"``. Rank (number of dimensions) of the data structure. Value could be either an unsigned integer or a symbol as defined in the *symbol* table of the NXDL file. For example: ``a[5]`` has ``rank="1"`` while ``b[8,5,6,4]`` has ``rank="4"``. See https://en.wikipedia.org/wiki/Rank_%28computer_programming%29 for more details. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1748719305.0 nexusformat-2.0.0/src/nexusformat/definitions/nxdlTypes.xsd0000644000077000000000000004233515016653311022634 0ustar00rosborn .. NeXus - Neutron and X-ray Common Data Format Copyright (C) 2008-2024 NeXus International Advisory Committee (NIAC) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA For further information, see http://www.nexusformat.org Unit categories in NXDL specifications describe the expected type of units for a NeXus field. They should describe valid units consistent with the manual section on NeXus units (based on UDUNITS). Units are not validated by NeXus. units of angle rad units for things like logs that aren't picky on units units of area m^2 barns units of quantity of item(s) such as number of photons, neutrons, pulses, or other counting events units of area (alias of NX_AREA) barn units of electrical charge C units of electrical current A units for fields where the units cancel out (NOTE: not the same as NX_UNITLESS) m/m units of emittance (``length * angle``) of a radiation source nm*rad units of energy J keV units of flux 1/s/cm^2 units of frequency Hz units of length m units of mass g units of mass density g/cm^3 units of molecular weight g/mol units of 1/length^2 1/m^2 units of 1/length 1/m units of time, period of pulsed source (alias to `NX_TIME`) us units of power W units of pressure Pa DEPRECATED: see NX_COUNT units of clock pulses (alias to `NX_NUMBER`) units of scattering length density m/m^3 units of solid angle sr steradian units of temperature K units of time s units of (neutron) time of flight (alias to `NX_TIME`) s units of the specified transformation could be any of these: ``NX_LENGTH``, ``NX_ANGLE``, or ``NX_UNITLESS`` There will be one or more transformations defined by one or more fields for each transformation. The units type ``NX_TRANSFORMATION`` designates the particular axis generating a transformation (e.g. a rotation axis or a translation axis or a general axis). ``NX_TRANSFORMATION`` designates the units will be appropriate to the type of transformation, indicated in the :ref:`NXtransformations` base class by the ``transformation_type`` value: * ``NX_LENGTH`` for ``translation`` * ``NX_ANGLE`` for ``rotation`` * ``NX_UNITLESS`` for axes for which no transformation type is specified. for fields that don't have a unit (e.g. hkl) so that they don't inherit the wrong units (NOTE: not the same as NX_DIMENSIONLESS) "" units of voltage V units of volume m^3 units of wavelength angstrom units of wavenumber or Q 1/nm 1/angstrom any valid NeXus field or attribute type A string of characters. The preferred string encoding is :index:`UTF-8`. This is the default field type. any representation of a floating point number any representation of an integer number any representation of an unsigned integer number (includes zero) any representation of a positive integer number (greater than zero) any valid NeXus number representation Compound type cartesian representation of complex numbers (real and imaginary parts) in NeXus. Compound type polar representation of complex numbers (amplitude and phase *in radians*) in NeXus. Compound type representation of complex numbers (either cartesian or polar form) in NeXus. Compound type representation of quaternion numbers (real,i,j,k) in NeXus. Alias for the ``ISO8601`` date/time stamp. It is recommended to add an explicit time zone, otherwise the local time zone is assumed per ISO8601. ISO8601 date/time stamp. It is recommended to add an explicit time zone, otherwise the local time zone *is assumed* per ISO8601. The norm is that if there is no time zone, it is assumed local time, however, when a file moves from one country to another it is undefined. If the local time zone is written, the ambiguity is gone. true/false value ( true | 1 | false | 0 ) any representation of binary data - if text, line terminator is [CR][LF] Any valid character string or NeXus number representation ././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.8802488 nexusformat-2.0.0/src/nexusformat/examples/0000755000077000000000000000000015060352601017413 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1757366496.0 nexusformat-2.0.0/src/nexusformat/examples/chopper.nxs0000644000077000000000000136741015057644340021633 0ustar00rosbornHDF  `  TREEHEAPXentryHv H file_name~ @default~ HNeXus_version~@PTREE pܳHEAPئ(sHu 0 NX_classNXsampleIPNSSNOD8^ 0 NX_classNXentry  WKSNOD8q ` PwEpuMgB2 PDOS 43.37g 8K 120meV E0@240Hz T0@120Hzff33̬gfhff@@@@fff@ff@@̬@@23@ef@@ffAAff6A@AIA43SA\AhffApAyAAhfA53AA̔AAifA63AA̬AAjfA73AAAAgfA43AAAAhfA53AAAAifABBgfBB33 B BBefBB13BBB%B(Bff*B4Bff6B8B23;BffBBDB23GBIB33SBUBWBefZBaBdBfffBhB33kBmB33wByB{Bef~BffB33BffBB̈BBB33BffBBffBB̚BB23BB33BffBB̦BB̬BB33BffB33BffBB̸BB̾BB33BffBBBB33BffBBffBBBB23BB33BffBBBffBBBB23BxUKN0 ͧv!$v\qĞ;pز@ΖSJx$i*=qISJ)S`dcN+٫rÙq2'}Zta^ x_  >oWQp'\ .nX{T UY4 gjف٫ګg۞~QL[aDPS5#ƳXg߹q\ idx2i|< so#gΕL:k}=D|7xGpqz=ڻ#чjRcGm5N|ZyG4G{wŋIqU\*.o6[MPLdA2xg[x΃P+<3{hy= ǜ߹'8D\=W wֳ5=5ޭ{VqZs~Vw7vO.=y=7أ xTM1 gfQ ą8%Zzvۙ$iFER@g}3'"(}-ثVp% 'U.| _Y(x)Awo69@9)=:n!rδ.T+gIaG8pq~v[粘=sav=3L߉lT}5\9|L>o{4>F7sW\d75dsn{Z`lbˎy~Z5]֪e\+ZqoĿ%^jּ{gm]{=輎rME >E@>E`>E>E>E>E>E?E ?E@?E`?E?E?E?E?E@E @E@@E`@E@E@E@E@EAE AE@AE`AEAEAEAEAEBE BE@BE`BEBEBEBEBECE CE@CE`CECECECECEDE DE@DE`DEDEDEDEDEEE EE@EE`EEEEEEEEEEFE FE@FE`FEFEFEFEFEGE GE@GE`GEGEGEGEGEHE HE@HE`HEHEHEHEHEIE IE@IE`IEIEIEIEIEJE JE@JE`JEJEJEJEJEKE KE@KE`KEKEKEKEKELE LE@LE`LELELELELEME ME@ME`MEMEMEMEMENE NE@NE`NENENENENEOE OE@OE`OEOEOEOEOEPE PE@PE`PEPEPEPEPEQE QE@QE`QEQEQEQEQERE RE@RE`RERERERERESE SE@SE`SESESESESETE TE@TE`TETE  deflateD(W2W @units H long_nameP>TREE9ݕxr'xU;N1 L6 H4T+p @Ie8 '+0ωK|;v)Ʋ(, 6Qp+R3ͫySMWEi UUW~\VPVCmnvf1./yӜ)bI(6\=Z,8S_dGٷ5ߥX8mk>y}950/+N(xsu}y=0ų9 )c^z\sgTkO֕;۟;˞E)eћlf?wfBj;SY)2:"f_/ 5xU;N1 f?oy$DAID TT3 QQBŵli0ve,8xHj+ $g\Ye>Yrp \-p<O | | <pS,5ǤgbzYvڷA[YsM7zPHHI0hm- >s [B-~8ѶКxY*#|sZ:ZsF/<o2i{hm}'q1EoNT_y?S7}nwoLc-h_jڎiZZmݣmΕմuZ˵ؖ;Ѫv~2ήij]n5l-]_mɕOiH;YK͙V_* xUQ0 }p^FSȍʌ4l6a̎ȎHߖmoD^6 {;0FM/kg`pQ\w{ţYxW|*ߊśEx0[`>~yok3^o{2.`;ǵ;'/sAuq#Y QHd{,*4G"z-ʹmPOgt2}_)0v^i9Os~<v8&XіgOG-cQS=a=y)4_zgk1.GcNgh-iPV DI+ȮR5_͊:M [gs/ߩvw?`mƍiОW덌WC?> {xV1 fayHGsHD R"YMrKHlx8H'6<{)ߚbQcW&܃G ^#o-KpP1^4Wڞ,QG_f4oN5ԸejJx ZWp9FGMkkNAsɚVzjCs8[8FΎ:VXtk_ 'ݹr{?ckk&osqZ|Z:X7!W336 Loſͨ՜7w -ux1DxTN0\;{O (?>]IL$[y'J#ξlZˠ^H{`WO x>?H=Oo%߈cZ^wJkplO;15:|a׌DK(W3no{ujfxzs\ۣͧss>^;_3h]fsFQ]tڜכ:W_.ӑ{/e kM쵺ҳ,ɹhgM'۬-n>ڣ|[6Kμ}?(3xTAN0 t4-8 ̉/ N!N'p4Mlw4J8cWD$(:;w;hG= dRS\(7{ţYxW|*JCxQ<)w[ŕqL`l;9Z:A~!9:Nĕ?k08;A nl?oٯs~{cQ?$K  ȾYӨS1so*Tk`ȕMC>5X_xc{Di{2'\.`hɭF!WKڝ_j5[N+|V:3#J[4R{tz~׸?rR}Zx}x-Ӣc4QkC; 5x;N0 &C<X8#GC !*W4ر'i۷ @69oHƙL4ҋ * p =x 'o<p n0KIXen9IFasQ򞥿x!9< B@QjƱ:^eIn_8el=y;ӺRHsVr ֹ=;nt@1{ˑzo7~oھfcksl~睫6{\}rɵ75e5[t-65uR'OK z^|~RZ_oQk=\^5?IwVS%vmmL xVKN0 u>-H`Ŋ#q18 XMp%[ZNf&S{q>-Q 'B_&ķ+ȸf3' N_7xc<3$׭{ђ6=}Q%iF8_>XAC 1{[,M\t-u|?'ȭ-琝8G@ jW0u1#8O#js9?ZPab^ J9Q͇ZN>k 1r/ާ[5f̧giv?.=Κ}çcjߺ=<=uxڶ֭G˽+5 ^:w)yl.f{mj bxU;R0 l -#r jJZmh8ŞeF޾87Vd;˺ +㙸 Cq8HQH\V׹!Cj>f;wNN" xXgΚ!x":ؘmq"k'xϜ5p3 1Qn݁KZ9tFÜJKlqYlq |55g H6.V7o6l+vsŕZqS+ϊWŇSxW(O(. Y3ְbSL{ u'e>eqG]#Z+,wpK0:g"p}:wyZ!.?$Zлe93\7e>}r^؋=DH}37m}s5þEEscε=Ո~ng{bs{{қ-,irkשkk=VVumfM xVKN1 o$\q.{ !سg7-q t4߳wK n׼JLbZ⌂ 8.'x>O_;s\W©(>b6՝7&= dMr@IY2S-菆 @ZFFr.O8zc̴Ow)bM-8NW?sq <-~7s:%][@-e{P7YwYR[=kK}:¾Wcb[^VZ^zuרySwH`M+9~k[lǼ>iޚE xUAN0 LG…3/r3ObV#+&Fmlgv6 `|J9ዔ˖H{; ; [G xހO ~?| <{N8g;>IGC}S$HӚwDc,)7L3;T"z#աy>\oNnj?>Ql01͚(f.5q XdY{*Kbqde̫x.ߞ &ĻS=mkxͰVkv.ͺygXoӪz5{[DVokV=guYXﳿ: CxU;R@\`yTahW1F^¡j_;c`g3.)Ts5tUZ쀆5k$6j{G6#qm1 'ë1|N_×nx1< wk;x?!zѳ%9X49-s}KXwjOyE-5E\|\Kq./9%Rlǧ.ͱ5\=_o{Օ#s{KvQRcKe ?^ xUAN0 L[V '> >…p_-o9|qr󎮋d7:N.2'j܏nӹ]OyKt' Ć_O#z>{܂ @:>ܘpAzkKϼz8{ OXc*[bC Z(Y{Sm/7PY>%ڔGzoN-X[usK?KkVVs=gSn/K}cN~ %xݖAN0 E"Fp,k%Xs N8،8 ɖXIN "=o'M;_[*%-?8h߱R~+7wb{F,׌V U7:kbWE?ϲ_wqw:3I2ɮo"np.w< xS~$y<'pn5gP4ZZC z{M{^H1SoИ+ K}vH~)GG}8Q44?zoӺ=ҹ4O>N'@.7~ɞ{4ߏ`bzׄ|.R6.Kvnu<{9ͰR\n'~Zm(iƧ9-ܿ=soIZs">ܝhѱ6mR{~g:jޚܹW=k2 cxV;N1gx iQ"!*Nנ pT\PRr*C;lXz<3k; n}ɡ`Y}-ʁ?#z` 8΀ nxN +3<)&! kF%?Yt '-E?mADEړ?C׉f/Q왾kYܯL6Oz{n4&O='<ߣ>G֒ $\ٿ_=8_{>͖%)x%wtԷαeNsjޱtjjL+ZKxKԳ_Ks,;Ss_ HxU;N@nNAEAGh8%@+pNAxf'G"1ғw~of$M[t7vnטcXg>$@so[-NKG^AvoW z> O~|!΁lbX=[YL_vķ2, kw,p_^8Ouy?EjOP_^'ߧ:B C$ޭD|v杊vkj{"{xV6өzCȱ29g\ xV;N0c;YPѭD9(8 `ECގqHOo>qPE?8~GWnrtֽQ@&V;Oxށ n/{<2OˆP$+`K;J™dXFiD'3U3S?IK5&FcxG$S9#R]|>dF|4ԧwLʼnc\':ܽ9ys^3Ujqt5m >onVO9ܣP{5l}wo/ZisߐsZ{df5޳Sh՛= jx͔M@ =lx\h+uP%% d?ƙMKf'E1=yP &<.ɘ3)2?sRfn;ybw2_'2/#s2WBj0g2Z:0ndQW!oOP'H_4Bo5_|=ff7ǚ# M/ |$'}@ h\b.cq ` 'БS+ҸwhFOX2ZyϮ{w 5b<}~֊hֈ}j{Ugn=3f^_Ѯլnicw͇߭7g=S1I!{Ys} kxU;N@ B(9'@\q.-%EfwKOg&$"W$gK}QSW FոI+gx>o 6 <\'=>IkjAPۨfs8;4o>>vTVԩnُ|جMgF9y]"D|g9xoym{o\\Mq& 尸Dy+9_Eϴy=w"?USHojyả)_<<87S%/;$ِ=Yutr=\)sd[[>+6뱼|sܞG$KgP(&sh_Ky(!Ǟ"3%u Y{t]{}-P xV[N0 ̣]$/Hh! n/αWҬi4J㉓v7R-| 2='#,k~1,X#`{Q,x >oY%xڛ y'ׂ 5G@6Slxv_bȟ(nOzaLGwC2 ĭ<&sI=_$gFH[lFS w*˻Z[Oę(»ü'](4oy|mL~]략XsqY[du$SMK,ԴNνz=J<ߚx絻_-1z?˷׺jߑm¹G_[}m~l/Nj?r# cxTM08N+t@pGÕN=DJʼn=Fx׉HhfB2qM"q)p\>o{x^7OxQ#u"چޏ8ѱN;=A癎GƠ5I3ժy[Ҋ;ZkzRvn~>67-l\KLwXf0!nlZ lP#2s&[i}Ros8RZs)n?_>gKy>jPcwK1Wsj6R^gmv.֜q_z~K4ZOwhޛ%n^\qKz3 BxTAN0\iC N'<3`"vb'PK#׳kg@H=Ftk栜D>uxo耕kv9p \w{ nwx{J;}մֳlޥk;[w*o+7,4GqvwAF~Iݫ#IaZoi4.8݆(?^H\>S^{Dd6"q̗T s1'֭ ߛ?8?Ϟ#0d]MϺZcڞM\-2;o+GMXGi95jrO89kgNDXzzLܿoṖ_7jr=L9?_ xTKN0 Ia#Blq{ ˰lpgJ N%"Rl5֨h ̗Lh;?)NqR\*nwţYxS+>BqKyWQ[9b ء.[{uA:贰1=}XЏCz1۞d;Sa<j |7ު;Z 㞱l__A |˛ah(:d;8=q2y=;k+⋳1?\S/ϙa?_;iVON7^c^,d9~*^~Oi,3wIYbԠ|-5sIh;.;p.kSI}JS~Jft)W՛5/Kz xTJ@Lޮ/TD/x7Ck28ӽRuq&%6sW5͡nͣNwt\CXҒEtOy-_RℜmTm}M﷋>czrեvf.G*>=T;eƸO_Rc3o- ~ xT;N0'n%H  q()9-vp ̛O<{z @$}$9=7/p9ސ!܌#'KVp'x ɟE)d>>v!< ng;D5l ` ';R[z_F)`ɬ~*@j0`Ŀ%8`;sp5w<r=xO^ \ 8+bdM$n!l߉V+ڝ~ύs=Zr[WJ~C:{:FlZUd[7S:; 8+=McfFK5K:kc nG3G:%nfk=*39vpVnc}4i}{czٟ=O ZT/VJؙrs>}u;9Se)#Ι-Kc}}?4}3N_fxՔ=N08?$zJh-gڊK@MOw b/Fz;8 Kϳ$QdQFY+IUW$$, Kr n / N!d >b;X |¾ X?;r.8o==O9R2_an'q3[E'u'̯$y5Oui=%kܔ?fl9Ǧ{0c%} P=[C{ȺC{9-f۝?܄xVKJAN AP Ľ+/)A7tpn TK9vg6<*U_De+7u .hQc0ց L=`c8.[ ؆ 8 ^ ^}$<fڈ'8h]cyvQq)Tlu㺻>zj!VvDZ 2?rܷbH>9u&y[1䭞˘?xTmJ@d7E"R 77'%|xIR73ov)Ji +}/j1'@㙢X^&(X|  x o(okWL5Lj(״.hT%Xpy纞RvM{_TtQGk45-TkEkݏď|4UT3jM}_c={,bM]߱$8g.U,$r𜹾/y.-tbWvwj;КCc)Iű:rS9Sc?/9xm=A..!H SpreM-=uOW.>1%vڏy^rQv`8AXSYVxx]sK{gWo1x?*:q{MN:;{p u2םs^_hR8h@k=]w=i* J;a~8̼־{lc!}&}X{jg[=9> '?שA·k:َs:;w3l9OcG~m[\˹enf;<{؞6q=Q7 cXqR{92ߖg^1گ>0 w0|5 )掳o5{ r8CLjnjY>i5c Xܛow~ Fl{o9jM˜w}|؉30]e5'm;Kc}™:rְgoӵ~9u3{aqmNÈ͘8aj}gu&e?iW. ;#qݳ?2xT;N1 L6K$ jJ**AE9-(3+0ۗ4rcNB iTvK/ w$բ֍i\ls`N31p \p <O ĉ+ < pa-H94&[{^ͦym>Zךzc0xlq_Eu&k7پ˖[ޛ$z~$@Mq'sVRD~]Cy5f~gIߥdߐMEs}<s !ߛ^ gb].Z^{嵔kmʹ_s>ccm KaNpF|ݵK}?D&^ɯ_˱C\ƚsp-6}E lx͔=N@gClo@H *$j*NP* ܃{ q ^e&NFޝ@0`?19U/D㌘q} |)h!8\p NQ-x ;x\ pݰ)ϊorJ_X{)g_ c댧瘱cGGc%s9o5VbZfŦV^Owk,oc$FߡVwE-hxWi~}} 2?ϭ{^Msۘ~W?Vߴ;sT,S*>'92]9ҷަG~1$6jݤكubeλ!.vo>6-aO%6t6!B9xT;N@N !$$ :Zn7r !,fhYﮈH&j)(rgBQ]gSHqgpO+\x d K D%y@9q +`hC`}`)Wc=sMȿVcsqԶ }֭WTg#i}O)3Ҹ!qTx U5nngJsz\}9n窶wd{lm\b2+ϩ?СXqv fXgX_fVl]"$Ms45şVRw2V3&)6m v9OqTdxUIN1 dzeq/ /πUh"vvz/ Ϟo$W+٧}[#G' Ǒqxt;vOǕys'j nf׎Wןf/~{r#ߪc3ı~=mً:qSx6yCȹ !}cV!O>밷kG&<m%kW#zח83Fp*whgMA|eL,Wԇ{oC# | 0}gcXOswkwz ͡?w>f{f,{TY?w/u9߬#٘/8{Ƌ@|>} \j~7) tizzq^,sy? $H#G!5|CT-ն{Y*tuuO̞Z!2oe,h;#ڠ]Ğ+` q>#l# 8'K x >G|~n7p  -x<CSھ!G9}? ^0CѽdΨs\pۣg95m}Lg60fd((>1Z/{AN@_O|#ǖ:+=5G J./Yڼ55RY'}oEz=%-z{:.5>kZ,y~'յڞO54FG{oxFQ kz6ړE]=7Kgo?j^hU3پS./o_|/rh6ϙW=d6:1o@;CΩ=`n~D8V 8.K;p~Dw5 l s? P-l5pJ=G0:cc`?}l%}[b>s%X3Isje|40oJm N 0w*}xu#LF+ƦVSE>;?3tTC'G_<J$/m{JynwOYM2;'Ԫ^㬤gp4ZXo/0Αp_s8BRRt=:opNM+fkQzssQ{ss>IGVWz>r9 v[^Գ>6ZUށ4=JsoI=G;%чmռy)#_ZbxT;N@۱MH$|+JN@EABH\+p=(()gFylcHO;"Hx"%+m~ȁUׁ ` 8N;Ak$ 0=#afv;7{Br y 8wpۓ:6}`q!0f)g̙ӟ{1Sq;) [#߈~s bĽYgsL1&]c-=Y[*gT?$|,xXv&g\+3%{l+xw-%sGofa _&Tꍄg;T]7Xc kE[_*o{p];W"v3={WM5?ڬ"'O5̾SY0Uj-U]C]jmoIa :VUo׺<4ɪΨj uf=u9r8W7u]9;_o3:eu/9p9~[]9kxUKN1 u:3w`*S$$W@l9܏%+V\ZVFzJbi& nkhѥN]L&n[ޮz{ۇSW>S/MMkޥ&_㐚]ut͓zWޱC߱o;Ry!xKnAE_ 0! @&e1̀{e !1` X{`{ᶸOynz[ r 2Wp6Ѿ5i9wc [|3h!QKhf 7;Fcw:x Q=>8 ;K'29^3>{5Iq \Uvmr=l3.{{& _{A >]N_tFp ۔:78?݂"ms+ ѹ+i0]ߒ 'Uvzw;ۂ=ƈ~g!s[kpFOh(h3seg9_s.[m$X*(IMN nc~r6 sx:1 E[9L檠+,1_BM kź2vͪ16wxss}g]gSgy:7Şut 5ƪzv^j̫qY}5nј:][uc/ųjҗ#[}(N_w&️"a[F[yjWx˄M`}ߕT>xF WxŖ;N@wNb$!T= :@ (^;nX3<ֻ^pwD9r"3KlMLlH>s d 0SCwϨSK}W udAdCr2JsNHƳ< hG[>g9OŪFʜ=Es*O̹VgYj$m^-;qGLF_^qq.Wjjw^ՈԳMoob⊸|UgD+=&PO;kշB6>buuuF./BN۶Fmh_t7K]G۽k:M*SOM]|!}>V?_oimP{YꪷTC?xTKN0t4MCTTرaN !6\0CX~3ob6+{ߜiSY|9.0Я8N3wo xAba|C.`ԘkB-@s`L ́p(]`(Crf{s9_8ӣoӫs9KހX{3oy8v1%_ķ}F/nyDFżsԤ13] /_e<=1Oȓ)u>ן!׉ƪK]35$b]=6;VhbBVFp^o+81&{ZS <ﴐGU}U_ƪlIM 崩we+nOul֦coQ՞PMM| u6w/}UxT9N1\{%@)2DF x)< b@ &Ff;,#lwWWw{lι8&qmHlzMR'!vl C` %p1} O>!;zu۹Gp+\⾠q \`y0e-G-|RBSr>g?:܇0bluszϸ_;\9voȜs'cyѦyJs΀]_3ڜ7v)'$w X8sڌ=hGu[ؘq]XcD;a1u[3egNF<}]暆5fO̵>ʆծʫ5^kuE߮j^w4{ڪ{S&>o]Y^%Ͽa] T7бzvii{xKN04-IQB;s%[.8H ?3rZ{=vB!FqFqN2b bSM~+}J>XC0#KmR7g \{ >Eo\ #܀u)x`lcpFٜrNPWi vd'8cs{5`\ۧ8p>!uc2$OO?}O zL{rj^IVC:SVPoq)߾^39|Ke .MGre{b(+;jk0[DY?ΠmI;!2k kz5[䷩/:ƩۮRW]=s|ZڞSXob^܀]c,+ЧmNۂqٞN[I%cjM91u >d fz??iH egQI5ؖjsPעlre܅ۼzjO4ݻ,&m/e4ГԌiDnM8kbkHEZ*1u[-w?kk'uWՋdgyyq?*$}{hyBCE9C~~SFU6ߦ3yQnQ>:]z/S[\`fuȻ/H\x (!OvJmV[W _:x;N@Y;vIHHBxр(GF :i# B5a$qVd?ۻ8\@*جݫD$T*u^Khb=`t>8܂;x o}~0} `` qޣmLq4C^G4'| u&#޷~${CeCdߦy3Uߨɺ)5-sPH  z*nR7[_ 55S:bW+_^]YO23Zobb^!r=&K_:>TqPpz5R>>ksJ/>e{E/Þu9%ELwQ>_/:.[F`e[5e<~E1E*K;o"Z'`bӣ;+#&΋UzX%:k;g ?#x;N1d7OB % J:J. 5+Prn=.H(k_>ٞءkk9h6h2;'Oh#!=p%U$jȬ5%X 8t"QC| BG@}6JRKss]͋~*VE=/E2ƔsU>U{uvn>gV_S==uヒlޥO+z#/[߷7ߺme_xTAN@5ͲB"Er [@;ojQ^K%tTS*?'pb[e '/_+_KwL~7`_|+Cgpb)p +;p lY}|> oGα kz=q#w|bn\wD={bz7ҿ8"o8z{Hglbkc'05d݂9hrN&|Z[%jWԉ|O+5s)VVK˹t^K V[^jr>g㦠F{a_W_{Wնqq%$RO[gOtf~ S>;T9^[k_c}qXZ|?NzN^)՞y%o^XܟO:cRZ;VӚh!^cb?Ozr5zr߷tDiSbl[cg*݅~>>WT cҸ/xUKn1||L O$X8w@H`.† { i*/vw#adT==fGV\ jEH+X[.p>?^ooD W}g_~{cOɻ!^v5cK#m8wS~"5o.m+ZKTߔPgE79z{Kvՙ7u-IΜkF=8wbF̈́ jy~um;B+ћfעeʾ=&ߗb*=w4dbkQe1rh#֙Sq9cS] qyܷ?_'믣/rgꛒtGf;W,нƻW-qGJ9cߠc1M4o_9ܻ+բ^xMN0_d2 tN@;Įr>mO+"=[w@b%ز㍝TX;k9df9Yf [B$fn(l`+081>pJ A[$VEߍ5K$r/s+8c ׬cwmh3#\ڧ{yoN};~ ƜU',W6c;`5nvM2fNթݔ z^5mvC֩gސV_w1lDv\r>༠kk8h[/IE灵ha18kL{8n̡Yp5j"2{5gc PD0vzV6nl{7KkTJwgf;;ʂ,ӕ7ռEgNޥKdr~k V;y֓:Osbߖ:j]߲m|RͪcL1e5}躇]ޛg[~wڤ_dTREE9'9:n;n<\ =E>O<?k6@AMBRCi$DXEQF/GL*H{7IMJܽSK)ML|MN`Ob.PNQ;R>NSy.T+U3V ]WS(XrY\ZJ=['\]] N^gW_N` iaZHb<c .dG&euAf"g@h9i>5jw6kDl Jm& Knp;opiqxrTREE9ݕh p|2457\788$ M 9 ; < B>?[AzBuYDE_GyHcJKMOPRS=UVfX Z [!H]"^#`$Sb%& d'e()Fg*i+gk,m-n.p/r[0t1>w2J38y47{5(}6789xU;N@]{8LBH@!Qq4;p .-G4t4\5TkuVUegfDٛ\u}?]ЇxUKnA|g`; Q"b "Iʖ7@+@BrTKr{<=JӮW랞vaf SG2/EA;FT`<^'>?!QƯax O6/pP3_xÚ 81#`J9 xBx:{ݗ? gfܔ܄EwH.hkZ2#3mȏ&z>F^!V0JͳS z[1۶8oBxVk綱^&Rkl*9ElT-+*#2Q5̅%]j~hUTm&^~gx~;uwV=7YOqmoZ_~lTޢyڼ1kR"&]^ڞ:]>M3Y}S=黾 6RyCc~=\=:{M0pxT;NA鞝]f?,`X~ –X"8qgpJB 29ȉJؖի"s]oCC<Z9 WXY` _#H Yܺ>-r|Z}m{KgFR5B}ujt݇2F7u~K{O].<ڎeWkx?n1=&DD b@)rZJrJ:ΐ"8 H_^lτ~oBhH+HF;糐ytƍ$^q/1ؒW#_-c G(o?= >s-q?ō\f1'c>N)Z!x^жz!uG&0ߚyj)ɿɊ濡=ebosb;w<= 2v;Jo,RbVDskYMEYVu༑볓ZjI7 YD[ Ou}y9΃Gm8}RȞ+>ծ2q%]N:}1[Cs/Uݯ!duDj1Љظ;'vvC|~?юB;~- |#;7_ȿnR3}#p'F88_G">)pE uJC,13`lr=omm0v6ωMbNK[]:rlSo"snj 1\kqN 4<^']xAfBkR{#6RoM'k[㸭F{r9U˸Zx%Z4[ۺi+;4W_1/møzѻ4J1U_%rBX;wX]W'8<[٨]|/iD3JK{__n|sTaUG 9\S7Ṕu`C  |~PLAx/Hd  k?`#8>6x@v(Q 3`}9p8 %^~B><"p uk`y| qor߷id-ςĵyGxkhK-u7ވoK)3v}Iho摹bg},O-~֯+ߧzZ?ֿD6+W[q+]쟰3%SKʕu|ޢ&!_Z ʭ֥>ٵd-5Y* WyuKպW/W!嗲c}ޯtN|%>mub-ǩo&Ǜ;KuյXv'rC]v/Wҙz.&Ym) Nɩc[/_b(Y SxKn1=~M2Ё^ ""  ٲN_cSU媲vBVaqKiD&zicAʞ}Ir-pS)O1xS>o p>;(|?O|Zo |{=c]uOcO+^r<ui;v9cמtؐQ%O2{>~O91&~/1dSͼ{y fqư=?k;^1(M2FCiqz6lϳͱ"GQo$Zd(yri]cu_;bQ8rl>(RenGk Ӆ!oEG a=kehܕ a] _&TꚼwZIy5ߛعNs5ĂŮuzuk[s[^}miM\f-WCj1oj[}β0W W[z5/swqIMsgV?f*xTN1wvKvb $hKKr"GN||?đ?/QeJQm]b7 DEj'SR_rR([F C8΀5p<, }t\1ϸ`)㷺mYϸ70nu_h|oN<V.c&e#r i\r5!ƜG@ۚ{Y5BkikȽUP_,&/7RFay)q[_׎Kch~fh`qrvhZlY[M'cݿ\:桜 աbEx@j]CsSYjjĐNѕAeEwnF}2tg{35|)l庬ݿ5o3w)>]ܹz,שVK.GϿr޷+}ͯS1R߸{SA6xTKn1LQ@$ lٲqY q p@YTUZ'bvwqafɖ2/ħkvnC_Jbk_ѷ8WC9x߁/Iπ' ΁ 3= #p5wsڞϧΘ=9KkjbTp>*kΨ:&Jn7#:Nh#)qFS|?$;u[ޮaczv)s}ogwVOw#θ[.Mgov+VIP5,IךykV?[Ǯpƽ8lZlqmOw)8S(K~w->嗦&{Nd1~l/>w->n2v7[Ju s8b|y) XZmm511ms̯խ:~MZnSr4\z*~yLqܗW>jkjhqwۘQ;Tn xF959Z>YxU[n1] OYȊWx7o@\ !'p$jjmŲggcv3+\;|oWO;% ` ,+up 8' Qxb_Al~N~#OQB !~ |g+{Swq1>qBx㟑9o˜'.w{+]M཯NɻG}V$O\3g!S7ܰMf#1jc*ILrꨆەm{oiodLgqn9$Ά15f~˸Fbu RuR❯&ٽw O~&7}LyK;ߣn;;3).~U~QZ)s~܈sSs]8t2!uR<gq=kV?bx?K͜Б<$ҧ-otѧkޡwʓ[:o}>mo=5TdLxInAEkȞ 6S 36jVHHXqv%kA8+U?O(RzȟcRHzBnDS}lFC`d`An -p 8/w-xWSל |?`=Ρ/؁ x.!O}1)c<~yz͖sl155\WX8 X d5}#̮rə.ؿdS9CtsjߗsvbYz5ccj͔X|Kld.6gyu`>q`ݶO3k=no֫EvcO3HRg%p\ Q'Z87: {pp83 ?}{9F6cN=Y&ボ~xoo7A_V/xG1o>-}Jo9`vȸ7Rb8,nsDHmgۘu> o3o}c9-p)΀2'SIBY&jh3^*%O!ށRX/9o([^+įR枾]|ל=Rv}Mx)g;5}/Y #YWo[m׊{ߦߵVʞ]7WSom3\{Y,נjnBS ]K34S]G xn1Ύ'dIA A% E:*Dx J{pF+NN<0'{k"Cp}d(Cm@c1u3uzư `l5x ^=8gp ?785 o d~@ xCpX1[ۻFC9G6xsɵ kkJ٧>m]r\\V&u7hIswSM8.?Ό2K鋹I,XR7kJ;9O9nʿeʎ%r>ϡgK" idG>V7o(~!̠Rz!hoC#koIcEweML?eZilMߤD4}BT_7O՘|iEև٫jTyN_nCk5sIZIQ.{{T^765Ljz{ȿ`^Ũ2mQMsVޫXs O׬jvwVKbv5Z}=ξ=PVx=N﯌_N\ߝP_HW}x.z9 a1}}[oxT[NQvzfPC4<$؀p` TJNnoG."r.3 p:D􉑭oZ}\,sH>_#vQb?"po(r>5 2~OD;Fw(xf 7w |>X5 xC%p{ ;^葹vigg;$>lQ~p&KsZ0:O~ro~jfʼԕFM;5KҦ\{\|I͛7UЮgrkz{Lfo-3qG[<5 :S[XG?K"$+93v*Ī])OL c|ڽx/5Ob9ܓy>|O'{:\lz3qMsoT76=ws=4>寣t5.ﯩocl~ܣ{Kk&mB xTANA]Bl0 ABP(?w3"/<#RN\VK{m'#zgfgB $H..-& em גжYn܊Cߥp <ld7~% B`}+ Dhϐ>G3p;{ 3fܘ8?~˜7&vHlgF\y-`.節z#&؋s{0J\.x6-*=ew^9. AN>Uj[/54`kZ۫tɥa.=da/5sgR8{Sa\JoU!5FO!T?"*'ucy=ݗĴ}~Oi׉#V־Y^b˛ǬoVը_L-i~,˼[/[g1<xTInT1zo&!i҄ABD`"e]*;.š-W(H{pWo,=\sˮCP%=!jko }`Jz},Qe[6m:`Nzsy !pgEbHGAHA",C>~>;Ⱦ@'l' s ?^ } Ϙ ڿN@ cKֿC:Hﲯdh_RMފ]YQ{gQXS-h׋<>ݙ_{3~}S1o}訾V 9] zfkٵB_X_cHӫܮ\=x^?M^ ,S/roS;^BKc鿟_{W9*~ʧ?SJ<{[MCuVw/W[nrw9Sq=?g[8e)&w&~)ƐmiC+Uk_oLRXC>zhAwxTKN@=xa`'~Bq.!"eAXg6\"'ȳJ9l$&u{.y\%M/^gR~:&.G_8\j³+DdowX}$z:{*K.[$/;mjD7% w|O=x S uuqZbL2b]C}w?9ݤhmJb>u_O#ϓ]ɐbߓJM)$kMR)5ޏ)+-"ju .)NL>iߣyuoѺq?ŋjt/~ؾO{uDZ~CR~^7տ?7z7"]k^FqL^["x;nA{zvǂVl0F N dpNWrhST]U!PAukK 4"Hlos6m=|G Xao;Y|_wC\T%~C5^\|)b)Nhވ'^?ęxw0ߒ'IS.X9↸-vC#H[9%KrHvSkA=I {η&n}< 㟣K)1~;cS CiF ֐=o~D|꘿5v$?z moDu$iLXc:[_7#"zY>vXe}_fyKrkJyB)e./X?m.fڥzym=uzizm3o1k]MW>4V}ʹno}u41.]}5]wGVtߓjs|]}=שLaLxJA;3$FEpq ] F|}śW/RTzkIԜs5$ ^66۔y)i(`,* ܀+p#xo |o0< 8?{OWzgC~ >gCk3w.8e.g9+`,>=}|Mdl.|.6s{סNؠ2K] i;ɜ{^X~ bUǧb\޹mFMnxx<#.#)kE\GUS7]Iδ |McZitifgsjb:jKT NDn{!VZ=͉̞hFbؚ-N%c7WggRC$L(Z:lzT9/~gz}칆i^b7WtNzԫϳ*?t.{ĤW{P&+E}zQދyy*E񢾿?xIN1]M P fLV,8rld "%'@b)sNo?Տ>~~g;z$#@8\p=co"^NYEYq 86>o;~8]&ۧlm 8_qxM\V:Xx ,s~ʳ]%sG׉Wo~V![)\>L^_*׼-˭`>ɤ\reߥ{{ki46^+':^s-zkanjeqcrOזW*?b+'=};Euj#\ݹpL>J;KvSJwʩR6ݎS1p(uO+q=)sxIn@e@S0u@b(BDa`Ş 8` B)sz_ <)#zͦ |'"%u#~)+&>@ f,X+`o{ 8o? G$;nHw{C}C#p^{`c yn=p<7]KԿ9}WS~\%EEp~..kFew ʫ̻d]s̻&u[]9egR硥Z933g e357{yujM$~ܸ7;0V1W)ҋK}SƱxjk̥֛5G[PX&[_Jx9׿-ֳB2mڭeZbdnRsZBt#Q}&/X {]NBkV;/l|Ztn΅O{itCz}3tgB_cFѽ2B{xUKnA-ǞLcb |D QRH|ĂHlX $Ě%r.Ca x%1n驫_͈m%POGm=9=ӗV^ 4 9?7DE{oO!p<w`ѷi6xA]} sKo7k/s/OLos]ƞQwњ2nF|6?5-?1b l[;21>ѐp];Hݖ}*Yxjӻ1c;zU&|kƍV&gEMF-]kMT2Z;J[y)LM Qno@Wh^19 VkWq>o]mx5Xy=p 7v!Zo{m,~}>':K_C)Z6y;hQ>η5:wg5=4|/%^^[_;퉏{ܮ=]kͫԑ;{artUE?=m~ ݅e9!zxUnT1xHfbK !HE $J~{#9r7PoT]]n{<1}0"6{į69̀)0oN{+` Lp>GHr$FnB#O+N@.#tNwx <xn[cγ 繁c\^ry6>aK g%3*{coҶ˺iq~blֹ+;汑3q%gK uM^bu˼5-VC{yְ;5Y1ǩppJxy4&̓IE3IoS6wؾ8VwD_˝ș7!Ro$q~XFv%:Vg%IaI&}&Fi WE,xA|[];V-ko45ۋrKcѧ;Ǯ>{>-`[CΥio*uYGy#yo{Hށ}CשּׂXڽ3hWjE}ԯךּb?; 6xn0L)Җ!^Ble`C}XX[c9Xd\s$Ό1L3}X?[ r.H6u~]nEo`'%o 4eߘc>CD/O: 9c y@yހ8;`6xUoG9{5??x,k :.3>*%P9+*F|#揘}zeܗ>jj Sq_VRSkXyqǸ~_)(ҨT~A|6UO+>}9uQRשPK]pj_:NmSv)2jtjv*r|C SLYVŊS״]?%.7l,)[lٱE#X}C_J+fӔMLsZMuǬ1M4mwRMu8̼f܇u` xe`3O]ܳܿUbc3ךc-Wo\+K%~ܐp܀E{E3\Sge3RVm;7 _P;d[[]㣝֚#PjU=gU/d.$ɞc2-]-+oͥ\~ocq!ۊp),6H\p__No~?$xΞܜyO>WJ|H}Ӈ;KgKm&}8&%[[]+?s%=:.il;]N{?R+xˊ1SIzƞ{먨xW [\Հ[ލ/¿?T |kNRxwF༓Ub^@""yQՑ#;` `X+j>')p/+ b]l/Z4 5ψ} /3\ep5pmnR.x.[ ءo9:Y R8 Z$ 6Q[[lNYQbz`@:m& N   ɿ#^ȷܹO?3D!8Gc <%/#l%آvk&x 1֟G@Cp@=a2n#~=p1oy!w%ĸUnP37}zrNz7G_+K!'c̀r!5zB.X\:o۟a/:el:|obrΡG*.^b6*wG4>Z#$_MH]줳VV7_L뵮vcҙZaitZ{wjWis!xOA>vNC`j! `$Zh4ck쩈4V>7<݋L;ΜwyoHGޢ6"OpDHΑ -Dߑ $|?МA78_g-vx%;3/'?wc`92ro =Žs~w|nPp=p>C;u+Y75xk%[mIa$zhF-'УO!Od9T,irҡ]<mh<|31{U.k 1RH՞ût[s8Z}ջO8n5Y7R=-}ϪS}V#Mߧ.tjYWka]MޱF]?t_&Je?!bxNAkggvvv? DJ!$jTmY:'}h4@HƯcm0A#K1yBW`E|GMSA'^#Q$o= !s @?{` `= {9ygg|_&o9oHS"g>貯$v@zf>yK].7Kџiρ0 #:e߄ƴiF3f-!N2N&MbIԈȌk&s$֧OIdKzƘ 3o6v)YqѓS'k<{ԫ9:¾{Ex_㳺W7zׅuM}k=g[ލq"9kϓn|^5V.jdieFwj/{Uխϫo9UcFYǸ=+yI|_ύ;(WQ\j_t]Vβ㜍qmި7#7xVɊTAj;K;4J Bø# w~xTx ~?(c.*+22{]*jA%*3Zl ɏ>m\w\?z`=%x /O?I@/Ŀ"oO` B8#Qp#; 73s?: <sȏyϵ ~{v\[܋)p{{I8WG\&ԜS?rvK})Sη8ߦ=혜tԎY_|i4K>ow_xûrއRnrx^?/ջGSt]TSN9UqJK{o]"xNSQS*&%DJ0dĄ s%|ރ0vvݹƛ|9gڻyP!1R97Ф=~I,e Ww ?a nP ܃!#G ]Bbp s |' ={cp>=G揨C=K;` @lXYkjǽ/v}\{Jn 8G <.K|%xm~M;4ڌk%}*T|c1Mjn=7U$]c.Vy-k\)k'+E̥ʻ4 cK͘yK4Z'=En4U7J.4DՈL NwQZc/4Hq_X{Qޏtfn=[_ֵO`l}ןݶvڞj=LmMTdg[f޻ɊwdZiO*K"y,5?/W|˹i<~ee}f/ xKRA{z 8(yKh0•`+n\xV`n1\WgtNEM`u#Ru{~o|S:b:v%^JZ{nSӧоAM%=ֱα,%<-סm4v{f9m)Ή[צI-2gymܹѩǫfNᆱٱ=M;mxN08$5Sv(R zQ"$Ė WXwE5lxij-LcSss8PJP=Vs:9BǦEi} y Z\7`6!8g .E#\[}p A.aFq8;lMLжG5f`F  k~_ɽK&ifͧyK9a7m ː{4uзJP`9s6-e?mr 1t55}ߜ'\%7KD} NuX%66.eL=ͯI8oPrr"F W4ߌdB D/}_mfXĄ/1Ǣ"F M(lMQ">tՈðoB-tvۦ_ %w٢n{Eve:٣ki|>Π,oUq]߽:sι{Y7L_u[fڝgn.{s>uV{}Xƴys{xKJA{Lf$|%F$ķŕną *.u![^čkx?)I&Q3xwiw 9EڤXmcR à*` D`Ly3xoPCG0F_W{' u([C&[u}G`2mZ7,`Fmy+ܷ 4K:ԙ_shggR < Q\G(.s_QzzD{(}UHIՑ+flE˾~ҫș*?/`*.7ݻ!zD=TzyJ 2}5cyRCrCh)eO"|g]%O%!u{z[擺y>TF) z/9cdbIu늷G%.OWϴwNOz^c_r Kf+l\:?xnAg{b'&A ! RpGB9hRS"Z*j*:wRa/^ә9sn33vZ*X?]lLgL]2Ϝo  .`}pހ ^ WP!wH |Gǘx 9 -p'gM)!Oc Q^xNC<` =;`zwWQ~c7gIg3͸WcN8ܔh ΃-28 . `$vc{xŘLh?|6QF2opX(9o>)YP+Jܨ+gL}JRk+/)pvJ dOr}Z2>k*^g}ǩg> eN \.? XTug$7P!7]`>:տ)^_>kUs]Surx՝]͟g]ךmuߏ퓣k{sh;kz7:ӮXmPo\ul5J1xՔIJCAMԈC!(ԅ({O w8{^( ʴWUlȹ¸ =Ƈʕs2'T-P\0{*͚;+y}f~=5J[i@MwDlҟ9>hMӃY;$ŧa6cgncc:RSjf-+߶:MILX_|)ʓsRWگ3K ZMM<~{RS| я8g?R==#V駮Erފ 7|gOxߝu?6_{'|1n7.2a}w]i]t-ҨR,,h?ӫ+zej^~PeZ3Pt}FN2䔝2_վΙWt' xUN1΁}{rY2ȯ9Ho!5~z {ɽx7y X^y.>̘%@УܡmNOY۔=OA##xޜ9ƕw#uwŷ$GFΜyfsm|%-+{^"_u:r~ꊿ7kuc!TEN],Ld6>˝H|"ěBe΄K+X{llqV.!V_檇tMƤ$LtL㫋Sx~y[gtU~9Cl?UKlL4=>cx|bK|su5=wQg=wXQwVOitnjxUNAQ7QBcfAX,_sҕ~;J΍JNn׹od({7{SiLlH +)}@[>mo1p|FEK GwYa?A?! y#48g]w[5k}` XE?.(/)'ԣ x&QS>|6q@R?%cb-Z1Xa~bnM:3淬ixHԂu΀FǜWuק,;{,.~@RgslyԴ.)sd(qֻq[Jo@l=̱{oRCj8 h#nocK2Wsi k Ske2ohpvq_p6s59zlekˣ'?3::ؗ9گ+ڙ<(NjrYෳ!-Of|spVWk6iŦK)E&XF囦fȇg._~1>U3ܯu'qZksw܅&{ߺi&mixKn@mόd H9 9X,8c]Xo+r{IKwUu.,+D7y4>} >* )Έb&v '^7!g%x?%.āQB,qO<&v]|6=X},^3^3/}/?b݇&9vًKpxm诈b u4ya~x?!kSWcs0?oc/Fb&kcl5y'h7Vib6]?-ֵ[Ŗڿ58]׸ʺRg5u.S$ЦYܵ\vSv9Miڿs3U_u85eYO}]Nu0 xNTAn 4FMѐ@;6 Wn}o_OVw]*RUgϹEWsphkW-Ϲ/dd6[ s>7NoQ/8G??mC@</l`v3_`h }~18uvkuGy* dU~τML7{<5/s"+xԿI1<}߶ Ӷonp=vE2n}8-EXd2'bךUz?_!1֛ݏ.+f-qyg 'wd!1vg{ sN ?wW+L {oԯJWb~&fƚ=6 l= Ewh!!'<`ݻ`<`~ Lڢx^?Ox C{e>n=-sƘ6}s\6-fm\.j*X/dяrp?5`h}ޯJb ׃h~k9J=x_2Gi41>P'ȟ^5}F щk.CgE_8}.j \0,A*r9][HĥsdyT)_)W*7jn5ٗiG`ES^Cp:_ck7oMc/gk,I^Rsf4~]Y~- xNSA^k(`"ZQcQ64&l`;w%vx arG9sgtfHYZu9kɟ]D,>m#~`o p _`oo$ߡ 8;d(!xG>}}$1pByBϬ1k`@V+@:J٠Ke֛dĘ]:`s p-o}LVXi_ cܜkGY΢˹..cΉ;&  ջ,lسpU7o|\0ŵp;5{:jwBk߲%oĤG焱soDcӷHئ[$E갵7[HKl^uqx.ug_o4,oxgԷ'z}}ox>tUU5|uݨor|XNTՎ7lӎ&禿z;M}YyڻPwӌ&q!x1 Om w xjUA {r351D$" @#A &]݈ |@|_Mƿ( ކ'DPg % mΌ%F+\3`,'^oc DCw!ـH#f1 _|xނg> v=lo'98xI:^=<w` \:_^\`\ {yWi[!Z s} y8n2HLǬhȈz},g\Urm;bm1v@_HN[PgHJ70h z]+HiROu-c蕴uL1׹2W-Y4~S[Ĩڃ-5xI6$8y"ƞ_ߩɣk;u~;kX~8eĵXcZ_RUo1|c6+umcWٚ?Pbw4nnuw2u\woڬjZ&=6&-uSMoDy6kh.o.$kl{')g={$xϊA+ӓd2ىjt5YQ] TdDQ|eoxcWRvO]]UMOOg2{21cw81 Z0>q:%j4]7v ` &`l  z B/QD6"+o?K?Gh z'|O{p6{&xG.3ƾO+~ߣPmɄ{t`{t\d\WwSnrnзꝧ&Ƭ}DN䜤Ƹ _IIj2^xnY7>2;c5FbL~J׌\ƌ?p\:Eў2;8MzL. \*~ƪ?\[ zAzftQXo4E߮kOfL|0~KDD}=׉y}_"4;^~ '6ΜO~붽_5zX/jyM;^3cn9~iRھTm=2Srďc2yTz}XRz輦֖erDbRwFisa"xKnA;{Ig ",@ x,x %b͆H,ٱ pEoU3 ZԏݲsZ[ s˺`:QT'}z28΃ X_{@5wܗ¹\}!6lӎs{H O}|;# v+< n6-p3ֹ["}C~\_#GEh3>)8s\6{;s  I1>ԁb_m=w|rCgԋ}ь}P#uFԓIcrweaiC1. 1&x{SeGmbk5ƥMV\54.7]?U*ݶaդYi7=yOլzGR[jbmu/UiL,[ݫ;wK?uW;lά7ͺ~&:{lIyuKVY޺Ǽx"ox1 Om w xjAg&1^cT" ^P00b ʅ n\&K|? XqέN2PQ :̷dt6Jbj2[# o |/MdOc Nv bWv O]Zw+lǴmg?'KpD~ GֿC^o3o>x f`uVw6{k}/` \|\dB%ZXuy1&/i6О{O%|Dc\oYc˚5vz{_-GK{EY'錑> 3Tce5V߈o#&rSYN vTs]oi~AbSBS1Ϳv*Ykށ6FςĖ.^SU^EgՓ㇝I5yLi|k th?r7gW[WYo-{}}rtz:tCڃu:nWC8>橽ڹ=!xjA{~vfgwܘMJ4Pb!>`.;o}4Jw܆>]=ݻE ZjPmbq@ZjeB䷒7#&/W|"{ oc1>;!b?{11:W)x` l]ڱGc>u"oYX3xG}D6]hX}` K^_[cΌ\Όa,0?HD<5z1=>;oƴ[&RCG^HkzSڸ {[c'}5xv*Ca@P_G,5!mmDf/6IPRXNKq\\c:zYN+ZklZG-cwꚯ2 n+U~NIyBJUkͯ956Zw}znS1>O>Ϸul=~k>7:~3O1T4Y3JK5aw[IϒsK۴lN/M \ ,߆Z>|E"OmiM]~rt=r5dZxҷQ87s*=qݙ]:S=)/u^oN^7r!Rgy)s{cJ>~<7wwgRy߷gwC4s} 97Қ߶T9rqKM lxVKnPlc3 @@_  "* @k6 p BYT+$J~_939Bڂc-[pov)p x|? 3oCh6 _höӘ= xWh݃:z߁Ocpr|x`6紿K ~ɻ\p\ky͔1S"ǫԺ\oN0#{ 8K);I[} t~-9N\lW_ḥFE{K,w1f:Fyt!}-8^ZF5PcOȩe]2_⸒SM1:9RG+q5>xm;7[%s8ߣhTv}wJmeX 7nIפyMb GV|\c͚W ȥ훓1Y՜:ϸoǵIqN9bsT Xwjm[Xzc>C*&Q4&RǩAu<ES_mQ/֑7K},u'Rg2Z?ꬤ|GՖʡ}x}ze 'eO䟾!lm!xɊT1s.yƲ[[^(88*6n~~ č.} >?$텏$'gpRUP:*Ӳm(7Zԫo6QsZc;#0M쯀8 ΁`|;_p_p>C ':m!G[~ؽ7#oM\9\ 68G8 Sd5x>xHWFpg:848` -q >/RgUb3dνS>'G1p#Q~P8 r.?0|f8'3f;i;!cu&vfb?\{(w3^ci>wҪ^Dò.z;()9[{/Zٜ*,ٰ}8{u{{:oȀeVt}4Aݫ}#Mq޾ r훭Soÿ*ӳ-IQ:Sg73+2fsIݑ{Uok'kC>F.wKe}uIͥt}֑ۇ\r|]rگtNk}唫ܝKt~^7WX:(#TREE"ݕxryjst[^uuvjwU x"yS%yz 2{4|4{}+7}~9t#<[>@hChEPWHYJfMNfOpQ$TkVYg[g^vm`brehgjm^#`$Sb%& d'e()Fg*i+gk,m-n.p/r[0t1>w2J38y47{5(}6789xTjTA;3wƹ1c$M$EDQ|b.BpqxJOaMݹ ǩ  c41М!e?LMDdܐ2Q p}.p>Dv@D_@z m߁ߐ!DW|C< p<XOSx@) %q)}[5+y]wfYinvlӿGSjM*pPM2s9myDE`XPߢ.xŷ༙wWY=0#T{{f^S|Hc>%}Fb\h^֔g5cڳ:R߯5ԾǦ3""GOayF wړEB+mO84.r`zg<ޖ;7t_'s}zɝQ ~J[ڷC} nsܧ'>cs}3}jzg<7Ro%)vmS^!x1 Om w xjA3IƠ"*1Bэ.tΕ >+̳Å-8UuU]Utf,/Ic%WΦrJ+ה}h+~5e8L N5pGw 좨 8?7?mv_g<3/ p9ߡ8njqO+}Q p \Yp ǧiN`ܠ"@S&:n2ViƜSsGikjm2˔Syǩ;FaYN~̱BF̕}ߣOfI旨kkH1LhӧnLs 7@x"ym.eF9fxvWjcF"cwm$$N+g1K>ػQI{,kg5ci6N{g:>ٛ!v.~%V錄ImZٖb\r5JVXE{$5i>vQE`{|ՁUJWڭY5F>XQL/Zՠussc׶FVc[^=>Et~OTv.E߾iy﷯r跶mu;|&)x[NAgagdA J :h%H41'7\K _̟JԩSVOW5jMwűo슧}g'ݳ1j![xnA{<㱱',Y" B\c x$'H<7)ƢO5ݵvOwBavz))m/.]ґXJ\)ͧ @C !Xk n]|>}[H|H{`'># ~_WepX Խw<o{P|+Ꟃ'%\y:s1:"k{lo)΂lPn>Iy0*u%|J:Q i31p 8_P7yG;Bs;"rD}ߘ9{>('tѮ!CO.пyCi6}~ǵ{,WѾf=ŶG;~-Gk^-~KΫpv-N-qK e|gX]RXUٚ+X}aO{k,6hK|b-֔ScaǷ3Cm4קc*_LsvV~r>*L}}zTN?W;[,oj/oPLQ( |'8Cg`Lإc䛂> PekXx=rWOR#8Gt#j%fcZѥyړ5u=\i1cH*_mꩱ%J^yq#gQE+n?2UFՏaLy&QQ++wH Dtfw//Cul4+ML*49l.{ ->gy5Oյ }zMY]m}Oͥf[nk cW3V~6&=U1֯@tx- #p  N!#Gkp{p_F8O5} 7%/{3}>OطC ~<ԑͿZ}lM6` iw#yN52?`>σ` ,ЧK,iR9`=,pM4AcL-wh.667o>+ f\Q0^(79ck5eUҟ8n/'ڒjm\Ťʮu$^KD-S 1c%kf$JSb3z#jfHպ/uSjf.%^N==kO{8W;2*&CdŮuYOs[U eZUv!ݪ}W/r;Z_[s[o(]ܥMsF WL\>bN7 ]?#xKnAk^LlL8`"Hx A@ ĒXr 8g܀-g_ʟrҧNif5(A%s"5K;>`/7]_#VӖ lM&x H|Aѿ?O} _p{`wh|#wYW| ނgx k<{P-p uֶE˴%d{e5ޮ[ԟqNoҶM.q} p 8 5&Sdx2:FߎH:[`U\+;M:c<Ljq# s1Gm=`oC]\ӯ '͍ [cjk7?kV=kw*pTw Nǘwك}ǵ+5+]m\yw5W_Ż 6 P-#2qes[o|U'mF|ϴ7֜#XY^M%}ZƖ[W?=Umzi l1FUZ=gGk={\V[ܜ˘o{s5޸-wfbXw-;?B볫N|_o1 ?2׿o)wTgYu/'}izZk|"xnS1}n99 IpB[(4\Dt]Ab tCAxv탰G3>{fرB(V"cqU".y-4ߊ o18 ΃mp |W܃I _ط`CZ`;Lx vmmo=W`Kp@}=bh*%oܟhc-3)k1~͸-foPg8g \Sp"ΒU~sGN;u sθ 猩ugYFhcZγ6o1CX_?߀sni-+EO4`{O'ڝr]Yi Ex+1%vh6[nٸ&c,mZ0vٻVk>}ow6x??8k)3T-ާZ܋t+{[j^J?WoJ7]sjEzѧfm=I݋EdY\餴ԺT3ސj޲sg^fSz>ՒlSs3&!UxNA{zgvge*+ BCFcQ[;nxxWD_GXݳC'_:'}3XJ˔-SDlmr; 0K<c|; u:W(܁{/.!Ǽ[p -x ~7a0'ށckS G# q7>a,|&XkeDer Xz8okf\$G8E=i[$$hOAEO >CjC}O.m=Cj=j}mU1EOӌSv'z~KJ&9J'wM-ZF]+ZAs7U\[j$ȑ׫⓳eN :oK"sԷԤuydԚSZ&oKo~;m1m )ڭn6o|N[cln/3v_+~kkuyCwA?NujkqbZrk[RcuMglȚMv1[7W+wRgmt~)ݾuط@Z^L>G{|Sﵵ5Y} #x[jQm3f4ޒ15buAp !Bp , oD܂_NwQU]f0!\XDL:d? 8G|?e4_hv7F ~'p 3K<}^q]>5Mpl` ܢ:{lr]}>nҿM]moPFpv V c؜UƮJ|Ga 2Ss͘36~3? 6k}k͔} 9}m+Ɔ>fs7@tS*2alV[w8aqݳ߰qAv!s'HjLeV&z3svd+關Eÿge=GWg&9[,H\gZǻx5z{iNsR{xZ&GCdg=릹iViLcqLӋw?ox }4R/[umuMw[.=O[{6tm?ruTf N"xN1;_w ECPQ47. Q|W}w>n\H C9\|vB ڪ\%)ڪdBKx^h,/` <'C3 :gA9;;濡S& ރ{?`/)xƸ)o){B# u)6WX-7W{ 6ƚ]m1خ;V+&̽\؈lkX^X _x&3ρ2$gMKY=o\5}{d̺#wNk)s_R?\S66s]ޑ֬3{RNiljMreTSB " "@,@Ē!8 n)8{dóx%=rXzr\Um[RJQMۢqm5aj?`j@l=c 8y Ug|~b+ w`GEi^k\vmJh[~ihx_1֭-8}FoI*Ȏj-s5A\H?Ap9KuWL)^˪{֍ xxNAkg8ب L@1 .X޽1 |7\x*+RU=u{ιiyxu4NhrB)Jt~<`cރ/_a\`_0Ywn ]pA 7{/,7`31y ^s19%':`!`vZϸɄl_sε1}^R%S2nJO?f O*?eΈo {?_KoWX<F\c dHy{qM<5}k}?`lV9gw֯e+dϒRw2oBYRܷ7 1xKn@'A! )"{>6`g([sf*s[)94)3<<+Abl}ͨ[%-VX'Rr+圧}}K9?븞V{9Yf5;ɧLnioH|/6 ڰ{a=$>N%٢{r&ɓ YLHn/mKnMzI#QA_\9}oZ=X|L)>Ϳ\/?I.HGTq~C2&ų{>g4 GI7U::|}qVnߊc,;ZQl|4{~9/9+jGy . xMnA˞gv`~6!KBEc\lpn8 7!Z~1ҧW=:+c z3Soi_%VɘhWu^7 C#(7;  `O}A!!t~O)} ^q|]p<{ x .s[/pރ}&Gd[p>eu8cc9S8Zi~;Ҟ֗Ok"}k%bVU0m1iїXSk1ЧoB{MzVɀCWQ_79:{dofIǚkKz sjusPk)s=jWR?{Jʱ+[1($Fu*[M]Kc2;oòn%:z靖Y;ޑ&99߽&cEi~Lb^08{[]ϲcOs?ݷAjzh~ՊjjᄋZt=綵%5wO;syګ;V} fs=]7o>KtޣvbΞm|f[_7!1xjA+]3ɘLB̈Q d(BP0]K}.\|p)<'4|ܪ[{dB=FIsz˹c'o+ gp@|+px ^\^)ysGO-59~wye~`{R5.p^.RSbm/ޖ/r+yK9m2mm,6e<%s&_?-y\ X|KM5>?弡nLD#2dՊ]L78[|5bJOGzW97=↌ѻI'z_]l:}Zџcmc>}=OWZ~St>皶i?}{Z7rc=c}Ytto]{jg}YMm߻yL׹߼ڿgk{_8Ws:]g}gvyokN~M8ԬR3X-i[}}'ejfLۀ%fQlLuNl1N+kC%h{ikQ9j_~^ >ע<ӼԪm3mOW1OcYѳs)u輪eF&{=:ϷJtv 3ӹI)՜Q5k;Kea:,zͥCchg(:kͧbX#Usrޱ*h{q1F-xzY;EH>Q)|wY"vՈqZ[]F&J״[Uz=:]"EQ:YUҖCOە_sң!xNU1ۮO(D%F5H< K_A| <d|i;3jw%:&ҷf]|`OR:6dUR\j]_ҎFþz{u)b9;7TӶrMɌid6Ni?Uulom^}r?cHߋ]ڷeZ>vJ]N]KΘ=[]_oݷt?}X?_ .!x[jAOwWwOf8$%% (WW_染16|TЂ42&n!0oI";6P`vh%x^'&`Bg`0?a⾁=x Ӝ{W xKNCgee< ~MU#xjTAeLf11[ &u$Gp>}9w3:3O>=ff{͟Z(k93`DZג7IlbLK{K:1)8=_w x G v?!xA <=ڲk? 4SH'؁ԫؐ#֫o`ǿFHVw_=SUFF+1f;\/cݲ/9`U^\\o&:>Kn۸}qh:^kyhUMg똋Q_jExQFg\z͠XLD~=%hݿwn}_^ּ~f_vwf>G8r.>qQ xunAkz3c;Nb,a K.BX^#wμAƍ_Jҧh@ ZY@'vy4ԴObWdX֕-ʸyfy`O+ "O@6`7??΀_>G9x&{ ހx{`an5S og<;vsƼr>Ϩs` 8%١emv/PwC)plpe |)[5n=B*㔭Q6}AS{Mf߈UOκtƜvY2!9G{{aL 'bx_K{m+.et{oJ*Ƚw{GE~K-1b1~G]e9f߬~}t}%q.;%kE_4Kr'\UAވ WX9w=ց޹I﮳j[yqC}sKsa=_\sm}o& \.S.)W79^~B&gglwlp9#=٠gc>[c#oOOe8zNYyyFԦe_HLj$k㘲pF\k /zd&YkQN{(Ӿ,qcebY'G5Ƨ11k'G?S,>+GsۼQ~_ӸZ|_jjv*;?#ܷӬ>Iy/}o輏Eq*Y.YT,R,ށr',_zr޿<=<ڗY.i><wG#?˾>S7;e^[gMXƹΑC=,S`y6eIlQg=bSNYrM3OAu]5 u;YGB0)i[ΛĜ-g4{kIN-:~O^OEoʵ=3wˌ3yn[*{םu6c[ElGdlė1do$=$:^[OlƳjW'j ^oJlx}\.ƧEs9߈\Zkܴj#T{Rq鿨$k_mƸ-heV{P;lW3c^j4ss)/rY<|V~^obqvU9A9W~-(;FVa>ٰvVn~F QԳWE? |},ߍ"xNA{zfvvY6`E ho411# ^$$z;^x:a/S]ugzB!*<5h؏'Z3id{%Fbk'v@贴- K`c x ~_/ ! "o~ç?SKߨ'l} }>f|?gc;spȹc-S mRJ'ƢeƲ_}=t>#Q66̻+=$qUl+G*U)E~=,3KGw ވ87=q+T0C3;ݾ1vXf8-ek 0msnc{̚փu96>žm\qUrlUˑ u +91aEޫILP#Wmq7;2-5j?#>yzbV9ެƾ?ꈸ1.ŚX?2ߝelr.m@|1 2 6F_MKEk8OsOb^I"gS{~žj3jS̨ws=uY;ς=l' kc%2KΑʿ:#_W̹g}廕/=-E\SX?b5)nqU>L/߄|RϞoϤI>K9@g庲Y'✙v$4,w,WKwWKxWKPTREEܳHEAPXHhudistancetemperaturenamechemical_formularun_numbertitledatastart_timeanalysissampleinstrumentend_timemonitor2monitor1   WK (unitsmPXPMgB2 PDOS 43.37g 8K 120meV E0@240Hz T0@120Hz2001-02-07T08:54:21-0600TOFNDGSdepleted_U @ @ @ @ @ @ @G @G @G @G @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @X9 @He3 gas cylinderff33̬gfhff@@@@fff@ff@@̬@@23@ef@@ffAAff6A@AIA43SA\AhffApAyAAhfA53AA̔AAifA63AA̬AAjfA73AAAAgfA43AAAAhfA53AAAAifABBgfBB33 B BBefBB13BBB%B(Bff*B4Bff6B8B23;BffBBDB23GBIB33SBUBWBefZBaBdBfffBhB33kBmB33wByB{Bef~BffB33BffBB̈BBB33BffBBffBB̚BB23BB33BffBB̦BB̬BB33BffB33BffBB̸BB̾BB33BffBBBB33BffBBffBBBB23BB33BffBBBffBBBB23B  +WK (unitsmPPW2W @units H long_name@X^ 8 NX_class NXmonitorSNOD0pv(ȎTREEܳHEAPX8Xsourcedetectormonochromatorname 8 8 NX_class NXinstrumentTREEH`ܳHEAPhЎA"Spallation Neutron Source8X@ЌCSNODi 0w( 0 NX_classNXsource  WK (unitsmPSNOD8@0(P` x WKWKWK  HWK (unitsHzPdistancetarget_materialnamemoderatorfrequencyproton_pulsestypeH LWKPWKTREE8ܳHEAPP,XFermiLRMECS2001-02-09T14:12:53-0600eP@} 8 NX_class NXdetector    Y @units . microseconds]SNOD(@ԥ8ĤDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEE E E@ E` E E E E E E E@ E` E E E E E E E@ E` E E E E E E E@ E` E E E E E E E@ E` E E E E EE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEE E E@ E` E E E E E!E !E@!E`!E!E!E!E!E"E "E@"E`"E"E"E"E"E#E #E@#E`#E#E#E#E#E$E $E@$E`$E$E$E$E$E%E %E@%E`%E%E%E%E%E&E &E@&E`&E&E&E&E&E'E 'E@'E`'E'E'E'E'E(E (E@(E`(E(E(E(E(E)E )E@)E`)E)E)E)E)E*E *E@*E`*E*E*E*E*E+E +E@+E`+E+E+E+E+E,E ,E@,E`,E,E,E,E,E-E -E@-E`-E-E-E-E-E.E .E@.E`.E.E.E.E.E/E /E@/E`/E/E/E/E/E0E 0E@0E`0E0E0E0E0E1E 1E@1E`1E1E1E1E1E2E 2E@2E`2E2E2E2E2E3E 3E@3E`3E3E3E3E3E4E 4E@4E`4E4E4E4E4E5E 5E@5E`5E5E5E5E5E6E 6E@6E`6E6E6E6E6E7E 7E@7E`7E7E7E7E7E8E 8E@8E`8E8E8E8E8E9E 9E@9E`9E9E9E9E9E:E :E@:E`:E:E:E:E:E;E ;E@;E`;E;E;E;E;EE >E@>E`>E>E>E>E>E?E ?E@?E`?E?E?E?E?E@E @E@@E`@E@E@E@E@EAE AE@AE`AEAEAEAEAEBE BE@BE`BEBEBEBEBECE CE@CE`CECECECECEDE DE@DE`DEDEDEDEDEEE EE@EE`EEEEEEEEEEFE FE@FE`FEFEFEFEFEGE GE@GE`GEGEGEGEGEHE HE@HE`HEHEHEHEHEIE IE@IE`IEIEIEIEIEJE JE@JE`JEJEJEJEJEKE KE@KE`KEKEKEKEKELE LE@LE`LELELELELEME ME@ME`MEMEMEMEMENE NE@NE`NENENENENEOE OE@OE`OEOEOEOEOEPE PE@PE`PEPEPEPEPEQE QE@QE`QEQEQEQEQERE RE@RE`RERERERERESE SE@SE`SESESESESETE TE@TE`TETE  %xPWK (unitsmP  WK (unitsbarsPuzWK   zPY @units time_of_flightdistancegas_pressuretypepolar_angle`TREE ܳHEAPX(ԩdistanceenergytype0 8 NX_class NXchopper  WK (unitsmPSNODܬ   WK (unitsmeV 8calibration_statusNominalWK WKWK $XTREEܳHEAPX0time_of_flightdistancedata(SNODHs(p 8 NX_class NXmonitor   ԷW2WF @units N Flight [microseconds]SNOD(}||DDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDD@DDDE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEE E E@ E` E E E E E E E@ E` E E E E E E E@ E` E E E E E E E@ E` E E E E E E E@ E` E E E E EE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E`EEEEEE E@E   '/<S/Kkr  T ZV9!  TREE ܳHEAPX0time_of_flightdistancedata(   xW2W @units  Flight [microseconds]SNOD(xh  /WK (unitsmPPW2W @units H long_name@zD@zDzDzD{D@{D{D{D|D@|D|D|D}D@}D}D}D~D@~D~D~DD@DDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD D@D`DDDDDD    .K H0Q 0"Y$&'&N%!.:s BJrgqh]SU`]9DALEA:=338<''%/%  !          H long_name @target&GCOLdegreesPolar Angle [degrees]&/entry/instrument/detector/polar_anglex H long_name. @target).GCOL microsecondsTime-of-Flight [microseconds])/entry/instrument/detector/time_of_flight` @ @signalNGCOLdata @axes>hGCOLcountsNeutron Countspolar_angle:time_of_flightfHVGCOLdatapolar_angle:time_of_flight `axes nnGCOLdatatime_of_flight polar_angleGCOLcountsGCOLcountsNeutron CountsGCOLdegreesGCOLdegreesPolar Angle [degrees]GCOLdegreesPolar Angle [degrees]&/entry/instrument/detector/polar_anglexGCOL microsecondsGCOL microsecondsTime-of-Flight [microseconds]GCOL microsecondsTime-of-Flight [microseconds])/entry/instrument/detector/time_of_flight` @unitsF0GCOLcounts H long_nameXGCOLcountsMonitor 1 CountsGCOLcountsMonitor 1 CountsGCOLcountsMonitor 1 Countstime_of_flight @units 0GCOL microseconds H long_nameXGCOL microsecondsTime-of-Flight [microseconds] @units0GCOLcounts H long_nameXGCOLcountsMonitor 2 CountsGCOLcountsMonitor 2 CountsGCOLcountsMonitor 2 Countstime_of_flight @units 60GCOL microseconds H long_nameNXGCOL microsecondsTime-of-Flight [microseconds]xv @signal~GCOLdata Paxes~`GCOLtime_of_flightdataDd @signalGCOLdata Paxes`GCOLtime_of_flightdata `axes NN`GCOLtime_of_flightdataGCOLdata@Y @unitsHGCOLK  AY @units@AGCOLKGCOL&/entry/instrument/detector/polar_angleGCOL)/entry/instrument/detector/time_of_flightGCOLdataGCOLdatatime_of_flight polar_angle` @defaultfGCOLdata H HDF5_Version~ H file_time~`GCOLdata/chopper.nxs4.2.1entry1.8.22010-04-20T21:38:39-05:00XȖYؖGCOLMagnesium Diboriderun_numbertitledatastart_timeanalysissampleinstrumentend_timemonitor2monitor1definitionrun_numbertitledatastart_timeanalysissampleinstrumentend_timemonitor2monitor1chemical_formulaGCOLMgB2YGCOLMgB2 GCOL NXdirecttof././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.8847213 nexusformat-2.0.0/src/nexusformat/nexus/0000755000077000000000000000000015060352601016737 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744750925.0 nexusformat-2.0.0/src/nexusformat/nexus/__init__.py0000644000077000000000000000303014777544515021071 0ustar00rosborn# ----------------------------------------------------------------------------- # Copyright (c) 2013-2021, NeXpy Development Team. # # Author: Paul Kienzle, Ray Osborn # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING, distributed with this software. # ----------------------------------------------------------------------------- """ Python NeXus interface. NeXus is a common data format for neutron, Xray and muon science. The files contain multidimensional data elements grouped into a hierarchical structure. The data sets are self-describing, with a description of the instrument configuration including the units used as well as the data measured. NeXus data are written to HDF files and accessed in this package using h5py. Example ======= First we need to load the file structure:: import nexusformat.nexus as nx f = nx.load('file.nxs') We can examine the file structure using a number of commands:: f.attrs # Shows file name, date, user, and NeXus version print(f.tree) # Lists the entire contents of the NeXus file f.NXentry # Shows the list of scans in the file f.NXentry[0].dir() # Lists the fields in the first entry Some files can even be plotted automatically:: f.NXentry[0].NXdata[0].plot() For a complete description of the features available in this tree view of the NeXus data file, see `nx.tree`. """ from .completer import nxcompleter from .lock import NXLock, NXLockException from .tree import * import hdf5plugin ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1745963862.0 nexusformat-2.0.0/src/nexusformat/nexus/completer.py0000644000077000000000000001432315004245526021313 0ustar00rosborn# ----------------------------------------------------------------------------- # Copyright (c) 2019-2021, NeXpy Development Team. # # Author: Paul Kienzle, Ray Osborn # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING, distributed with this software. # ----------------------------------------------------------------------------- """IPython extension to allow autocompletion of NeXus object names. This modifies h5py.ipy_completer, written by Darren Dale, to accommodate the completion of NeXus paths defined as nested dictionaries. It will also autocomplete attributes at the end of a dictionary path. The NeXus objects can follow an assignment or be embedded in function arguments. Examples -------- Autocompletion works on each component of the following commands:: >>> signal = root[entry/data/signal] >>> units = root[entry/data/signal].units >>> data = NXdata(root[entry/data/signal]) """ import re try: import readline except ImportError: readline = None from string import punctuation from .tree import NeXusError, NXobject re_attr_match = re.compile(r"(.+\[.*\].*)\.(\w*)$") re_item_match = re.compile(r"""(.*)\[(?P['|"])(?!.*(?P=s))(.*)$""") re_object_match = re.compile(r"(.+?)(?:\[)") def _retrieve_obj(name, shell): """Retrieve the NeXus object at the base of the command. This filters out invalid characters not caught by the regex. Parameters ---------- name : str Name of the object to be retrieved. shell : InteractiveShell IPython shell containing the namespace to be searched. Returns ------- NXobject The NeXus object at the base of the command. Raises ------ ValueError If the object name contains a '('. """ if '(' in name: raise ValueError() return eval(name, shell.user_ns) def nxitem_completer(shell, command): """Compute possible dictionary matches for NXgroups or NXfields. This matches NeXus objects referenced as nested dictionary paths. Parameters ---------- shell : InteractiveShell IPython shell containing the namespace to be searched. command : str Command to be autocompleted Returns ------- list of str List of possible completions. """ base, item = re_item_match.split(command)[1:4:2] try: obj = _retrieve_obj(base, shell) except Exception: return [] from pathlib import PurePosixPath as PosixPath item_path = PosixPath(item) path = str(item_path.parent) if str(item_path.parent) != '.' else '' try: if path: items = (str(PosixPath(path) / name) for name in obj[path].keys()) else: items = obj.keys() except Exception: items = [] items = list(items) readline.set_completer_delims(' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?') return [i for i in items if i[:len(item)] == item] def nxattr_completer(shell, command): """Compute possible matches for NXgroup or NXfield attributes. This matches attributes at the end of NeXus dictionary references. If the entire NeXus path is defined using attribute references, then the autocompletion is handled by other completers. Parameters ---------- shell : InteractiveShell IPython shell containing the namespace to be searched. command : str Command to be autocompleted Returns ------- list of str List of possible completions. """ from IPython import get_ipython from IPython.core.error import TryNext from IPython.utils import generics base, attr = re_attr_match.split(command)[1:3] base = base.strip() try: obj = _retrieve_obj(base, shell) except Exception: return [] attrs = obj._get_completion_list() try: attrs = generics.complete_object(obj, attrs) except TryNext: pass omit__names = get_ipython().Completer.omit__names if omit__names == 1: attrs = [a for a in attrs if not a.startswith('__')] elif omit__names == 2: attrs = [a for a in attrs if not a.startswith('_')] readline.set_completer_delims(' =') return [f".{a}" for a in attrs if a[:len(attr)] == attr] def nxcompleter(shell, event): """Completer function to be loaded into IPython. Only text that ends with a valid NXobject is inspected. Parameters ---------- shell : InteractiveShell IPython shell containing the namespace to be searched. event : IPython object containing the command to be completed. Returns ------- list of str List of possible completions. Raises ------ TryNext If no completions are found. """ from IPython.core.error import TryNext if readline is None: raise NeXusError( "Install the readline module to enable tab completion") command = re.split('[ !#$%&()*+,:;<=>?@^~]', event.line)[-1].lstrip(punctuation) try: base = re_object_match.split(command)[1] except Exception: raise TryNext try: obj = shell._ofind(base).obj except AttributeError: obj = shell._ofind(base).get('obj') if not isinstance(obj, NXobject): raise TryNext try: return nxattr_completer(shell, command) except ValueError: pass try: return nxitem_completer(shell, command) except ValueError: pass return [] def load_ipython_extension(ip=None): """Load completer function into IPython. This calls the IPython set_hook function to add nxcompleter to the list of completer functions. This function disables the use of Jedi autcompletion, which is currently incompatible with the nexusformat classes. Parameters ---------- ip : InteractiveShell, optional IPython shell to be modified. By default, it is set by get_ipython(). """ from IPython import get_ipython if readline is None: raise NeXusError( "Install the readline module to enable tab completion") if ip is None: ip = get_ipython() ip.Completer.use_jedi = False ip.set_hook('complete_command', nxcompleter, re_key=r"(?:.*\=)?(?:.*\()?(?:.*,)?(.+?)\[") ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649549.0 nexusformat-2.0.0/src/nexusformat/nexus/lock.py0000644000077000000000000002022314777236515020263 0ustar00rosborn# ----------------------------------------------------------------------------- # Copyright (c) 2019-2021, NeXpy Development Team. # # Author: Paul Kienzle, Ray Osborn # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING, distributed with this software. # ----------------------------------------------------------------------------- """Module to provide a file locking mechanism to prevent data corruption.""" import errno import os import socket import time import timeit from pathlib import Path class NXLockException(Exception): LOCK_FAILED = 1 class NXLock: """Class for acquiring and releasing file-based locks. Attributes ---------- lock_file : str Name of the lock file. This has the extension `.lock` appended to the name of the locked file. pid : int Current process id. fd : int File descriptor of the opened lock file. """ def __init__(self, filename, timeout=None, check_interval=1, expiry=28800, directory=None): """Create a lock to prevent file access. This creates a lock, which can be later acquired and released. It creates a file, named `.lock`, which contains the calling process ID. Parameters ---------- filename : str Name of file to be locked. timeout : int, optional Number of seconds to wait for a prior lock to clear before raising a NXLockException, by default 60. check_interval : int, optional Number of seconds between attempts to acquire the lock, by default 1. expiry : int, optional Number of seconds after which a lock expires, by default 8*3600. Set to 0 or None to make the locks persist indefinitely. directory : str, optional Path to directory to contain lock file paths. """ from .tree import nxgetconfig self.filename = Path(filename).resolve() suffix = self.filename.suffix + '.lock' if timeout is None: timeout = nxgetconfig('lock') self.timeout = timeout self.check_interval = check_interval self.expiry = expiry if directory is None: directory = nxgetconfig('lockdirectory') if directory: try: directory = Path(directory).resolve(strict=True) except FileNotFoundError: raise NXLockException( f"Lockfile directory '{directory}' does not exist") path = self.filename.relative_to(self.filename.anchor) self.lock_file = Path(directory).joinpath('!!'.join(path.parts) ).with_suffix(suffix) else: self.lock_file = self.filename.with_suffix(suffix) self.pid = os.getpid() self.addr = f"{self.pid}@{socket.gethostname}" self.fd = None def __repr__(self): return f"NXLock('{self.filename.name}', pid={self.addr})" def acquire(self, timeout=None, check_interval=None, expiry=None): """Acquire the lock. Parameters ---------- timeout : int, optional Number of seconds to wait for a prior lock to clear before raising a NXLockException, by default `self.timeout`. check_interval : int, optional Number of seconds between attempts to acquire the lock, by default `self.check_interval`. expiry : int, optional Number of seconds after which a lock expires, by default `self.expiry`. Raises ------ NXLockException If lock not acquired before `timeout`. """ if timeout is None: timeout = self.timeout if timeout == 0: return if check_interval is None: check_interval = self.check_interval if expiry is None: expiry = self.expiry timeoutend = timeit.default_timer() + timeout initial_attempt = True while timeoutend > timeit.default_timer(): try: # Attempt to create the lockfile. If it already exists, # then someone else has the lock and we need to wait self.fd = os.open(self.lock_file, os.O_CREAT | os.O_EXCL | os.O_RDWR) open(self.lock_file, 'w').write(self.addr) os.chmod(self.lock_file, 0o777) break except OSError as e: # Only catch if the lockfile already exists if e.errno != errno.EEXIST: raise # Remove the lockfile if it is older than one day elif initial_attempt and expiry: if self.is_stale(expiry=expiry): self.clear() initial_attempt = False time.sleep(check_interval) # Raise an error if we had to wait for too long else: self.fd = None raise NXLockException( f"'{self.filename}' is currently locked by an external process" ) def release(self): """Release the lock. Note ==== This will only work if the lock was created by the current process. """ if self.fd is not None: os.close(self.fd) try: os.remove(self.lock_file) except FileNotFoundError: pass self.fd = None @property def locked(self): """Return True if the current process has locked the file.""" if not self.lock_file.exists(): self.fd = None return self.fd is not None def clear(self): """Clear the lock even if created by another process. This will either release a lock created by the current process or remove the lock file created by an external process. Note ==== This is used to clear stale locks caused by a process that terminated prematurely. It should be used with caution. """ if self.fd is not None: self.release() else: try: os.remove(self.lock_file) except FileNotFoundError: pass def wait(self, timeout=None, check_interval=None): """Wait until an existing lock is cleared. This is for use in processes checking for external locks. Parameters ---------- timeout : int, optional Number of seconds to wait for a prior lock to clear before raising a NXLockException, by default `self.timeout`. check_interval : int, optional Number of seconds between attempts to acquire the lock, by default `self.check_interval`. Raises ------ NXLockException If lock not cleared before `timeout`. """ if self.lock_file.exists(): if timeout is None: timeout = self.timeout if check_interval is None: check_interval = self.check_interval timeoutend = timeit.default_timer() + timeout while timeoutend > timeit.default_timer(): time.sleep(check_interval) if not self.lock_file.exists(): break else: raise NXLockException(f"'{self.filename}' is currently locked " "by an external process") return def is_stale(self, expiry=None): """Return True if the lock file is older than one day. If the lock file has been cleared before this check, the function returns False to enable another attempt to acquire it. """ if expiry is None: expiry = self.expiry try: return ((time.time() - self.lock_file.stat().st_mtime) > expiry) except FileNotFoundError: return False def __enter__(self): return self.acquire() def __exit__(self, *args): self.release() def __del__(self): self.release() ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/nexus/plot.py0000644000077000000000000003220214777236751020313 0ustar00rosborn# ----------------------------------------------------------------------------- # Copyright (c) 2013-2025, NeXpy Development Team. # # Author: Paul Kienzle, Ray Osborn # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING, distributed with this software. # ----------------------------------------------------------------------------- """Module to provide standard Matplotlib plotting to the NeXus Python API.""" import copy import numpy as np from . import NeXusError, NXfield def centers(axis, dimlen): """Return the centers of the axis bins. This works regardless of whether the axis consists of bin boundaries, i.e, `dimlen = len(axis) + 1``, or centers, i.e., `dimlen = len(axis)`. Parameters ---------- axis : ndarray Array containing the axis values. dimlen : int Length of corresponding data dimension. Returns ------- ndarray Array of bin centers with a size of dimlen. """ ax = axis.astype(np.float64) if ax.shape[0] == dimlen+1: return (ax[:-1] + ax[1:])/2 else: assert ax.shape[0] == dimlen return ax def boundaries(axis, dimlen): """Return the axis bin boundaries. This works regardless of whether the axis consists of bin boundaries, i.e, dimlen = len(axis) + 1, or centers, i.e., dimlen = len(axis). Parameters ---------- axis : ndarray Array containing the axis values. dimlen : int Length of corresponding data dimension. Returns ------- ndarray Array of bin boundaries with a size of dimlen + 1. """ ax = axis.astype(np.float64) if ax.shape[0] == dimlen: start = ax[0] - (ax[1] - ax[0])/2 end = ax[-1] + (ax[-1] - ax[-2])/2 return np.concatenate((np.atleast_1d(start), (ax[:-1] + ax[1:])/2, np.atleast_1d(end))) else: assert ax.shape[0] == dimlen + 1 return ax def label(field): """Return a label for a data field suitable for use on a graph axis. This returns the attribute 'long_name' if it exists, or the field name, followed by the units attribute if it exists. Parameters ---------- field : NXfield NeXus field used to construct the label. Returns ------- str Axis label. """ if 'long_name' in field.attrs: return field.long_name elif 'units' in field.attrs: return f"{field.nxname} ({field.units})" else: return field.nxname class PyplotPlotter: """Matplotlib plotter class for 1D or 2D NeXus data. When the nexusformat package is used within NeXpy, plots are produced by calling the NXPlotView class function, 'plot'. This provides a function with the same call signature for use outside NeXpy. """ def plot(self, data_group, fmt=None, xmin=None, xmax=None, ymin=None, ymax=None, vmin=None, vmax=None, **kwargs): """Plot the NXdata group. Parameters ---------- data_group : NXdata NeXus group containing the data to be plotted. fmt : str, optional Formatting options that are compliant with PyPlot, by default None xmin : float, optional Minimum x-boundary, by default None xmax : float, optional Maximum x-boundary, by default None ymin : float, optional Minimum y-boundary, by default None ymax : float, optional Maximum y-boundary, by default None vmin : float, optional Minimum signal value for 2D plots, by default None vmax : float, optional Maximum signal value for 2D plots, by default None **kwargs : dict Options used to customize the plot. Note ---- If the qualitative color map, 'tab10', is specified as a keyword argument, the color scale is chosen so that all the integer values are centered on each color band, if the maximum intensity is less than 10. """ try: import matplotlib.pyplot as plt except ImportError: raise NeXusError( "Default plotting package (matplotlib) not available.") over = kwargs.pop("over", False) image = kwargs.pop("image", False) log = kwargs.pop("log", False) logx = kwargs.pop("logx", False) logy = kwargs.pop("logy", False) origin = kwargs.pop("origin", "lower") aspect = kwargs.pop("aspect", "auto") regular = kwargs.pop("regular", False) cmap = kwargs.pop("cmap", "viridis") colorbar = kwargs.pop("colorbar", True) interpolation = kwargs.pop("interpolation", "nearest") bad = kwargs.pop("bad", "darkgray") weights = kwargs.pop("weights", False) ax = kwargs.pop("ax", None) signal = data_group.nxsignal if signal.ndim > 2 and not image: raise NeXusError( "Can only plot 1D and 2D data - please select a slice") errors = data_group.nxerrors title = data_group.nxtitle coordinates = data_group.nxcoordinates # Provide a new view of the data if there is a dimension of length 1 if len(coordinates) > 0: data = signal.nxdata else: data, axes = (signal.nxdata.reshape(data_group.plot_shape), data_group.plot_axes) if weights and data_group.nxweights: with np.errstate(divide='ignore'): w = data_group.nxweights.nxdata.reshape(data_group.plot_shape) data = np.where(w > 0, data/w, 0.0) isinteractive = plt.isinteractive() plt.ioff() try: if over: plt.autoscale(False) else: plt.autoscale(True) if ax is None: plt.clf() if ax: plt.sca(ax) else: ax = plt.gca() # One-dimensional Plot if len(data.shape) == 1 and len(coordinates) == 0: if 'marker' in kwargs: fmt = kwargs.pop('marker') else: fmt = 'o' if 'units' in signal.attrs: if not errors and signal.attrs['units'] == 'counts': errors = NXfield(np.sqrt(data)) if errors: ebars = errors.nxdata ax.errorbar(centers(axes[0], data.shape[0]), data, ebars, fmt=fmt, **kwargs) else: ax.plot(centers(axes[0], data.shape[0]), data, fmt, **kwargs) if not over: if xmin is not None: ax.set_xlim(left=xmin) if xmax is not None: ax.set_xlim(right=xmax) if ymin is not None: ax.set_ylim(bottom=ymin) if ymax is not None: ax.set_ylim(top=ymax) if logx: ax.set_xscale('log') if log or logy: ax.set_yscale('log') plt.xlabel(label(axes[0])) plt.ylabel(label(signal)) plt.title(title) if len(data.shape) == 1 and len(coordinates) > 0: if 'size' in kwargs: s = kwargs.pop('size') else: s = 50 if len(coordinates) == 1: x = coordinates[0].nxdata ax.scatter(x, data, s=s, **kwargs) elif len(coordinates) == 2: y = coordinates[0].nxdata x = coordinates[1].nxdata ax.scatter(x, y, c=data, s=s, **kwargs) else: raise NeXusError("Cannot plot more than two coordinates.") if not over: if xmin is not None: ax.set_xlim(left=xmin) if xmax is not None: ax.set_xlim(right=xmax) if ymin is not None: ax.set_ylim(bottom=ymin) if ymax is not None: ax.set_ylim(top=ymax) if logx: ax.set_xscale('log') if log or logy: ax.set_yscale('log') if len(coordinates) == 1: plt.xlabel(label(coordinates[0])) plt.ylabel(label(signal)) else: plt.xlabel(label(coordinates[1])) plt.ylabel(label(coordinates[0])) plt.title(title) # Two dimensional plot else: from matplotlib.colors import LogNorm, Normalize if image: x = boundaries(axes[-1], data.shape[-2]) y = boundaries(axes[-2], data.shape[-3]) xlabel, ylabel = label(axes[-1]), label(axes[-2]) else: x = boundaries(axes[-1], data.shape[-1]) y = boundaries(axes[-2], data.shape[-2]) xlabel, ylabel = label(axes[-1]), label(axes[-2]) if not vmin: vmin = np.nanmin(data[data > -np.inf]) if not vmax: vmax = np.nanmax(data[data < np.inf]) if image: im = ax.imshow(data, origin='upper', **kwargs) ax.set_aspect('equal') else: from packaging.version import Version from matplotlib import __version__ as mplversion if log: vmin = max(vmin, 0.01) vmax = max(vmax, 0.01) kwargs["norm"] = LogNorm(vmin, vmax) else: kwargs["norm"] = Normalize(vmin, vmax) if Version(mplversion) >= Version('3.5.0'): from matplotlib import colormaps cm = copy.copy(colormaps[cmap]) else: from matplotlib.cm import get_cmap cm = copy.copy(get_cmap(cmap)) cm.set_bad(bad, 1.0) if regular: extent = (x[0], x[-1], y[0], y[-1]) kwargs['interpolation'] = interpolation im = ax.imshow(data, origin=origin, extent=extent, cmap=cm, **kwargs) else: im = ax.pcolormesh(x, y, data, cmap=cm, **kwargs) ax.set_xlim(x[0], x[-1]) ax.set_ylim(y[0], y[-1]) if aspect == 'equal': try: if 'scaling_factor' in axes[-1].attrs: _xscale = axes[-1].attrs['scaling_factor'] else: _xscale = 1.0 if 'scaling_factor' in axes[-2].attrs: _yscale = axes[-2].attrs['scaling_factor'] else: _yscale = 1.0 aspect = float(_yscale / _xscale) except Exception as error: raise NeXusError(str(error)) ax.set_aspect(aspect) if colorbar: cb = plt.colorbar(im) if cmap == 'tab10': cmin, cmax = im.get_clim() if cmax - cmin <= 9: if cmin == 0: im.set_clim(-0.5, 9.5) elif cmin == 1: im.set_clim(0.5, 10.5) if Version(mplversion) >= Version('3.5.0'): cb.ax.set_ylim(cmin-0.5, cmax+0.5) cb.set_ticks(range(int(cmin), int(cmax)+1)) if xmin is not None: ax.set_xlim(left=xmin) if xmax is not None: ax.set_xlim(right=xmax) if ymin is not None: if image: ax.set_ylim(top=ymin) else: ax.set_ylim(bottom=ymin) if ymax is not None: if image: ax.set_ylim(bottom=ymax) else: ax.set_ylim(top=ymax) plt.xlabel(xlabel) plt.ylabel(ylabel) plt.title(title) if isinteractive: plt.pause(0.001) plt.show(block=False) else: plt.show() finally: if isinteractive: plt.ion() plotview = PyplotPlotter() ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1755016116.0 nexusformat-2.0.0/src/nexusformat/nexus/tree.py0000644000077000000000000107743415046665664020314 0ustar00rosborn#!/usr/bin/env python # ----------------------------------------------------------------------------- # Copyright (c) 2013-2025, NeXpy Development Team. # # Author: Paul Kienzle, Ray Osborn # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING, distributed with this software. # ----------------------------------------------------------------------------- """ Module to read, write, analyze, manipulate, and visualize NeXus data. This is designed to accomplish two goals: 1. To provide convenient access to existing data contained in NeXus files. 2. To enable new NeXus data to be created and manipulated interactively. These goals are achieved by mapping hierarchical NeXus data structures directly into Python objects, which represent NeXus groups, fields, or attributes. Entries in a group are referenced as a dictionary containing other groups or fields. The entire data hierarchy can be referenced at any time, whether the NeXus data has been loaded from an existing NeXus file or created dynamically within the Python session. This provides a natural scripting interface for the creation, manipulation, and visualization of NeXus data. Example 1: Loading a NeXus file ------------------------------- The following commands loads NeXus data from a file, displays the contents as a tree, and then accesses individual data items. Note that all the classes and functions returned by the wildcard import in the example start with 'NX' or 'nx' so name clashes with other modules are unlikely. >>> from nexusformat.nexus import * >>> a=nxload('sns/data/ARCS_7326.nxs') >>> print(a.tree) root:NXroot @HDF5_Version = 1.8.2 @NeXus_version = 4.2.1 @file_name = ARCS_7326.nxs @file_time = 2010-05-05T01:59:25-05:00 entry:NXentry data:NXdata data = float32(631x461x4x825) @axes = rotation_angle:tilt_angle:sample_angle:time_of_flight @signal = 1 rotation_angle = float32(632) @units = degree sample_angle = [ 210. 215. 220. 225. 230.] @units = degree tilt_angle = float32(462) @units = degree time_of_flight = float32(826) @units = microsecond run_number = 7326 sample:NXsample pulse_time = 2854.94747365 @units = microsecond . . . >>> a['entry/run_number'] NXfield(7326) The tree returned from :func:`nxload()` has an entry for each group, field and attribute. You can traverse the hierarchy using the names of the groups. For example, tree['entry/instrument/detector/distance'] is an example of a field containing the distance to each pixel in the detector. Entries can also be referenced by NXclass name, such as ``tree.NXentry[0].instrument``. Since there may be multiple entries of the same NeXus class, the ``NXclass`` attribute returns a (possibly empty) list. The :func:`nxload()` and :func:`nxsave()` functions are implemented using the :class:`NXFile` class, a subclass of :class:`h5py.File`. Example 2: Creating a NeXus file dynamically -------------------------------------------- The second example shows how to create NeXus data dynamically and saves it to a file. The data are first created as NumPy arrays >>> import numpy as np >>> x=y=np.linspace(0,2*np.pi,101) >>> X,Y=np.meshgrid(y,x) >>> z=np.sin(X)*np.sin(Y) Then, a NeXus data group is created and the data inserted to produce a NeXus-compliant structure that can be saved to a file >>> root=NXroot(NXentry()) >>> print(root.tree) root:NXroot entry:NXentry >>> root.entry.data=NXdata(z,[x,y]) Note that in this example, we have used the alternative attribute form for accessing objects in the hierarchical structure, *i.e.*, `root.entry.data` instead of `root['entry/data']`. The attribute form is faster to type interactively, but the dictionary form is safer for scripts when there is a chance of clashes with class attributes or methods. Additional metadata can be inserted before saving the data to a file. >>> root.entry.sample=NXsample() >>> root.entry.sample.temperature = 40.0 >>> root.entry.sample.temperature.units = 'K' >>> root.save('example.nxs') :class:`NXfield` objects have much of the functionality of NumPy arrays. They may be used in simple arithmetic expressions with other NXfields, NumPy arrays or scalar values and will be cast as ndarray objects if used as arguments in NumPy modules. >>> x=nx.NXfield(np.linspace(0,10.0,11)) >>> x NXfield([ 0. 1. 2. ..., 8. 9. 10.]) >>> x + 10 NXfield([ 10. 11. 12. ..., 18. 19. 20.]) >>> np.sin(x) array([ 0. , 0.84147098, 0.90929743, ..., 0.98935825, 0.41211849, -0.54402111]) If the arithmetic operation is assigned to a NeXus group attribute, it will be automatically cast as a valid :class:`NXfield` object with the type and shape determined by the NumPy array type and shape. >>> entry.data.result = np.sin(x) >>> entry.data.result NXfield([ 0. 0.84147 0.90929 ..., 0.98935 0.41211 -0.54402]) >>> entry.data.result.dtype, entry.data.result.shape (dtype('float64'), (11,)) Notes ----- Properties of the entry in the tree are referenced by attributes that depend on the object type, different nx attributes may be available. Objects (:class:`NXobject`) have attributes shared by both groups and fields:: * nxname object name * nxclass object class for groups, 'NXfield' for fields * nxgroup group containing the entry, or None for the root * attrs dictionary of NeXus attributes for the object Fields (:class:`NXfield`) have attributes for accessing data: * shape dimensions of data in the field * dtype data type * nxdata data in the field Groups (:class:`NXgroup`) have attributes for accessing children:: * entries dictionary of entries within the group * component('nxclass') return group entries of a particular class * dir() print the list of entries in the group * tree return the list of entries and subentries in the group * plot() plot signal and axes for the group, if available Linked fields or groups (:class:`NXlink`) have attributes for accessing the link:: * nxlink reference to the linked field or group NeXus attributes (:class:`NXattr`) have a type and a value only:: * dtype attribute type * nxdata attribute data There is a subclass of :class:`NXgroup` for each group class defined by the NeXus standard, so it is possible to create an :class:`NXgroup` of NeXus :class:`NXsample` directly using: >>> sample = NXsample() The default group name will be the class name following the 'NX', so the above group will have an nxname of 'sample'. However, this is overridden by the attribute name when it is assigned as a group attribute, e.g., >>> entry['sample1'] = NXsample() >>> entry['sample1'].nxname sample1 You can traverse the tree by component class instead of component name. Since there may be multiple components of the same class in one group you will need to specify which one to use. For example:: tree.NXentry[0].NXinstrument[0].NXdetector[0].distance references the first detector of the first instrument of the first entry. Unfortunately, there is no guarantee regarding the order of the entries, and it may vary from call to call, so this is mainly useful in iterative searches. """ __all__ = ['NXFile', 'NXobject', 'NXfield', 'NXgroup', 'NXattr', 'NXvirtualfield', 'NXlink', 'NXlinkfield', 'NXlinkgroup', 'NeXusError', 'nxgetconfig', 'nxsetconfig', 'nxgetcompression', 'nxsetcompression', 'nxgetencoding', 'nxsetencoding', 'nxgetlock', 'nxsetlock', 'nxgetlockdirectory', 'nxsetlockdirectory', 'nxgetlockexpiry', 'nxsetlockexpiry', 'nxgetmaxsize', 'nxsetmaxsize', 'nxgetmemory', 'nxsetmemory', 'nxgetrecursive', 'nxsetrecursive', 'nxclasses', 'nxload', 'nxopen', 'nxsave', 'nxduplicate', 'nxdir', 'nxconsolidate', 'nxdemo', 'nxversion'] import numbers import os import re import sys import warnings from copy import copy, deepcopy from pathlib import Path from pathlib import PurePosixPath as PurePath import h5py as h5 import numpy as np from .. import __version__ as nxversion from .lock import NXLock, NXLockException from .utils import get_base_classes, remove_deprecations warnings.simplefilter('ignore', category=FutureWarning) # Default configuration parameters. NX_CONFIG = {'compression': 'gzip', 'definitions': None, 'encoding': 'utf-8', 'lock': 0, 'lockdirectory': None, 'lockexpiry': 8 * 3600, 'maxsize': 10000, 'memory': 2000, 'recursive': False} # These are overwritten below by environment variables if defined. # List of NeXus base classes nxclasses = get_base_classes() string_dtype = h5.special_dtype(vlen=str) np.set_printoptions(threshold=5, precision=6) def text(value): """ Return a unicode string. Parameters ---------- value : str or bytes String or byte array to be converted. Returns ------- str Converted unicode string Notes ----- If the argument is a byte array, the function will decode the array using the encoding specified by NX_ENCODING, which is initially set to the system's default encoding, usually 'utf-8'. If this generates a UnicodeDecodeError exception, an alternate encoding is tried. Null characters are removed from the return value. """ if isinstance(value, np.ndarray) and value.shape == (1,): value = value[0] if isinstance(value, bytes): try: _text = value.decode(NX_CONFIG['encoding']) except UnicodeDecodeError: if NX_CONFIG['encoding'] == 'utf-8': _text = value.decode('latin-1') else: _text = value.decode('utf-8') else: _text = str(value) return _text.replace('\x00', '').rstrip() def is_text(value): """ Return True if the value represents text. Parameters ---------- value : str or bytes Value to be checked. Returns ------- bool True if the value is a string or bytes array. """ if isinstance(value, bytes) or isinstance(value, str): return True else: return False def is_string_dtype(dtype): """ Return True if the dtype corresponds to a string type. Parameters ---------- dtype : np.dtype NumPy data type to be tested. Returns ------- bool True if the dtype corresponds to a string type. """ return dtype == string_dtype or dtype.kind == 'S' or dtype.kind == 'U' def is_iterable(obj): """ Return True if the object is a list or a tuple. Parameters ---------- obj : list or tuple Object to be tested. Returns ------- bool True if the object is a list or a tuple. """ return isinstance(obj, list) or isinstance(obj, tuple) def format_float(value, width=np.get_printoptions()['precision']): """ Return a float value with the specified width. This function results in a more compact scientific notation where relevant. """ text = "{:.{width}g}".format(value, width=width) return re.sub(r"e(-?)0*(\d+)", r"e\1\2", text.replace("e+", "e")) def natural_sort(key): """ Sort a list of strings containing numbers in natural order. This function is used to customize the sorting of lists of strings. For example, it ensures that 'label_10' follows 'label_9' after sorting. Parameters ---------- key : str String in the list to be sorted. Returns ------- list List of components splitting embedded numbers as integers. """ return [int(t) if t.isdigit() else t for t in re.split(r'(\d+)', key)] class NeXusError(Exception): """NeXus Error""" pass class NXFile: """ Interface for input/output to NeXus files using h5py. Usage:: file = NXFile(filename, ['r','rw','w']) - open the NeXus file root = file.readfile() - read the structure of the NeXus file. Returns a NeXus tree. file.writefile(root) - write a NeXus tree to the file. Example ------- nx = NXFile('REF_L_1346.nxs','r') root = nx.readfile() for entry in root.NXentry: process(entry) copy = NXFile('modified.nxs','w') copy.writefile(root) Note that the large datasets are not loaded immediately. Instead, the when the data set is requested, the file is reopened, the data read, and the file closed again. """ def __init__(self, name, mode='r', recursive=None, **kwargs): """ Open an HDF5 file for reading and writing NeXus files. This creates a h5py File instance that is used for all subsequent input and output. Unlike h5py, where a closed file is no longer accessible, the NXFile instance is persistent, and can be used to with a context manager to ensure that all file operations are completed and the h5py File is released. A file locking mechanism is optionally available to prevent corruption of the file when being accessed by multiple processes. Parameters ---------- name : str Name of the HDF5 file. mode : {'r', 'rw', 'r+', 'w', 'w-', 'a'}, optional Read/write mode of the HDF5 file, by default 'r'. These all have the same meaning as their h5py counterparts, apart from 'rw', which is equivelent to 'r+'. After creating and/or opening the file, the mode is set to 'r' or 'rw' for remaining operations. recursive : bool, optional If True, the file tree is loaded recursively, by default True. If False, only the entries in the root group are read. Other group entries will be read automatically when they are referenced. **kwargs Keyword arguments to be used when opening the h5py File object. """ self.h5 = h5 self.name = str(name) self._file = None self._filename = str(Path(name).resolve()) self._filedir = str(Path(self._filename).parent) self._lock = NXLock(self._filename, timeout=NX_CONFIG['lock'], expiry=NX_CONFIG['lockexpiry'], directory=NX_CONFIG['lockdirectory']) self._lockdir = self.lock_file.parent self._path = '/' self._root = None self._with_count = 0 if recursive is None: self.recursive = NX_CONFIG['recursive'] else: self.recursive = recursive if mode is None: mode = 'r' elif mode == 'w5': mode = 'w' elif mode == 'w4' or mode == 'wx': raise NeXusError("Only HDF5 files supported") elif mode not in ['r', 'rw', 'r+', 'w', 'a', 'w-', 'x']: raise NeXusError("Invalid file mode") if not os.access(self._filedir, os.R_OK): raise NeXusError(f"'{self._filedir}/' is not accessible") elif (self._lock.timeout > 0 and not os.access(self._lockdir, os.W_OK)): raise NeXusError( f"Not permitted to create a lock file in '{self._lockdir}'") file_exists = Path(self._filename).exists() if mode in ['w', 'a', 'w-', 'x']: if file_exists: if mode == 'w-' or mode == 'x': raise NeXusError(f"'{self._filename}' already exists") elif not os.access(self._filename, os.W_OK): raise NeXusError( f"Not permitted to write to '{self._filename}'") elif mode == 'a': mode = 'rw' elif not os.access(self._filedir, os.W_OK): raise NeXusError( f"Not permitted to create files in '{self._filedir}'") else: if not file_exists: raise NeXusError(f"'{self._filename}' does not exist") elif not os.access(self._filename, os.R_OK): raise NeXusError(f"Not permitted to read '{self._filename}'") elif (mode != 'r' and not os.access(self._filename, os.W_OK)): raise NeXusError( f"Not permitted to write to '{self._filename}'") try: self.acquire_lock() if mode in ['r', 'r+', 'rw']: self._file = self.h5.File(self._filename, 'r', **kwargs) else: self._file = self.h5.File(self._filename, mode, **kwargs) if not file_exists: self._rootattrs() self._file.close() except NeXusError as error: raise error except Exception as error: raise NeXusError(str(error)) finally: self.release_lock() if mode == 'r': self._mode = 'r' else: self._mode = 'rw' def __repr__(self): return ( f'') def __getattr__(self, name): """Return an attribute of the file if not defined by NXFile""" return getattr(self.file, name) def __getitem__(self, key): """Return an object from the NeXus file using its path.""" return self.file.get(key) def __setitem__(self, key, value): """Set the value of an object in the file.""" self.file[key] = value def __delitem__(self, key): """Delete an object from the file. """ del self.file[key] def __contains__(self, key): """Implement 'k in d' test for entries in the file.""" return self.file.__contains__(key) def __enter__(self): """ Open and, optionally, lock a file for multiple operations. Returns ------- NXFile Current NXFile instance. """ if self._with_count == 0: self.open() self._with_count += 1 return self def __exit__(self, *args): """Close the NeXus file and, if necessary, release the lock.""" if self._with_count == 1: self.close() self._with_count -= 1 def __del__(self): """Close the file and delete the NXFile instance.""" self.close() self.release_lock() @property def root(self): """Return the root group of the NeXus file.""" return self._root @property def mtime(self): """Return the modification time of the NeXus file.""" return Path(self._filename).stat().st_mtime @property def lock(self): """ Return the NXLock instance to be used in file locking. The parameter, `NX_LOCK`, defines the default timeout in seconds of attempts to acquire the lock. If it is set to 0, the NXFile object is not locked by default. The `lock` property can be set to turn on file locking, either by setting it to a new timeout value or by setting it to `True`, in which case a default timeout of 10 seconds is used. Notes ----- The default value of `NX_LOCK` can be set using the `nxsetlock` function. Returns ------- NXLock Instance of the file lock. """ return self._lock @lock.setter def lock(self, value): if self._lock is None: self._lock = NXLock(self._filename, timeout=NX_CONFIG['lock'], expiry=NX_CONFIG['lockexpiry'], directory=NX_CONFIG['lockdirectory']) if value is False or value is None or value == 0: self._lock.timeout = 0 else: if value is True: if NX_CONFIG['lock']: timeout = NX_CONFIG['lock'] else: timeout = 10 else: timeout = value self._lock.timeout = timeout @property def locked(self): """Return True if a lock is active in the current process.""" return self._lock is not None and self._lock.locked @property def lock_file(self): """Return the name of the file used to establish the lock.""" if self._lock is None: self._lock = NXLock(self._filename, timeout=NX_CONFIG['lock'], expiry=NX_CONFIG['lockexpiry'], directory=NX_CONFIG['lockdirectory']) return self._lock.lock_file def acquire_lock(self, timeout=None): """ Acquire the file lock. This uses the NXLock instance returned by `self.lock`. Parameters ---------- timeout : int, optional Timeout for attempts to acquire the lock, by default None. """ if self.locked: return if self._lock is None: if timeout is not None: self.lock = timeout elif NX_CONFIG['lock']: self.lock = NX_CONFIG['lock'] elif self.is_locked(): self.lock = True if self._lock is None: return try: self._lock.acquire() except PermissionError: raise NeXusError("Denied permission to create the lock file") except NXLockException as error: raise NeXusError(str(error)) def release_lock(self): """Release the lock acquired by the current process.""" if self.locked: self._lock.release() def wait_lock(self, timeout=True): """ Wait for a lock created by an external process to be cleared. Parameters ---------- timeout : bool or int, optional The value, in seconds, of the time to wait. If set to `True`, a default value of 10 seconds is used. """ self.lock = timeout NXLock(self._filename, timeout=timeout).wait() def clear_lock(self, timeout=True): """ Clear the lock whether created by this or another process. Notes ----- Since the use of this function implies that another process is accessing this file, file locking is turned on for future input/output. The `timeout` value applies to future access. The existing lock is cleared immediately. Parameters ---------- timeout : bool or int, optional The value, in seconds, of the time to wait for future file locks. If set to `True`, a default value of 10 seconds is used. """ if self.is_locked(): self.lock = timeout self._lock.clear() def is_locked(self): """Return True if a lock file exists for this NeXus file.""" return Path(self.lock_file).exists() def get(self, *args, **kwargs): """Return the value defined by the `h5py` object path.""" return self.file.get(*args, **kwargs) @property def file(self): """The h5py File object, which is opened if necessary.""" if not self.is_open(): self.open() return self._file def open(self, **kwargs): """Open the NeXus file for input/output.""" if not self.is_open(): self.acquire_lock() if self._mode == 'rw': self._file = self.h5.File(self._filename, 'r+', **kwargs) else: self._file = self.h5.File(self._filename, self._mode, **kwargs) if self._root: self._root._mtime = self.mtime self.nxpath = '/' def close(self): """ Close the NeXus file. Notes ----- The file modification time of the root object is updated. """ if self.is_open(): self._file.close() self.release_lock() try: self._root._mtime = self.mtime except Exception: pass def is_open(self): """Return True if the file is open for input/output in h5py.""" if self._file is not None: return True if self._file.id.valid else False else: return False def is_accessible(self): """Return True if a lock file exists for this NeXus file.""" return Path(self.lock_file).exists() def readfile(self): """ Read the NeXus file and return a tree of NeXus objects. The hierarchy is traversed using `nxpath` to record the current location within the file. It is initially set to the root object, *i.e.*, '/'. Notes ----- This lazily loads all the file objects, *i.e.*, the values stored in large dataset arrays are not read until they are needed. """ _mode = self._mode self._mode = 'r' self.nxpath = '/' root = self._readgroup('root') root._group = None root._file = self root._filename = self._filename root._mode = self._mode = _mode root._file_modified = False self._root = root return root def _readattrs(self): """ Read an object's attributes Returns ------- dict Dictionary of attribute values. """ item = self.get(self.nxpath) if item is not None: attrs = {} for key in item.attrs: try: attrs[key] = item.attrs[key] except Exception: attrs[key] = None return attrs else: return {} def _readchildren(self): """ Read the children of the group defined by the current path. Returns ------- list of NXfield or NXgroup The objects contained within the current group. """ children = {} items = self[self.nxpath].items() for name, value in items: self.nxpath = self.nxpath + '/' + name if isinstance(value, self.h5.Group): children[name] = self._readgroup( name, recursive=self.recursive) elif isinstance(value, self.h5.Dataset): children[name] = self._readdata(name) else: _link = self._readlink(name) if _link: children[name] = _link self.nxpath = self.nxparent return children def _readgroup(self, name, recursive=True): """ Return the group at the current path. Parameters ---------- name : str Name of the group. recursive : bool, optional If True, the group children will be loaded into the group dictionary, by default True. Returns ------- NXgroup or NXlinkgroup Group or link defined by the current path. """ attrs = self._readattrs() nxclass = self._getclass(attrs.pop('NX_class', 'NXgroup')) if nxclass == 'NXgroup' and self.nxpath == '/': nxclass = 'NXroot' _target, _filename, _abspath, _soft = self._getlink() if _target is not None: group = NXlinkgroup(nxclass=nxclass, name=name, target=_target, file=_filename, abspath=_abspath, soft=_soft) else: group = NXgroup(nxclass=nxclass, name=name, attrs=attrs) if recursive: children = self._readchildren() group._entries = {} for child in children: group._entries[child] = children[child] children[child]._group = group group._changed = True return group def _readdata(self, name): """ Read a dataset and return the field at the current path. Parameters ---------- name : str Name of the field or link. Returns ------- NXfield, NXvirtualfield, or NXlinkfield Field or link defined by the current path. """ _target, _filename, _abspath, _soft = self._getlink() if _target is not None: return NXlinkfield(name=name, target=_target, file=_filename, abspath=_abspath, soft=_soft) else: field = self.get(self.nxpath) # Read in the data if it's not too large if _getsize(field.shape) < 1000: # i.e., less than 1k dims try: value = self.readvalue(self.nxpath) except Exception: value = None else: value = None attrs = self.attrs if 'NX_class' in attrs and text(attrs['NX_class']) == 'SDS': attrs.pop('NX_class') if field.is_virtual: sources = field.virtual_sources() target = sources[0].dset_name files = [s.file_name for s in sources] return NXvirtualfield(target, files, name=name, attrs=attrs, shape=field.shape[1:], dtype=field.dtype, create_vds=False) else: return NXfield(value=value, name=name, dtype=field.dtype, shape=field.shape, attrs=attrs) def _readlink(self, name): """ Read an object that is an undefined link at the current path. This is usually an external link to a non-existent file. It can also be a link to an external file that has not yet been resolved. Parameters ---------- name : str Name of the object link. Returns ------- NXlink Link defined by the current path. """ _target, _filename, _abspath, _soft = self._getlink() if _target is not None: return NXlink(name=name, target=_target, file=_filename, abspath=_abspath, soft=_soft) else: return None def _getclass(self, nxclass): """ Return a valid NeXus class from the object attribute. This function converts the `NX_class` attribute of an object in the NeXus file and converts it to a valid string. If no attribute is found, the class is set to 'NXgroup'. Parameters ---------- nxclass : str Attribute defining the object class. Returns ------- str Valid NeXus class. """ nxclass = text(nxclass) if nxclass is None: return 'NXgroup' else: return nxclass def _getlink(self, path=None): """ Return the link target path and filename. Returns ------- str, str, bool Link path, filename, and boolean that is True if an absolute file path is given. """ current_path = self.nxpath if path is not None: self.nxpath = path _target, _filename, _abspath, _soft = None, None, False, False if self.nxpath != '/': _link = self.get(self.nxpath, getlink=True) if isinstance(_link, h5.ExternalLink): _target, _filename = _link.path, _link.filename _abspath = Path(_filename).is_absolute() elif isinstance(_link, h5.SoftLink): _target = _link.path _soft = True elif 'target' in self.attrs: _target = text(self.attrs['target']) if not _target.startswith('/'): _target = '/' + _target if _target == self.nxpath: _target = None self.nxpath = current_path return _target, _filename, _abspath, _soft def writefile(self, root): """ Write the whole NeXus tree to the file. The file is assumed to start empty. Parameters ---------- root : NXroot Root group of the NeXus tree. """ links = [] self.nxpath = "" for entry in root.values(): links += self._writegroup(entry) self._writelinks(links) if len(root.attrs) > 0: self._writeattrs(root.attrs) root._filename = self._filename self._root = root def _writeattrs(self, attrs): """ Write attributes for the group or field. The attributes are stored as NXattr entries in an AttrDict dictionary. The attribute values are contained in the NXattr `nxdata` attribute. Parameters ---------- attrs : AttrDict Dictionary of group or field attributes. """ if self[self.nxpath] is not None: for name, value in attrs.items(): if value.nxdata is not None: self[self.nxpath].attrs[name] = value.nxdata def _writegroup(self, group): """ Write a group and its children to the NeXus file. Internal NXlinks cannot be written until the linked group is created, so this routine returns the set of links that need to be written. Call writelinks on the list. Parameters ---------- group : NXgroup NeXus group to be written. Returns ------- list List of links. """ if group.nxpath != '' and group.nxpath != '/': self.nxpath = self.nxpath + '/' + group.nxname if group.nxname not in self[self.nxparent]: if group._target is not None: if group._filename is not None: self.nxpath = self.nxparent self._writeexternal(group) self.nxpath = self.nxparent return [] else: self[self.nxparent].create_group(group.nxname) if group.nxclass and group.nxclass != 'NXgroup': self[self.nxpath].attrs['NX_class'] = group.nxclass links = [] self._writeattrs(group.attrs) if group._target is not None: links += [(self.nxpath, group._target, group._soft)] for child in group.values(): if isinstance(child, NXlink): if child._filename is not None: self._writeexternal(child) else: links += [(self.nxpath+"/"+child.nxname, child._target, child._soft)] elif isinstance(child, NXfield): links += self._writedata(child) else: links += self._writegroup(child) self.nxpath = self.nxparent return links def _writedata(self, data): """ Write the field to the NeXus file. NXlinks cannot be written until the linked group is created, so this routine returns the set of links that need to be written. Call writelinks on the list. Parameters ---------- data : NXfield NeXus field to be written to the file. Returns ------- list List of links. """ self.nxpath = self.nxpath + '/' + data.nxname # If the data is linked then if data._target is not None: if data._filename is not None: self._writeexternal(data) self.nxpath = self.nxparent return [] else: path = self.nxpath self.nxpath = self.nxparent return [(path, data._target, data._soft)] if data._uncopied_data: if self.nxpath in self: del self[self.nxpath] _file, _path = data._uncopied_data if _file._filename != self._filename: with _file as f: f.copy(_path, self[self.nxparent], name=self.nxpath) else: self.copy(_path, self[self.nxparent], name=self.nxpath) data._uncopied_data = None elif data._memfile: data._memfile.copy('data', self[self.nxparent], name=self.nxpath) data._memfile = None elif data.nxfile and data.nxfile.filename != self.filename: data.nxfile.copy(data.nxpath, self[self.nxparent]) elif data.dtype is not None: if data.nxname not in self[self.nxparent]: self[self.nxparent].create_dataset(data.nxname, shape=data.shape, dtype=data.dtype, **data._h5opts) try: if data._value is not None: self[self.nxpath][()] = data._value except NeXusError: pass self._writeattrs(data.attrs) self.nxpath = self.nxparent return [] def _writeexternal(self, item): """ Create an external link. Notes ----- The filename is converted to a path relative to the current NeXus file, unless `item._abspath` is set to True. Parameters ---------- item : NXlinkgroup or NXlinkfield NeXus group or field containing the link target and filename. """ if self._getlink(item.nxpath)[0] is not None: del self[item.nxpath] self.nxpath = self.nxpath + '/' + item.nxname if item._abspath: filename = item.nxfilename elif Path(item._filename).is_absolute(): filename = os.path.relpath(Path(item._filename), Path(self.filename).parent) else: filename = item._filename self[self.nxpath] = self.h5.ExternalLink(filename, item._target) self.nxpath = self.nxparent def _writelinks(self, links): """ Creates links within the NeXus file. These are defined by the set of tuples returned by _writegroup and _writedata, which define the path to the link, the link target, and a boolean that determines whether the link is hard or soft. Parameters ---------- links : list ot tuples List of tuples containing the link path, target, and type. """ for path, target, soft in links: if self._getlink(path)[0] is not None: del self[path] target_path = str(PurePath(path).parent.joinpath(target)) if (path != target_path and path not in self['/'] and target_path in self['/']): if soft: self[path] = h5.SoftLink(target) else: self[path] = self[target_path] if 'target' not in self[target_path].attrs: self[target_path].attrs['target'] = target_path if self._root: self._root[target_path].attrs['target'] = target_path def readpath(self, path): """ Read the object defined by the given path. Parameters ---------- path : str Path to the NeXus object. Returns ------- NXgroup or NXfield The group or field defined by the specified path. """ self.nxpath = path return self.readitem() def readitem(self): """ Read the object defined by the current path. Returns ------- NXgroup or NXfield The group or field defined by the current path. """ item = self.get(self.nxpath) if item is None: return None elif isinstance(item, self.h5.Group): return self._readgroup(self.nxname) else: return self._readdata(self.nxname) def readentries(self, group): """ Return the group entries from the file. Parameters ---------- group : NXgroup The group whose entries are to be loaded. Returns ------- dict A dictionary of all the group entries. """ self.nxpath = group.nxpath children = self._readchildren() _entries = {} for child in children: _entries[child] = children[child] _entries[child]._group = group return _entries def readvalues(self, attrs=None): """ Read the values of the field at the current path. Notes ----- The values are only read if the array size is less than 10000. Parameters ---------- attrs : dict, optional Attribute of the field, by default None Returns ------- tuple Value, shape, dtype, and attributes of the field """ field = self.get(self.nxpath) if field is None: return None, None, None, {} shape, dtype = field.shape, field.dtype # Read in the data if it's not too large if _getsize(shape) < 1000: # i.e., less than 1k dims try: value = self.readvalue(self.nxpath) except Exception: value = None else: value = None if attrs is None: attrs = self.attrs if 'NX_class' in attrs and text(attrs['NX_class']) == 'SDS': attrs.pop('NX_class') return value, shape, dtype, attrs def readvalue(self, path, idx=()): """ Return the array stored in the file at the specified path. Parameters ---------- path : str Path to the NeXus field. idx : tuple, optional Slice of field to be returned, by default the whole field. Returns ------- array_like or str Array or string stored in the file at the current path. """ field = self.get(path) if field is not None: return field[idx] return None def writevalue(self, path, value, idx=()): """ Write a field value at the specified path in the file. Parameters ---------- path : str Specified path value : NXfield or array-like Value to be written at the specified path. idx : tuple, optional Slice to be written, by default the whole field. """ self[path][idx] = value def move(self, source, destination): """ Move an object defined by its path to another location. This is an interface to the `h5py.Group` move function. Parameters ---------- source : str Path to the object to be moved. destination : str Path of the new destination. """ self.file.move(source, destination) def copy(self, source, destination, **kwargs): """ Copy an object defined by its path to another location. This is an interface to the `h5py.Group` copy function. All the `h5py` keyword arguments can be used. Parameters ---------- source : str Path to the object to be copied. destination : str Path of the new copy. """ self.file.copy(source, destination, **kwargs) def copyfile(self, input_file, **kwargs): """ Copy an entire NeXus file to another file. All the `h5py.Group.copy()` keyword arguments can be used. Parameters ---------- input_file : NXFile NeXus file to be copied. """ for entry in input_file['/']: input_file.copy(entry, self['/'], **kwargs) self._rootattrs() def _rootattrs(self): """Write root attributes to the NeXus file.""" from datetime import datetime self.file.attrs['file_name'] = self.filename self.file.attrs['file_time'] = datetime.now().isoformat() self.file.attrs['HDF5_Version'] = self.h5.version.hdf5_version self.file.attrs['h5py_version'] = self.h5.version.version self.file.attrs['creator'] = 'nexusformat' from .. import __version__ self.file.attrs['creator_version'] = __version__ if self._root: self._root._setattrs(self.file.attrs) def update(self, item): """ Update the specifed object in the NeXus file. Notes ----- If the specified object is an NXobject, it is assumed to contain the path, file, and keyword arguments to be used to copy it to the specified item path, using the `h5py.Group` copy function. Parameters ---------- item : NXgroup or NXfield or AttrDict Group, field or attributes to be updated in the NeXus file. """ self.nxpath = item.nxpath if isinstance(item, AttrDict): self._writeattrs(item) else: self.nxpath = self.nxparent if isinstance(item, NXlink): if item._filename is None: self._writelinks([(item.nxpath, item._target, item._soft)]) else: self._writeexternal(item) elif isinstance(item, NXfield): self._writedata(item) elif isinstance(item, NXgroup): links = self._writegroup(item) self._writelinks(links) elif isinstance(item, NXobject): if isinstance(item._copyfile, NXFile): with item._copyfile as f: self.copy(f[item._copypath], item.nxpath, **item._attrs) item = self.readpath(item.nxpath) if self.nxparent == '/': group = self._root else: group = self._root[self.nxparent] group.entries[item.nxname] = item group[item.nxname]._group = group self.nxpath = item.nxpath def reload(self): """ Reload the entire NeXus file. This may be necessary if another process has modified the file on disk. """ self.nxpath = '/' self._root._entries = self._readchildren() for entry in self._root._entries: self._root._entries[entry]._group = self._root self._root._changed = True self._root._file_modified = False self._root._mtime = self.mtime def rename(self, old_path, new_path): """ Rename an object defined by its path to a new path. Parameters ---------- old_path : str Old path to the NeXus object. new_path : str New path to the NeXus object. """ if old_path != new_path: self.file['/'].move(old_path, new_path) @property def filename(self): """The file name on disk.""" return self._filename @property def mode(self): """File mode of the NeXus file.""" return self._mode @mode.setter def mode(self, mode): if mode == 'rw' or mode == 'r+': self._mode = 'rw' else: self._mode = 'r' @property def attrs(self): """Attributes of the object defined by the current path.""" return self._readattrs() @property def nxpath(self): """Current path in the NeXus file.""" return self._path.replace('//', '/') @nxpath.setter def nxpath(self, value): self._path = value.replace('//', '/') @property def nxparent(self): """Path to the parent of the current path.""" return '/' + self.nxpath[:self.nxpath.rfind('/')].lstrip('/') @property def nxname(self): """Name of the object at the current path.""" return self.nxpath[self.nxpath.rfind('/')+1:] def _makeclass(cls, bases=None): """ Create a new subclass of the NXgroup class. Parameters ---------- bases : tuple of classes, optional Superclasses of the new class, by default :class:`NXgroup`. Returns ------- type New subclass. """ docstring = f""" {cls} group. This is a subclass of the NXgroup class. See the NXgroup documentation for more details. """ if bases is None: bases = (NXgroup,) return type(str(cls), bases, {'_class': cls, '__doc__': docstring}) def _getclass(cls, link=False): """ Return class based on the name or type. Parameters ---------- link : bool, optional True if the class is also a :class:`NXlink` subclass, by default False. Returns ------- type Class object. """ if isinstance(cls, type): cls = cls.__name__ if not cls.startswith('NX'): return type(object) elif cls in globals() and (not link or cls.startswith('NXlink')): return globals()[cls] if cls != 'NXlink' and cls.startswith('NXlink'): link = True cls = cls.replace('NXlink', 'NX') if link: if cls in globals(): bases = (NXlinkgroup, globals()[cls]) cls = cls.replace('NX', 'NXlink') globals()[cls] = _makeclass(cls, bases) else: raise NeXusError(f"'{cls}' is not a valid NeXus class") else: globals()[cls] = _makeclass(cls, (NXgroup,)) return globals()[cls] def _getvalue(value, dtype=None, shape=None): """ Return the value of a field or attribute based on a Python value. If 'dtype' and/or 'shape' are specified as input arguments, the value is converted to the given dtype and/or reshaped to the given shape. Otherwise, the dtype and shape are determined from the value. If the value is a masked array, the returned value is only returned as a masked array if some of the elements are masked. Parameters ---------- value Input Python value dtype : dtype or str, optional Required dtype of value, by default None shape : tuple, optional Required shape of value, by default None Returns ------- tuple Value, dtype, and shape for creation of new field or attribute. """ dtype, shape = _getdtype(dtype), _getshape(shape) if isinstance(value, NXfield) or isinstance(value, NXattr): value = value.nxvalue elif isinstance(value, Path): value = str(value) if value is None: return None, dtype, shape elif is_text(value): if shape is not None and shape != (): raise NeXusError("The value is incompatible with the shape") if dtype is not None: try: _dtype = _getdtype(dtype) if _dtype.kind == 'S': value = np.array(text(value).encode('utf-8'), dtype=_dtype) else: value = np.array(value, dtype=_dtype) return value.item(), value.dtype, () except Exception: raise NeXusError("The value is incompatible with the dtype") else: _value = text(value) return _value, string_dtype, () elif isinstance(value, np.ndarray): if isinstance(value, np.ma.MaskedArray): if value.count() < value.size: # some values are masked _value = value else: _value = np.asarray(value) else: _value = np.asarray(value) # convert subclasses of ndarray else: try: _value = [np.asarray(v) for v in value] if len(set([v.shape for v in _value])) > 1: raise NeXusError( "Cannot assign an iterable with items of multiple shapes") _value = np.asarray(_value) except TypeError: _value = np.asarray(value) if _value.dtype.kind == 'S' or _value.dtype.kind == 'U': _value = _value.astype(string_dtype) if dtype is not None: if isinstance(value, bool) and dtype != bool: raise NeXusError( "Cannot assign a Boolean value to a non-Boolean field") elif isinstance(_value, np.ndarray): try: _value = _value.astype(dtype) except Exception: raise NeXusError("The value is incompatible with the dtype") if shape is not None and isinstance(_value, np.ndarray): try: _value = _value.reshape(shape) except ValueError: raise NeXusError("The value is incompatible with the shape") if _value.shape == () and not np.ma.is_masked(_value): return _value.item(), _value.dtype, _value.shape else: return _value, _value.dtype, _value.shape def _getdtype(dtype): """ Return a valid h5py dtype. This converts string dtypes to the special HDF5 dtype for variable length strings. Other values are checked against valid NumPy dtypes. Parameters ---------- dtype : dtype Proposed datatype of an NXfield. Returns ------- dtype Valid dtype for storing in an HDF5 file. """ if dtype is None: return None elif is_text(dtype) and dtype == 'char': return string_dtype else: try: _dtype = np.dtype(dtype) if _dtype.kind == 'U': return string_dtype else: return _dtype except TypeError: raise NeXusError(f"Invalid data type: {dtype}") def _getshape(shape, maxshape=False): """ Return a valid shape tuple. The returned shape tuple will contain integer values, unless maxshape is True, in which case, values of None are allowed. Parameters ---------- shape : tuple of int Proposed new shape maxshape : bool, optional True if values of None are permitted in a shape element, by default False Returns ------- tuple of int Valid shape tuple. """ if shape is None: return None else: try: if not is_iterable(shape): shape = [shape] if maxshape: return tuple([None if i is None else int(i) for i in shape]) elif None in shape: return None else: return tuple([int(i) for i in shape]) except ValueError: raise NeXusError(f"Invalid shape: {shape}") def _getmaxshape(maxshape, shape): """ Return maximum shape if compatible with the specified shape. This raises a NeXusError if the length of the shapes do not match or if any of the elements in maxshape are smaller than the corresponding element in shape. If maxshape has a size of 1, an empty tuple is returned. Parameters ---------- maxshape : tuple of int Proposed maximum shape of the array shape : tuple of int Current shape of the array Returns ------- tuple of int Maximum shape """ maxshape, shape = _getshape(maxshape, maxshape=True), _getshape(shape) if maxshape is None or shape is None: return None else: if maxshape == (1,) and shape == (): return () elif len(maxshape) != len(shape): raise NeXusError( "Number of dimensions in maximum shape does not match the field") else: if _checkshape(shape, maxshape): return maxshape else: raise NeXusError( "Maximum shape must be larger than the field shape") def _checkshape(shape, maxshape): """ True if the shape is consistent with the maximum allowed shape. Each element of shape must be less than or equal to the corresponding element of maxshape, unless the latter is set to None, in which case the value of the shape element is unlimited. Parameters ---------- shape : tuple of int Shape to be checked. maxshape : tuple of int Maximum allowed shape Returns ------- bool True if the shape is consistent. """ for i, j in [(_i, _j) for _i, _j in zip(maxshape, shape)]: if i is not None and i < j: return False return True def _getsize(shape): """ Return the total size of the array with the specified shape. If the shape is None, a size of 1 is returned. Parameters ---------- shape : tuple of int Shape of the array. Returns ------- int Size of the array """ if shape is None: return 1 else: try: return np.prod(shape, dtype=np.int64) except Exception: return 1 def _readaxes(axes): """ Return a list of axis names stored in the 'axes' attribute. If the input argument is a string, the names are assumed to be separated by a delimiter, which can be white space, a comma, or a colon. If it is a list of strings, they are converted to Unicode strings. Parameters ---------- axes : str or list of str Value of 'axes' attribute defining the plotting axes. Returns ------- list of str Names of the axis fields. """ if is_text(axes): return list(re.split(r'[,:; ]', text(axes).strip('[]()').replace('][', ':'))) else: return [text(axis) for axis in axes] class AttrDict(dict): """ A dictionary class to assign and return values to NXattr instances. This is used to control the initialization of the NXattr objects and the return of their values. For example, attributes that contain string or byte arrays are returned as lists of (unicode) strings. Size-1 arrays are returned as scalars. The 'get' function can be used to return the original array. If the attribute are stored in a NeXus file with read/write access, their values are automatically updated. Parameters ---------- parent : NXfield or NXgroup The field or group to which the attributes belong. attrs : dict A dictionary containing the first set of attributes. """ _parent = None def __init__(self, parent=None, attrs=None): super().__init__() self._parent = parent if attrs is not None: self._setattrs(attrs) def _setattrs(self, attrs): for key, value in attrs.items(): super().__setitem__(key, NXattr(value)) def __getitem__(self, key): """Returns the value of the requested NXattr object.""" return super().__getitem__(key).nxvalue def __setitem__(self, key, value): """Creates a new entry in the dictionary.""" if value is None: return elif isinstance(self._parent, NXobject): if self._parent.nxfilemode == 'r': raise NeXusError("NeXus file opened as readonly") elif self._parent.is_linked(): raise NeXusError("Cannot modify an item in a linked group") if isinstance(value, NXattr): super().__setitem__(text(key), value) else: super().__setitem__(text(key), NXattr(value)) if isinstance(self._parent, NXobject): self._parent.set_changed() if self._parent.nxfilemode == 'rw': with self._parent.nxfile as f: f.update(self) def __delitem__(self, key): """Deletes an entry from the dictionary.""" if isinstance(self._parent, NXobject): if self._parent.nxfilemode == 'r': raise NeXusError("NeXus file opened as readonly") elif self._parent.is_linked(): raise NeXusError("Cannot modify an item in a linked group") super().__delitem__(key) if isinstance(self._parent, NXobject): self._parent.set_changed() if self._parent.nxfilemode == 'rw': with self._parent.nxfile as f: f.nxpath = self._parent.nxpath del f[f.nxpath].attrs[key] def get(self, key, default=None): """Return the value of the requested attribute.""" if key in self: return super().get(key).nxvalue else: return default @property def nxpath(self): """Path to the field or group containin the attributes.""" return self._parent.nxpath class NXattr: """ Class for NeXus attributes of a NXfield or NXgroup object. Attributes ---------- nxvalue : str, scalar, or array-like The value of the NeXus attribute modified as described below. nxdata : str, scalar, or array-like The unmodified value of the NeXus attribute. dtype : str The data type of the NeXus attribute value. shape : tuple The shape of the NeXus attribute value. Notes ----- NeXus attributes are stored in the 'attrs' dictionary of the parent object, NXfield or NXgroup, but can often be referenced or assigned using the attribute name as if it were an object attribute. For example, after assigning the NXfield, the following three attribute assignments are all equivalent:: >>> entry.sample.temperature = NXfield(40.0) >>> entry.sample.temperature.attrs['units'] = 'K' >>> entry.sample.temperature.units = NXattr('K') >>> entry.sample.temperature.units = 'K' The last version above is only allowed for NXfield attributes and is not allowed if the attribute has the same name as one of the following internally defined attributes, i.e., ['entries', 'attrs', 'dtype','shape'] or if the attribute name begins with 'nx' or '_'. It is only possible to reference attributes with one of the proscribed names using the 'attrs' dictionary. """ def __init__(self, value=None, dtype=None, shape=None): if isinstance(value, NXattr) or isinstance(value, NXfield): value = value.nxdata elif isinstance(value, NXgroup): raise NeXusError("A data attribute cannot be a NXgroup") self._value, self._dtype, self._shape = _getvalue(value, dtype, shape) def __str__(self): return text(self.nxvalue) def __unicode__(self): return text(self.nxvalue) def __repr__(self): if (self.dtype is not None and (self.shape == () or self.shape == (1,)) and (self.dtype.type == np.bytes_ or self.dtype.type == np.str_ or self.dtype == string_dtype)): return f"NXattr('{self}')" else: return f"NXattr({self})" def __eq__(self, other): """True if the values of the two attributes are the same.""" if id(self) == id(other): return True elif isinstance(other, NXattr): return self.nxvalue == other.nxvalue else: return self.nxvalue == other def __hash__(self): return id(self) @property def nxvalue(self): """ The attribute value for use in Python scripts. This is the value stored in the NeXus file, with the following exceptions. 1) Size-1 arrays are returned as scalars. 2) String or byte arrays are returns as a list of strings. Notes ----- If unmodified values are required, use the 'nxdata' property. """ if self._value is None: return '' elif (self.dtype is not None and (self.dtype.type == np.bytes_ or self.dtype.type == np.str_ or self.dtype == string_dtype)): if self.shape == (): return text(self._value) elif self.shape == (1,): return text(self._value[0]) else: return [text(value) for value in self._value[()]] elif self.shape == (): return self._value elif self.shape == (1,): return self._value.item() else: return self._value.tolist() @property def nxdata(self): """The attribute value as stored in the NeXus file.""" return self._value @property def dtype(self): """The attribute dtype""" return self._dtype @property def shape(self): """The attribute shape.""" try: return tuple([int(i) for i in self._shape]) except (TypeError, ValueError): return () _npattrs = list(filter(lambda x: not x.startswith('_'), np.ndarray.__dict__)) class NXobject: """ Abstract base class for elements in NeXus files. The object has a subclass of NXfield, NXgroup, or one of the NXgroup subclasses. Child nodes should be accessible directly as object attributes. Constructors for NXobject objects are defined by either the NXfield or NXgroup classes. Attributes ---------- nxclass : str The class of the NXobject. NXobjects can have class NXfield, NXgroup, or be one of the NXgroup subclasses. nxname : str The name of the NXobject. Since it is possible to reference the same Python object multiple times, this is not necessarily the same as the object name. However, if the object is part of a NeXus tree, this will be the attribute name within the tree. nxgroup : NXgroup The parent group containing this object within a NeXus tree. If the object is not part of any NeXus tree, it will be set to None. nxpath : str The path to this object with respect to the root of the NeXus tree. For NeXus data read from a file, this will be a group of class NXroot, but if the NeXus tree was defined interactively, it can be any valid NXgroup. nxroot : NXgroup The root object of the NeXus tree containing this object. For NeXus data read from a file, this will be a group of class NXroot, but if the NeXus tree was defined interactively, it can be any valid NXgroup. nxfile : NXFile The file handle of the root object of the NeXus tree containing this object. nxfilename : str The file name of NeXus object's tree file handle. attrs : dict A dictionary of the NeXus object's attributes. """ _class = "unknown" _name = "unknown" _group = None _attrs = AttrDict() _file = None _filename = None _abspath = False _target = None _soft = None _external = None _mode = None _link = None _value = None _copyfile = None _copypath = None _memfile = None _uncopied_data = None _changed = True _backup = None _file_modified = False _smoothing = None _vpath = None _vfiles = None _vshape = None _vidx = None _proxy = None def __init__(self, *args, **kwargs): self._name = kwargs.pop("name", None) self._class = kwargs.pop("nxclass", NXobject) self._group = kwargs.pop("group", None) self._copyfile = kwargs.pop("nxfile", None) self._copypath = kwargs.pop("nxpath", None) self._attrs = kwargs def __getstate__(self): result = self.__dict__.copy() hidden_keys = [key for key in result if key.startswith('_')] needed_keys = ['_class', '_name', '_group', '_target', '_entries', '_attrs', '_filename', '_mode', '_dtype', '_shape', '_value', '_h5opts', '_changed'] for key in hidden_keys: if key not in needed_keys: del result[key] return result def __setstate__(self, dict): self.__dict__ = dict def __str__(self): return self.nxname def __repr__(self): return f"NXobject('{self.nxname}')" def __bool__(self): """True if the object exists.""" return True def __contains__(self, key): """Only defined for groups.""" return False def __lt__(self, other): """Define ordering of NeXus objects using their names.""" if not isinstance(other, NXobject): return False else: return self.nxname < other.nxname def _setattrs(self, attrs): for k, v in attrs.items(): self._attrs[k] = v def walk(self): if False: yield def _str_name(self, indent=0): return " " * indent + self.nxname def _str_attrs(self, indent=0): names = sorted(self.attrs) result = [] for k in names: txt1 = " " * indent txt2 = "@" + k + " = " txt3 = text(self.attrs[k]) if len(txt3) > 50: txt3 = txt3[:46] + '...' if is_text(self.attrs[k]): txt3 = "'" + txt3 + "'" else: txt3 = txt3 txt = (txt1 + txt2 + txt3) try: txt = txt[:txt.index('\n')]+'...' except ValueError: pass result.append(txt) return "\n".join(result) def _str_tree(self, indent=0, attrs=False, recursive=False): result = [self._str_name(indent=indent)] if self.attrs and (attrs or indent == 0): result.append(self._str_attrs(indent=indent+2)) return "\n".join(result) def _get_completion_list(self): """Return attributes and methods for use in autocompletion.""" return (dir(self) + [attr for attr in object.__dir__(self) if not attr.startswith('_')]) def dir(self, attrs=False, recursive=False): """Print the group directory. The directory is a list of NeXus objects within this group, either NeXus groups or NXfield data. If 'attrs' is True, NXfield attributes are displayed. If 'recursive' is True, the contents of child groups are also displayed. Parameters ---------- attrs : bool, optional Display attributes in the directory if True, by default False. recursive : bool, optional Display the directory contents recursively if True, by default False. """ print(self._str_tree(attrs=attrs, recursive=recursive)) @property def tree(self): """ Return the directory tree as a string. The tree contains all child objects of this object and their children. It invokes the 'dir' method with 'attrs' set to False and 'recursive' set to True. Returns ------- str String containing the hierarchical structure of the tree. """ return self._str_tree(attrs=True, recursive=True) @property def short_tree(self): """ Return a shortened directory tree as a string. The tree contains all child objects of this object and their children. It invokes the 'dir' method with 'attrs' set to False and 'recursive' set to True. Returns ------- str String containing the hierarchical structure of the tree. """ return self._str_tree(attrs=False, recursive=1) def rename(self, name): """ Rename the NeXus object. This changes the signal or axes attributes to use the new name if necessary. Parameters ---------- name : str New name of the NeXus object. """ name = text(name) old_name = self.nxname if name == old_name: return else: old_path = self.nxpath group = self.nxgroup if group is not None: signal = axis = False if group.nxfilemode == 'r': raise NeXusError("NeXus parent group is readonly") elif self is group.nxsignal: signal = True else: axes = group.nxaxes if axes is not None: axis_names = [axis.nxname for axis in axes] if self.nxname in axis_names: axis = axis_names.index(self.nxname) elif self.nxfilemode == 'r': raise NeXusError("NeXus file opened as readonly") self._name = name if group is not None: new_path = group.nxpath + '/' + name if not isinstance(self, NXroot) and group.nxfilemode == 'rw': with group.nxfile as f: f.rename(old_path, new_path) group.entries[name] = group.entries.pop(old_name) if signal: group.nxsignal = self elif axis is not False: axes[axis] = self group.nxaxes = axes self.set_changed() def save(self, filename=None, mode='w-', **kwargs): """ Save the NeXus object to a data file. If the object is an NXroot group, this can be used to save the whole NeXus tree. If the tree was read from a file and the file was opened as read only, then a file name must be specified. Otherwise, the tree is saved to the original file. An error is raised if the object is an NXroot group from an external file that has been opened as readonly and no file name is specified. If the object is not an NXroot, group, a filename must be specified. The saved NeXus object is wrapped in an NXroot group (with name 'root') and an NXentry group (with name 'entry'), if necessary, in order to produce a valid NeXus file. Only the children of the object will be saved. This capability allows parts of a NeXus tree to be saved for later use, e.g., to store an NXsample group to be added to another file at a later time. Parameters ---------- filename : str Name of the data file. mode : str, optional Mode for opening the file, by default 'w-' Returns ------- NXroot Tree containing all the NeXus fields and groups saved to the file. Example ------- >>> data = NXdata(sin(x), x) >>> data.save('file.nxs') >>> print(data.nxroot.tree) root:NXroot @HDF5_Version = 1.8.2 @NeXus_version = 4.2.1 @file_name = file.nxs @file_time = 2012-01-20T13:14:49-06:00 entry:NXentry data:NXdata axis1 = float64(101) signal = float64(101) @axes = axis1 @signal = 1 >>> root['entry/data/axis1'].units = 'meV' >>> root.save() """ if filename: filename = Path(filename) if filename.suffix == '': filename = filename.with_suffix('.nxs') if self.nxclass == 'NXroot': root = self elif self.nxclass == 'NXentry': root = NXroot(self) else: root = NXroot(NXentry(self)) if mode != 'w': write_mode = 'w-' else: write_mode = 'w' with NXFile(filename, write_mode, **kwargs) as f: f.writefile(root) root = f._root root._file = f if mode == 'w' or mode == 'w-': root._mode = 'rw' else: root._mode = mode self.set_changed() return root else: raise NeXusError("No output file specified") def copy(self, name=None, **kwargs): """ Returns information allowing the object to be copied. If no group is specified and the current group is saved to a file, a skeleton group is created with information to be used by a h5py copy. This is resolved when the skeleton group is assigned to a parent group. Parameters ---------- name : str, optional Name of copied object if different from current object. **kwargs Keyword arguments to be transferred to the h5py copy function. Returns ------- NXobject NeXus object containing information for subsequent copies. """ if self.nxfilemode is None: raise NeXusError("Can only copy objects saved to a NeXus file.") if name is None: name = self.nxname return NXobject(name=name, nxclass=self.nxclass, nxfile=self.nxfile, nxpath=self.nxfilepath, **kwargs) def update(self): """Update the object values in its NeXus file if necessary.""" if self.nxfilemode == 'rw': with self.nxfile as f: f.update(self) self.set_changed() @property def changed(self): """ True if the object has been changed. This property is for use by external scripts that need to track which NeXus objects have been changed. """ return self._changed def set_changed(self): """Set an object's change status to changed.""" self._changed = True if self.nxgroup: self.nxgroup.set_changed() def set_unchanged(self, recursive=False): """Set an object's change status to unchanged.""" if recursive: for node in self.walk(): node._changed = False else: self._changed = False def _setclass(self, cls): """ Change the object class. Parameters ---------- cls : type New object class. """ try: class_ = _getclass(cls) if issubclass(class_, NXobject): self.__class__ = class_ self._class = self.__class__.__name__ if (self._class.startswith('NXlink') and self._class != 'NXlink'): self._class = 'NX' + self._class[6:] except (TypeError, NameError): raise NeXusError("Invalid NeXus class") @property def nxclass(self): """NeXus object class.""" return text(self._class) @nxclass.setter def nxclass(self, cls): self._setclass(cls) self.set_changed() @property def nxname(self): """NeXus object name.""" return text(self._name) @nxname.setter def nxname(self, value): self.rename(value) @property def nxgroup(self): """Parent group of NeXus object.""" return self._group @nxgroup.setter def nxgroup(self, value): if isinstance(value, NXgroup): self._group = value else: raise NeXusError("Value must be a valid NeXus group") @property def nxpath(self): """Path to the object in the NeXus tree.""" group = self.nxgroup if self.nxclass == 'NXroot': return "/" elif group is None: return self.nxname elif isinstance(group, NXroot): return "/" + self.nxname else: return group.nxpath+"/"+self.nxname @property def nxroot(self): """NXroot object of the NeXus tree.""" if self._group is None or isinstance(self, NXroot): return self elif isinstance(self._group, NXroot): return self._group else: return self._group.nxroot @property def nxentry(self): """Parent NXentry group of the NeXus object.""" if self._group is None or isinstance(self, NXentry): return self elif isinstance(self._group, NXentry): return self._group else: return self._group.nxentry @property def nxfile(self): """NXFile storing the NeXus data.""" if self._file: return self._file elif not self.is_external() and self.nxroot._file: return self.nxroot._file elif self.nxfilename: self._file = NXFile(self.nxfilename, self.nxfilemode) return self._file else: return None @property def nxfilename(self): """File name of the NeXus file containing the NeXus object. If the NeXus object is an external link, this is the filename containing the linked data. """ if self._filename is not None: if Path(self._filename).is_absolute(): return str(self._filename) elif (self._group is not None and self._group.nxfilename is not None): return str(Path(self._group.nxfilename).parent.joinpath( self._filename)) else: return str(Path(self._filename).resolve()) elif self._group is not None: return self._group.nxfilename else: return None @property def nxfilepath(self): """File path containing the NeXus object. If the NeXus object is an external link, this is the path to the object in the external file. """ if self.nxclass == 'NXroot': return "/" elif self.nxtarget: return self.nxtarget elif self.nxgroup is None: return "" elif isinstance(self.nxgroup, NXroot): return "/" + self.nxname elif isinstance(self.nxgroup, NXlink): group_path = self.nxgroup.nxtarget else: group_path = self.nxgroup.nxfilepath if group_path: return group_path+"/"+self.nxname else: return self.nxname @property def nxfullpath(self): """Path of the NeXus object including the filename.""" return self.nxfilename+"['"+self.nxfilepath+"']" @property def nxfilemode(self): """Read/write mode of the NeXus file if saved to a file.""" if self._mode is not None: return self._mode elif self._group is not None: return self._group.nxfilemode else: return None @property def nxtarget(self): """Property of NXlink objects.""" return self._target @property def attrs(self): """Dictionary of object attributes.""" if self._attrs is None: self._attrs = AttrDict() return self._attrs def is_plottable(self): """True if the NeXus object is plottable.""" return False def is_modifiable(self): _mode = self.nxfilemode if _mode is None or _mode == 'rw' and not self.is_linked(): return True else: return False def is_linked(self): """True if the NeXus object is embedded in a link.""" if self._group is not None: if isinstance(self._group, NXlink): return True else: return self._group.is_linked() else: return False def is_external(self): """True if the NeXus object is an external link.""" return (self.nxfilename is not None and self.nxfilename != self.nxroot.nxfilename) def file_exists(self): """True if the file containing the NeXus object exists.""" if self.nxfilename is not None: return Path(self.nxfilename).exists() else: return True def path_exists(self): """True if the path to the NeXus object exists.""" if self.is_external(): if self.file_exists(): try: with self.nxfile as f: return self.nxfilepath in f except Exception: return False else: return False else: return True def exists(self): """True if the NeXus object file and path is accessible.""" return self.file_exists() and self.path_exists() @property def id(self): """ Return the HDF5 identifier for the object in the NeXus file. This only works for objects that within trees saved to a file. Otherwise, None is returned. """ if self.nxfilemode: return self.nxfile[self.nxpath].id else: return None @property def addr(self): """ Return the HDF5 address for the object in the NeXus file. This only works for objects that within trees saved to a file. Otherwise, None is returned. """ if self.nxfilemode: return h5.h5o.get_info(self.id).addr else: return None @property def rc(self): """ Return the reference count for the object in the NeXus file. This only works for objects that within trees saved to a file. Otherwise, None is returned. """ if self.nxfilemode: return h5.h5o.get_info(self.id).rc else: return None class NXfield(NXobject): """ NeXus field containing scalars, arrays or strings with attributes. NXfields usually consist of arrays of numeric data with associated meta-data, the NeXus attributes. The exception is when they contain character strings. This makes them similar to NumPy arrays, and this module allows the use of NXfields in numerical operations in the same way as NumPy arrays. NXfields are technically not a sub-class of the ndarray class, but most NumPy operations work on NXfields, returning either another NXfield or, in some cases, an `ndarray` that can easily be converted to an NXfield. Parameters ---------- value : int, float, array_like or string Numerical or string value of the NXfield, which is directly accessible as the NXfield attribute 'nxvalue'. name : str Name of the NXfield. dtype : np.dtype or str Data type of the NXfield value. Valid dtypes correspond to standard NumPy data types, using names defined by the NeXus API, *i.e.*, 'float32' 'float64' 'int8' 'int16' 'int32' 'int64' 'uint8' 'uint16' 'uint32' 'uint64' 'char' If the data type is not specified, it is determined automatically by the data type of the 'value'. shape : list of ints Shape of the NXfield data. This corresponds to the shape of the NumPy array. Scalars (numeric or string) are stored as zero-rank arrays, for which `shape=()`. group : NXgroup Parent group of NeXus field. attrs : dict Dictionary containing NXfield attributes. kwargs: dict Dictionary containing allowed `h5py.Dataset` keyword arguments, *i.e.*, 'chunks', 'compression', 'compression_opts', 'fillvalue', 'fletcher32', 'maxshape', 'scaleoffset', and 'shuffle'. Attributes ---------- nxclass : str The class of the NXobject. nxname : string The name of the NXfield. Since it is possible to reference the same Python object multiple times, this is not necessarily the same as the object name. However, if the field is part of a NeXus tree, this will be the attribute name within the tree. nxgroup : NXgroup The parent group containing this field within a NeXus tree. If the field is not part of any NeXus tree, it will be set to None. dtype : string or NumPy dtype The data type of the NXfield value. If the NXfield has been initialized but the data values have not been read in or defined, this is a string. Otherwise, it is set to the equivalent NumPy dtype. shape : list or tuple of ints The dimensions of the NXfield data. If the NXfield has been initialized but the data values have not been read in or defined, this is a list of ints. Otherwise, it is set to the equivalent NumPy shape, which is a tuple. Scalars (numeric or string) are stored as NumPy zero-rank arrays, for which shape=(). attrs : dict A dictionary of all the NeXus attributes associated with the field. These are objects with class NXattr. nxdata : scalar, NumPy array or string The data value of the NXfield. This is normally initialized using the 'value' parameter (see above). If the NeXus data is contained in a file and the size of the NXfield array is too large to be stored in memory, the value is not read in until this attribute is directly accessed. Even then, if there is insufficient memory, a value of None will be returned. In this case, the NXfield array should be read as a series of smaller slabs using 'get'. nxpath : string The path to this object with respect to the root of the NeXus tree. For NeXus data read from a file, this will be a group of class NXroot, but if the NeXus tree was defined interactively, it can be any valid NXgroup. nxroot : NXgroup The root object of the NeXus tree containing this object. For NeXus data read from a file, this will be a group of class NXroot, but if the NeXus tree was defined interactively, it can be any valid NXgroup. Notes ----- NeXus attributes are stored in the `attrs` dictionary of the NXfield, but can usually be assigned or referenced as if they are Python attributes, as long as the attribute name is not the same as one of those listed above. This is to simplify typing in an interactive session and should not cause any problems because there is no name clash with attributes so far defined within the NeXus standard. When writing modules, it is recommended that the attributes always be referenced using the `attrs` dictionary if there is any doubt. 1) Assigning a NeXus attribute In the example below, after assigning the NXfield, the following three NeXus attribute assignments are all equivalent: >>> entry['sample/temperature'] = NXfield(40.0) >>> entry['sample/temperature'].attrs['units'] = 'K' >>> entry['sample/temperature'].units = NXattr('K') >>> entry['sample/temperature'].units = 'K' 2) Referencing a NeXus attribute If the name of the NeXus attribute is not the same as any of the Python attributes listed above, or one of the methods listed below, or any of the attributes defined for NumPy arrays, they can be referenced as if they were a Python attribute of the NXfield. However, it is only possible to reference attributes with one of the proscribed names using the `attrs` dictionary. >>> entry['sample/temperature'].tree = 10.0 >>> entry['sample/temperature'].tree temperature = 40.0 @tree = 10.0 @units = K >>> entry['sample/temperature'].attrs['tree'] NXattr(10.0) Examples -------- The following examples show how fields can usually be treated like NumPy arrays. >>> x = NXfield((1.0,2.0,3.0,4.0)) >>> print(x+1) [ 2. 3. 4. 5.] >>> print(2*x) [ 2. 4. 6. 8.] >>> print(x/2) [ 0.5 1. 1.5 2. ] >>> print(x**2) [ 1. 4. 9. 16.] >>> print(x.reshape((2,2))) [[ 1. 2.] [ 3. 4.]] >>> y = NXfield((0.5,1.5,2.5,3.5)) >>> x + y NXfield(array([1.5, 3.5, 5.5, 7.5])) >>> x * y NXfield(array([ 0.5, 3. , 7.5, 14. ])) >>> (x + y).shape (4,) >>> (x + y).dtype dtype('float64') All these operations return valid NXfield objects containing the same attributes as the first NXobject in the expression. The 'reshape' and 'transpose' methods also return NXfield objects. It is possible to use the standard slice syntax. >>> x=NXfield(np.linspace(0,10,11)) >>> x NXfield([ 0. 1. 2. ..., 8. 9. 10.]) >>> x[2:5] NXfield([ 2. 3. 4.]) In addition, it is possible to use floating point numbers as the slice indices. If one of the indices is not integer, both indices are used to extract elements in the array with values between the two index values. >>> x=NXfield(np.linspace(0,100.,11)) >>> x NXfield([ 0. 10. 20. ..., 80. 90. 100.]) >>> x[20.:50.] NXfield([ 20. 30. 40. 50.]) The standard NumPy ndarray attributes and methods will also work with NXfields, but will return scalars or NumPy arrays. >>> x.size 4 >>> x.sum() 10.0 >>> x.max() 4.0 >>> x.mean() 2.5 >>> x.var() 1.25 >>> x.reshape((2,2)).sum(1) NXfield(array([3., 7.])) Finally, NXfields are cast as `ndarrays` for operations that require them. The returned value will be the same as for the equivalent ndarray operation, *e.g.*, >>> np.sin(x) NXfield(array([ 0. , 0.84147, 0.90929, ..., 0.98935, 0.41211, -0.54402])) >>> np.sqrt(x) NXfield(array([0. , 1. , 1.41421, ..., 2.82842, 3., 3.16227])) """ properties = ['mask', 'dtype', 'shape', 'chunks', 'compression', 'compression_opts', 'fillvalue', 'fletcher32', 'maxshape', 'scaleoffset', 'shuffle'] def __init__(self, value=None, name='unknown', shape=None, dtype=None, group=None, attrs=None, **kwargs): self._class = 'NXfield' self._name = name self._group = group self._value, self._dtype, self._shape = _getvalue(value, dtype, shape) _size = _getsize(self._shape) _h5opts = {} _h5opts['chunks'] = kwargs.pop('chunks', True if _size > NX_CONFIG['maxsize'] else None) _h5opts['compression'] = kwargs.pop('compression', NX_CONFIG['compression'] if _size > NX_CONFIG['maxsize'] else None) _h5opts['compression_opts'] = kwargs.pop('compression_opts', None) _h5opts['fillvalue'] = kwargs.pop('fillvalue', None) _h5opts['fletcher32'] = kwargs.pop('fletcher32', None) _h5opts['maxshape'] = _getmaxshape(kwargs.pop('maxshape', None), self._shape) _h5opts['scaleoffset'] = kwargs.pop('scaleoffset', None) _h5opts['shuffle'] = kwargs.pop('shuffle', True if _size > NX_CONFIG['maxsize'] else None) self._h5opts = dict((k, v) for (k, v) in _h5opts.items() if v is not None) if attrs is None: attrs = {} attrs.update(kwargs) self._attrs = AttrDict(self, attrs=attrs) self._memfile = None self._uncopied_data = None self.set_changed() def __dir__(self): return sorted([c for c in dir(super()) if not c.startswith('_')] + list(self.attrs), key=natural_sort) def __repr__(self): if self._value is not None: return f"NXfield({repr(self._value)})" else: return f"NXfield(shape={self.shape}, dtype={self.dtype})" def __str__(self): if self._value is not None: return text(self.nxvalue) return "" def __format__(self, format_spec): return format(self.nxvalue, format_spec) def __getattr__(self, name): """Return NumPy array or NeXus attributes.""" if name in _npattrs: return getattr(self.nxdata, name) elif name in self.attrs: return self.attrs[name] else: raise AttributeError("'"+name+"' not in "+self.nxpath) def __setattr__(self, name, value): """ Add an attribute to the NXfield's attribute dictionary. Parameters ---------- name : str Name of the field attribute. value : str or array-like Value to be assigned to the field attribute. Notes ----- If the attribute name starts with 'nx' or '_', they are assigned as NXfield attributes without further conversions. """ if (name.startswith('_') or name.startswith('nx') or name in self.properties): object.__setattr__(self, name, value) elif self.is_modifiable(): self._attrs[name] = value self.set_changed() elif self.is_linked(): raise NeXusError("Cannot modify an item in a linked group") else: raise NeXusError("NeXus file opened as readonly") def __delattr__(self, name): """Delete an attribute in the NXfield attributes dictionary.""" if self.is_modifiable() and name in self.attrs: del self.attrs[name] self.set_changed() elif self.is_linked(): raise NeXusError("Cannot modify an item in a linked group") else: raise NeXusError("NeXus file opened as readonly") def __getitem__(self, idx): """ Return a slice from the NXfield. In most cases, the slice values are applied to the NXfield nxdata array and returned within an NXfield object with the same metadata. However, if the array is one-dimensional and the index start and stop values are real, the nxdata array is returned with values between those limits. This is to allow axis arrays to be limited by their actual value. This real-space slicing should only be used on monotonically increasing (or decreasing) one-dimensional arrays. Parameters ---------- idx : slice Slice index or indices. Returns ------- NXfield Field containing the slice values. """ if idx is None or idx is Ellipsis: return self if is_real_slice(idx): idx = convert_index(idx, self) if self._value is None: if self._uncopied_data: result = self._get_uncopied_data(idx) elif self.nxfilemode: result = self._get_filedata(idx) elif self._memfile: result = self._get_memdata(idx) mask = self.mask if mask is not None: if isinstance(mask, NXfield): mask = mask[idx].nxdata else: mask = mask[idx] if isinstance(result, np.ma.MaskedArray): result = result.data result = np.ma.array(result, mask=mask) elif self.fillvalue: result = np.asarray(np.empty(self.shape, dtype=self.dtype)[idx]) result.fill(self.fillvalue) else: raise NeXusError( "Data not available either in file or in memory") if self.mask is not None: result = np.ma.MaskedArray.__getitem__(result, ()) elif self.mask is not None: result = np.ma.MaskedArray.__getitem__(self.nxdata, idx) else: result = np.asarray(self.nxdata[idx]) return NXfield(result, name=self.nxname, attrs=self.safe_attrs) def __setitem__(self, idx, value): """ Assign values to a NXfield slice. Parameters ---------- idx : slice Slice to be modified. value Value to be added. The value must be compatible with the NXfield dtype and it must be possible to broadcast it to the shape of the specified slice. """ if self.nxfilemode == 'r': raise NeXusError("NeXus file opened as readonly") elif self.is_linked(): raise NeXusError("Cannot modify an item in a linked group") elif self.dtype is None: raise NeXusError("Set the field dtype before assignment") if is_real_slice(idx): idx = convert_index(idx, self) if value is np.ma.masked: self._mask_data(idx) else: if isinstance(value, bool) and self.dtype != bool: raise NeXusError( "Cannot set a Boolean value to a non-Boolean data type") elif value is np.ma.nomask: value = False if isinstance(value, NXfield): value = value.nxdata if self._value is not None: self._value[idx] = value if self.nxfilemode == 'rw': self._put_filedata(value, idx) elif self._value is None: if self.size > NX_CONFIG['maxsize']: self._put_memdata(value, idx) else: self._value = np.empty(self.shape, self.dtype) if self.fillvalue: self._value.fill(self.fillvalue) elif is_string_dtype(self.dtype): self._value.fill(' ') else: self._value.fill(0) self._value[idx] = value self.set_changed() def _str_name(self, indent=0): s = text(self).replace('\r\n', '\n') if self.dtype is not None: if is_string_dtype(self.dtype): if len(s) > 60: s = s[:56] + '...' try: s = s[:s.index('\n')]+'...' except ValueError: pass if self.size == 1: s = "'" + s + "'" elif len(self) > 3 or '\n' in s or s == "": if self.shape is None: dims = '' else: dims = 'x'.join([text(n) for n in self.shape]) s = f"{self.dtype}({dims})" elif s == "": s = "None" try: return " " * indent + self.nxname + " = " + s except Exception: return " " * indent + self.nxname def _get_filedata(self, idx=()): """ Return the specified slab from the NeXus file. Parameters ---------- idx : slice, optional Slice indices, by default (). Returns ------- array_like Array containing the slice values. """ with self.nxfile as f: result = f.readvalue(self.nxfilepath, idx=idx) if 'mask' in self.attrs: try: mask = self.nxgroup[self.attrs['mask']] result = np.ma.array(result, mask=f.readvalue(mask.nxfilepath, idx=idx)) except KeyError: pass return result def _put_filedata(self, value, idx=()): """ Write the specified slice to the NeXus file. Parameters ---------- value Slice values to be written. idx : slice, optional Slice indices, by default (). """ with self.nxfile as f: if isinstance(value, np.ma.MaskedArray): if self.mask is None: self._create_mask() f.writevalue(self.nxpath, value.data, idx=idx) f.writevalue(self.mask.nxpath, value.mask, idx=idx) else: f.writevalue(self.nxpath, value, idx=idx) def _get_memdata(self, idx=()): """Retrieve data from HDF5 core memory file. Parameters ---------- idx : slice, optional Slice indices, by default (). Returns ------- array_like Array containing the slice values. """ result = self._memfile['data'][idx] if 'mask' in self._memfile: mask = self._memfile['mask'][idx] if mask.any(): result = np.ma.array(result, mask=mask) return result def _put_memdata(self, value, idx=()): """ Write the specified slice to HDF5 core memory file. Parameters ---------- value Slice values to be written. idx : slice, optional Slice indices, by default (). """ if self._memfile is None: self._create_memfile() if 'data' not in self._memfile: self._create_memdata() self._memfile['data'][idx] = value if isinstance(value, np.ma.MaskedArray): if 'mask' not in self._memfile: self._create_memmask() self._memfile['mask'][idx] = value.mask def _create_memfile(self): """Create an HDF5 core memory file to store the data.""" import tempfile self._memfile = h5.File(tempfile.mkstemp(suffix='.nxs')[1], mode='r+', driver='core', backing_store=False).file def _create_memdata(self): """Create an HDF5 core memory dataset to store the data.""" if self._shape is not None and self._dtype is not None: if self._memfile is None: self._create_memfile() self._memfile.create_dataset('data', shape=self._shape, dtype=self._dtype, **self._h5opts) else: raise NeXusError( "Cannot allocate to field before setting shape and dtype") def _create_memmask(self): """Create an HDF5 core memory dataset to store the data mask.""" if self._shape is not None: if self._memfile is None: self._create_memfile() self._memfile.create_dataset('mask', shape=self._shape, dtype=bool, **self._h5opts) else: raise NeXusError("Cannot allocate mask before setting shape") def _create_mask(self): """Create a data mask field if none exists.""" if self.nxgroup is not None: if 'mask' in self.attrs: mask_name = self.attrs['mask'] if mask_name in self.nxgroup: return mask_name mask_name = f'{self.nxname}_mask' self.nxgroup[mask_name] = NXfield(shape=self._shape, dtype=bool, fillvalue=False) self.attrs['mask'] = mask_name return mask_name return None def _mask_data(self, idx=()): """ Add a data mask covering the specified indices. Parameters ---------- idx : slice, optional Slice indices, by default (). """ mask_name = self._create_mask() if mask_name: self.nxgroup[mask_name][idx] = True elif self._memfile: if 'mask' not in self._memfile: self._create_memmask() self._memfile['mask'][idx] = True if self._value is not None: if not isinstance(self._value, np.ma.MaskedArray): self._value = np.ma.array(self._value) self._value[idx] = np.ma.masked def _get_uncopied_data(self, idx=None): """ Retrieve copied data from a NeXus file. The HDF5 copy command is used to copy the data directly to a new file. If no file is opened, it is copied to a core memory file. Parameters ---------- idx : slice, optional Slice indices, by default None. Returns ------- array_like Array containing the copied values. """ _file, _path = self._uncopied_data with _file as f: if idx: return f.readvalue(_path, idx=idx) else: if self.nxfilemode == 'rw': f.copy(_path, self.nxpath) else: self._create_memfile() f.copy(_path, self._memfile, name='data') self._uncopied_data = None if (_getsize(self.shape) * np.dtype(self.dtype).itemsize <= NX_CONFIG['memory']*1000*1000): return f.readvalue(_path) else: return None def __deepcopy__(self, memo={}): """Return a deep copy of the field and its attributes.""" obj = self dpcpy = obj.__class__() memo[id(self)] = dpcpy dpcpy._name = copy(self.nxname) dpcpy._dtype = copy(obj.dtype) dpcpy._shape = copy(obj.shape) dpcpy._h5opts = copy(obj._h5opts) dpcpy._changed = True dpcpy._memfile = obj._memfile dpcpy._uncopied_data = obj._uncopied_data if obj._value is not None: dpcpy._value = copy(obj._value) dpcpy._memfile = dpcpy._uncopied_data = None elif obj.nxfilemode: dpcpy._uncopied_data = (obj.nxfile, obj.nxpath) for k, v in obj.attrs.items(): dpcpy.attrs[k] = copy(v) if 'target' in dpcpy.attrs: del dpcpy.attrs['target'] dpcpy._group = None return dpcpy def serialize(self): """Serialize the field to a dictionary.""" return {'name': self.nxname, 'class': self.__class__.__name__, 'target': self._target, 'filename': self._filename, 'mode': self._mode, 'proxy': self._proxy, 'abspath': self._abspath, 'soft': self._soft, 'dtype': str(self.dtype), 'shape': self.shape, 'value': self._value, 'vpath': self._vpath, 'vfiles': self._vfiles, 'vshape': self._vshape, 'vidx': self._vidx, 'h5opts': self._h5opts, 'entries': None, 'attrs': {k: v._value for k, v in self.attrs.items()}} @classmethod def deserialize(cls, serialized_field): """Deserialize the field from a dictionary.""" target_cls = _getclass(serialized_field['class']) obj = super(target_cls, target_cls).__new__(target_cls) obj._name = serialized_field['name'] obj._class = serialized_field['class'] obj._target = serialized_field['target'] obj._filename = serialized_field['filename'] obj._mode = serialized_field['mode'] obj._proxy = serialized_field['proxy'] obj._abspath = serialized_field['abspath'] obj._soft = serialized_field['soft'] if 'link' in serialized_field['class']: obj.initialize_link() else: obj._dtype = np.dtype(serialized_field['dtype']) obj._shape = serialized_field['shape'] obj._value = serialized_field['value'] obj._h5opts = serialized_field['h5opts'] obj._attrs = AttrDict(obj) obj._attrs._setattrs(serialized_field['attrs']) if target_cls == NXvirtualfield: obj._vpath = serialized_field['vpath'] obj._vfiles = serialized_field['vfiles'] obj._vshape = serialized_field['vshape'] obj._vidx = serialized_field['vidx'] return obj def __iter__(self): """Implement key iteration.""" try: return self.nxvalue.__iter__() except AttributeError: return self def __next__(self): """Implements key iteration.""" try: return self.nxvalue.__next__() except AttributeError: raise StopIteration def __contains__(self, key): """Implement 'k in d' test using the NXfield `nxvalue`.""" return self.nxvalue.__contains__(key) def __len__(self): """Return the length of the NXfield data.""" if is_string_dtype(self.dtype): return len(self.nxvalue) elif self.shape == (): return 1 else: return self.shape[0] def any(self): """Return False if all values are 0 or False, True otherwise.""" try: return np.any(self.nxvalue) except TypeError: raise NeXusError("Invalid field type for numeric comparisons") def all(self): """Return False if any values are 0 or False, True otherwise.""" try: return np.all(self.nxvalue) except TypeError: raise NeXusError("Invalid field type for numeric comparisons") def index(self, value, max=False): """ Return the index of a value in a one-dimensional NXfield. The index is less than (greater than) or equal to the given value for a monotonically increasing (decreasing) array. Parameters ---------- value : int or float Value to be indexed. max : bool, optional True if the index is greater than (less than) or equal to the value for a monotonically increasing (decreasing) array, by default False. Returns ------- int Index of value. Examples -------- >>> field NXfield([ 0. 0.1 0.2 ..., 0.8 0.9 1. ]) >>> field.index(0.1) 1 >>> field.index(0.11) 1 >>> field.index(0.11, max=True) 2 >>> reverse_field NXfield([ 1. 0.9 0.8 ..., 0.2 0.1 0. ]) >>> reverse_field.index(0.89) 1 >>> reverse_field.index(0.89, max=True) 2 The value is considered to be equal to an NXfield element's value if it differs by less than 1% of the step size to the neighboring element. """ if self.ndim != 1: raise NeXusError( "NXfield must be one-dimensional to use the index function") if self.nxdata[-1] < self.nxdata[0]: flipped = True else: flipped = False if max: if flipped: idx = np.max(len(self.nxdata) - len(self.nxdata[self.nxdata < value])-1, 0) else: idx = np.max(len(self.nxdata) - len(self.nxdata[self.nxdata > value])-1, 0) try: diff = value - self.nxdata[idx] step = self.nxdata[idx+1] - self.nxdata[idx] if abs(diff/step) > 0.01: idx = idx + 1 except IndexError: pass else: if flipped: idx = len(self.nxdata[self.nxdata > value]) else: idx = len(self.nxdata[self.nxdata < value]) try: diff = value - self.nxdata[idx-1] step = self.nxdata[idx] - self.nxdata[idx-1] if abs(diff/step) < 0.99: idx = idx - 1 except IndexError: pass return int(np.clip(idx, 0, len(self.nxdata)-1)) def __array__(self, *args, **kwargs): """Cast the NXfield as a NumPy array.""" return np.asarray(self.nxdata, *args, **kwargs) def __array_wrap__(self, value, context=None, return_scalar=False): """Transform the array resulting from a ufunc to an NXfield.""" return NXfield(value, name=self.nxname) def __int__(self): """Cast a scalar field as an integer.""" return int(self.nxvalue) def __float__(self): """Cast a scalar field as floating point number.""" return float(self.nxvalue) def __complex__(self): """Cast a scalar field as a complex number.""" return complex(self.nxvalue) def __neg__(self): """Return the negative value of a scalar field.""" return -self.nxvalue def __abs__(self): """Return the absolute value of a scalar field.""" return abs(self.nxvalue) def __eq__(self, other): """Return true if the values of another NXfield are the same.""" if id(self) == id(other): return True elif isinstance(other, NXfield): if (isinstance(self.nxvalue, np.ndarray) and isinstance(other.nxvalue, np.ndarray)): try: return np.array_equal(self, other) except ValueError: return False else: return self.nxvalue == other.nxvalue else: return self.nxvalue == other def __ne__(self, other): """Return true if the values of another NXfield are not the same.""" if isinstance(other, NXfield): if (isinstance(self.nxvalue, np.ndarray) and isinstance(other.nxvalue, np.ndarray)): try: return not np.array_equal(self, other) except ValueError: return True else: return self.nxvalue != other.nxvalue else: return self.nxvalue != other def __lt__(self, other): """Return true if self.nxvalue < other[.nxvalue].""" if isinstance(other, NXfield): return self.nxvalue < other.nxvalue else: return self.nxvalue < other def __le__(self, other): """Return true if self.nxvalue <= other[.nxvalue].""" if isinstance(other, NXfield): return self.nxvalue <= other.nxvalue else: return self.nxvalue <= other def __gt__(self, other): """Return true if self.nxvalue > other[.nxvalue].""" if isinstance(other, NXfield): return self.nxvalue > other.nxvalue else: return self.nxvalue > other def __ge__(self, other): """Return true if self.nxvalue >= other[.nxvalue].""" if isinstance(other, NXfield): return self.nxvalue >= other.nxvalue else: return self.nxvalue >= other def __add__(self, other): """Return the sum of the field and a field/number.""" if isinstance(other, NXfield): return NXfield(value=self.nxdata+other.nxdata, name=self.nxname, attrs=self.safe_attrs) else: return NXfield(value=self.nxdata+other, name=self.nxname, attrs=self.safe_attrs) def __radd__(self, other): """Return the sum of the field and a field/number. This variant makes __add__ commutative. """ return self.__add__(other) def __sub__(self, other): """Return the field subtracting a field/number.""" if isinstance(other, NXfield): return NXfield(value=self.nxdata-other.nxdata, name=self.nxname, attrs=self.safe_attrs) else: return NXfield(value=self.nxdata-other, name=self.nxname, attrs=self.safe_attrs) def __rsub__(self, other): """Returns the field after subtracting a field/number.""" if isinstance(other, NXfield): return NXfield(value=other.nxdata-self.nxdata, name=self.nxname, attrs=self.safe_attrs) else: return NXfield(value=other-self.nxdata, name=self.nxname, attrs=self.safe_attrs) def __mul__(self, other): """Return the product of the field with a field/number.""" if isinstance(other, NXfield): return NXfield(value=self.nxdata*other.nxdata, name=self.nxname, attrs=self.safe_attrs) else: return NXfield(value=self.nxdata*other, name=self.nxname, attrs=self.safe_attrs) def __rmul__(self, other): """ Return the product of the field with a field/number. This variant makes __mul__ commutative. """ return self.__mul__(other) def __truediv__(self, other): """Returns the field divided by a field/number.""" if isinstance(other, NXfield): return NXfield(value=self.nxdata/other.nxdata, name=self.nxname, attrs=self.safe_attrs) else: return NXfield(value=self.nxdata/other, name=self.nxname, attrs=self.safe_attrs) def __rtruediv__(self, other): """Return the inverse of the field divided by a field/number.""" if isinstance(other, NXfield): return NXfield(value=other.nxdata/self.nxdata, name=self.nxname, attrs=self.safe_attrs) else: return NXfield(value=other/self.nxdata, name=self.nxname, attrs=self.safe_attrs) def __pow__(self, power): """Return the field raised to the specified power.""" return NXfield(value=pow(self.nxdata, power), name=self.nxname, attrs=self.safe_attrs) def min(self, axis=None, **kwargs): """Return the minimum value of the array ignoring NaNs.""" return np.nanmin(self.nxdata[self.nxdata > -np.inf], axis, **kwargs) def max(self, axis=None, **kwargs): """Return the maximum value of the array ignoring NaNs.""" return np.nanmax(self.nxdata[self.nxdata < np.inf], axis, **kwargs) def sum(self, axis=None, **kwargs): """Return the sum of field values. Parameters ---------- axis : int or tuple of ints, optional Axis or axes to be summed over, by default all axes. Returns ------- NXfield Summed values. """ return NXfield(np.sum(self.nxdata, axis), name=self.nxname, attrs=self.safe_attrs, **kwargs) def average(self, **kwargs): """Return the average of field values. Returns ------- NXfield The average of the field. """ return NXfield(np.average(self.nxdata, **kwargs), name=self.nxname, attrs=self.safe_attrs) def mean(self, **kwargs): """Return the mean value of the field. Returns ------- NXfield The mean of the field. """ return NXfield(np.mean(self.nxdata, **kwargs), name=self.nxname, attrs=self.safe_attrs) def var(self, **kwargs): """ Return the variance of the field. Returns ------- NXfield The variance of the field. """ return NXfield(np.var(self.nxdata, **kwargs), name=self.nxname, attrs=self.safe_attrs) def std(self, **kwargs): """ Return the standard deviation of the field. Returns ------- NXfield The standard deviation of the field. """ return NXfield(np.std(self.nxdata, **kwargs), name=self.nxname, attrs=self.safe_attrs) def moment(self, order=1, **kwargs): """ Return the moments about the mean of the field. Other parameters are passed to `scipy.stats.moment` Parameters ---------- order : int, optional Order of the calculated moment, by default 1. Returns ------- NXfield Value of field moment. """ from scipy.stats import moment try: return NXfield(moment(self.nxdata, order=order, **kwargs), name=self.nxname, attrs=self.safe_attrs) except TypeError: return NXfield(moment(self.nxdata, order, **kwargs), name=self.nxname, attrs=self.safe_attrs) def reshape(self, shape): """Return a field with the specified shape.""" return NXfield(value=self.nxdata, name=self.nxname, shape=shape, attrs=self.safe_attrs) def transpose(self, axes=None): """ Return an field containing the transpose of the data array. Parameters ---------- axes : tuple or list of ints, optional If specified, it must be a tuple or list which contains a permutation of [0,1,..,N-1] where N is the number of axes. If not specified, defaults to range(self.ndim)[::-1]. Returns ------- NXfield NXfield containing the transposed array. """ value = self.nxdata.transpose(axes) return NXfield(value=value, name=self.nxname, shape=value.shape, attrs=self.safe_attrs) @property def T(self): return self.transpose() def centers(self): """ Return a field with bin centers. This is used for one-dimensional fields containing axes that are stored as bin boundaries. """ return NXfield((self.nxdata[:-1]+self.nxdata[1:])/2, name=self.nxname, attrs=self.safe_attrs) def boundaries(self): """ Return a field with bin boundaries. This is used for one-dimensional fields containing axes that are stored as bin centers. """ ax = self.nxdata start = ax[0] - (ax[1] - ax[0])/2 end = ax[-1] + (ax[-1] - ax[-2])/2 return NXfield(np.concatenate((np.atleast_1d(start), (ax[:-1] + ax[1:])/2, np.atleast_1d(end))), name=self.nxname, attrs=self.safe_attrs) def add(self, data, offset): """ Add a slab into the data array. Parameters ---------- data : array_like Slab values to be added to the field. offset : tuple Offsets containing the lowest slab indices. """ idx = tuple(slice(i, i+j) for i, j in zip(offset, data.shape)) if isinstance(data, NXfield): self[idx] += data.nxdata.astype(self.dtype) else: self[idx] += data.astype(self.dtype) def walk(self): yield self def replace(self, value): """ Replace the value of a field. If the size or dtype of the field differs from an existing field within a saved group, the original field will be deleted and replaced by the newone. Otherwise, the field values are updated. """ group = self.nxgroup if group is None: raise NeXusError("The field must be a member of a group") if isinstance(value, NXfield): del group[self.nxname] group[self.nxname] = value elif is_text(value): if self.dtype == string_dtype: self.nxdata = value group.update() else: del group[self.nxname] group[self.nxname] = NXfield(value, attrs=self.attrs) else: value = np.asarray(value) if value.shape == self.shape and value.dtype == self.dtype: self.nxdata = value group.update() else: del group[self.nxname] group[self.nxname] = NXfield(value, attrs=self.attrs) @property def nxaxes(self): """ List of fields containing axes. If the NXfield does not have the 'axes' attribute but is defined as the signal in its parent group, a list of the parent group's axes will be returned. """ def invalid_axis(axis): return axis.size != self.shape[i] and axis.size != self.shape[i]+1 def empty_axis(i): return NXfield(np.arange(self.shape[i]), name=f'Axis{i}') def plot_axis(axis): return NXfield(axis.nxvalue, name=axis.nxname, attrs=axis.attrs) if self.nxgroup: if 'axes' in self.attrs: axis_names = _readaxes(self.attrs['axes']) elif 'axes' in self.nxgroup.attrs: axis_names = _readaxes(self.nxgroup.attrs['axes']) else: axis_names = ['.'] * self.plot_rank if len(axis_names) > self.plot_rank: axis_names = axis_names[:self.plot_rank] axes = [] for i, axis_name in enumerate(axis_names): axis_name = axis_name.strip() if (axis_name not in self.nxgroup or invalid_axis(self.nxgroup[axis_name])): axes.append(empty_axis(i)) else: axes.append(plot_axis(self.nxgroup[axis_name])) return axes else: return [empty_axis(i) for i in range(self.plot_rank)] def valid_axes(self, axes): """ Return True if the axes are consistent with the field. It checks that all the axes are one-dimensional, and that the size of each axis is equal to or one greater than the field dimension. Parameters ---------- axes : list List of NXfields Notes ----- The function removes scalar axes before the check even though these are returned by the nxaxes property. That is because ndim is 0 for scalars. They are automatically removed when plotting so this does not invalidate the check. """ if not is_iterable(axes): axes = [axes] plot_axes = [axis for axis in axes if axis.size >= 1] axis_shape = [axis.size for axis in plot_axes] if (all(axis.ndim == 1 for axis in plot_axes) and len([x for x, y in zip(self.plot_shape, axis_shape) if x == y or x == y-1]) == self.plot_rank): return True else: return False @property def nxvalue(self): """NXfield value. This is the value stored in the NeXus file, with the following exceptions. 1) Size-1 arrays are returned as scalars. 2) String or byte arrays are returns as a list of strings. Notes ----- If unmodified values are required, use the `nxdata` property. """ _value = self.nxdata if _value is None: return None elif (self.dtype is not None and (self.dtype.type == np.bytes_ or self.dtype.type == np.str_ or self.dtype == string_dtype)): if self.shape == (): return text(_value) elif self.shape == (1,): return text(_value[0]) else: return [text(value) for value in _value[()]] elif self.shape == (1,): return _value.item() else: return _value @property def nxdata(self): """NXfield data as stored in a file. If the requested data is larger than NX_MEMORY, the return value is `None`. """ if self._value is None: if self.dtype is None or self.shape is None: return None if (_getsize(self.shape) * np.dtype(self.dtype).itemsize <= NX_CONFIG['memory']*1000*1000): try: if self.nxfilemode: self._value = self._get_filedata() elif self._uncopied_data: self._value = self._get_uncopied_data() if self._memfile: self._value = self._get_memdata() except Exception: raise NeXusError(f"Cannot read data for '{self.nxname}'") if self._value is not None: self._value.shape = self.shape else: raise NeXusError("Use slabs to access data larger than " f"NX_MEMORY={NX_CONFIG['memory']} MB") if self.mask is not None: try: if isinstance(self.mask, NXfield): mask = self.mask.nxdata if isinstance(self._value, np.ma.MaskedArray): self._value.mask = mask else: self._value = np.ma.array(self._value, mask=mask) except Exception: pass return self._value @nxdata.setter def nxdata(self, value): if self.nxfilemode == 'r': raise NeXusError("NeXus file is locked") else: self._value, self._dtype, self._shape = _getvalue( value, self._dtype, self._shape) if self._memfile: self._put_memdata(self._value) @property def nxtitle(self): """ Title as a string. If there is no title attribute in the parent group, the group's path is returned. """ root = self.nxroot if root.nxname != '' and root.nxname != 'root': return (root.nxname + '/' + self.nxpath.lstrip('/')).rstrip('/') else: fname = self.nxfilename if fname is not None: return str(Path(fname).name) + ':' + self.nxpath else: return self.nxpath @property def nxunits(self): """Units of the field.""" if 'units' in self.attrs: return self.attrs['units'] else: return '' @nxunits.setter def nxunits(self, value): if self.nxfilemode == 'r': raise NeXusError("NeXus file opened as readonly") elif self.is_linked(): raise NeXusError("Cannot modify an item in a linked group") self.attrs['units'] = value @property def mask(self): """NXfield's mask as an array. Only works if the NXfield is in a group and has the 'mask' attribute set or if the NXfield array is defined as a masked array. """ if 'mask' in self.attrs: if self.nxgroup and self.attrs['mask'] in self.nxgroup: return self.nxgroup[self.attrs['mask']] if self._value is None and self._memfile: if 'mask' in self._memfile: return self._memfile['mask'] if self._value is not None and isinstance(self._value, np.ma.MaskedArray): return self._value.mask return None @mask.setter def mask(self, value): if self.nxfilemode == 'r': raise NeXusError("NeXus file opened as readonly") elif self.is_linked(): raise NeXusError("Cannot modify an item in a linked group") if 'mask' in self.attrs: if self.nxgroup: mask_name = self.attrs['mask'] if mask_name in self.nxgroup: self.nxgroup[mask_name][()] = value else: del self.attrs['mask'] elif self._value is None: if self._memfile: if 'mask' not in self._memfile: self._create_memmask() self._memfile['mask'][()] = value if self._value is not None: if isinstance(self._value, np.ma.MaskedArray): self._value.mask = value else: self._value = np.ma.array(self._value, mask=value) def valid_attributes(self, group=None, definitions=None, deprecated=False): """ Return a list of valid attribute names for the NeXus field. Parameters ---------- group : NXgroup, optional The group containing the field. If not provided, the field's parent group is used. definitions : str, optional The path to the directory containing the NeXus base class definitions (default is None). deprecated : bool, optional True if deprecated attributes should be included Returns ------- list A list of valid attributes for the NeXus field. """ if group is None: group = self.nxgroup if group: valid_fields = group.valid_fields(definitions) if self.nxname in valid_fields: if 'attribute' in valid_fields[self.nxname]: attributes = valid_fields[self.nxname]['attribute'] if deprecated: return attributes else: return remove_deprecations(attributes) return {} def valid_values(self, group=None, attribute=None, definitions=None): """ Return a list of valid values for the NeXus field or attribute. Parameters ---------- group : NXgroup, optional The group containing the field. If not provided, the field's parent group is used. attribute : str, optional The attribute name. If not provided, the field's value is checked. definitions : str, optional The path to the directory containing the NeXus base class definitions (default is None). Returns ------- list A list of valid values for the NeXus field or attribute. """ if group is None: group = self.nxgroup if group: valid_fields = group.valid_fields(definitions) if attribute is not None: if 'attribute' in valid_fields[self.nxname]: valid_attributes = valid_fields[self.nxname]['attribute'] if (attribute in valid_attributes and 'enumeration' in valid_attributes[attribute]): return valid_attributes[attribute]['enumeration'] elif (self.nxname in valid_fields and 'enumeration' in valid_fields[self.nxname]): return valid_fields[self.nxname]['enumeration'] return [] def resize(self, shape, axis=None): """ Resize the NXfield. Parameters ---------- shape : tuple of ints Requested shape. axis : int, optional Axis whose length is to be resized, by default None """ if axis is not None: if not (axis >= 0 and axis < self.ndim): raise NeXusError(f"Invalid axis (0 to {self.ndim-1} allowed)") try: newlen = int(shape) except TypeError: raise NeXusError( "Argument must be a single integer if axis is specified") shape = list(self._shape) shape[axis] = newlen if self.checkshape(shape): if self.nxfilemode: with self.nxfile as f: f[self.nxpath].shape = shape self._value = None elif self._memfile: self._memfile['data'].shape = shape self._value = None else: raise NeXusError("Shape incompatible with current NXfield") self._shape = shape if self._value is not None: self._value.resize(self._shape, refcheck=False) def checkshape(self, shape): """ True if the shape argument is compatible with the field.""" _maxshape = self.maxshape if _maxshape and not _checkshape(shape, _maxshape): return False elif self.nxfilemode or self._memfile: return _checkshape(self._shape, shape) else: return True @property def shape(self): """Shape of the field.""" try: return _getshape(self._shape) except TypeError: return () @shape.setter def shape(self, value): self.resize(value) @property def dtype(self): """Dtype of the field.""" return self._dtype @dtype.setter def dtype(self, value): if self.nxfilemode: raise NeXusError( "Cannot change the dtype of a field already stored in a file") elif self._memfile: raise NeXusError( "Cannot change the dtype of a field already in core memory") self._dtype = _getdtype(value) if self._value is not None: self._value = np.asarray(self._value, dtype=self._dtype) def get_h5opt(self, name): """ Return the option set for the h5py dataset. Parameters ---------- name : str Name of the h5py option. """ if self.nxfilemode: with self.nxfile as f: self._h5opts[name] = getattr(f[self.nxfilepath], name) elif self._memfile: self._h5opts[name] = getattr(self._memfile['data'], name) if name in self._h5opts: return self._h5opts[name] else: return None def set_h5opt(self, name, value): """ Set the value of a h5py option. Parameters ---------- name : str Name of option. value Option value. """ if self.nxfilemode: raise NeXusError(f"Cannot change the {name} of a field " "already stored in a file") elif self._memfile: raise NeXusError(f"Cannot change the {name} of a field " "already in core memory") if value is not None: self._h5opts[name] = value @property def compression(self): """NXfield compression.""" return self.get_h5opt('compression') @compression.setter def compression(self, value): self.set_h5opt('compression', value) @property def compression_opts(self): """NXfield compression options.""" return self.get_h5opt('compression_opts') @compression_opts.setter def compression_opts(self, value): self.set_h5opt('compression_opts', value) @property def fillvalue(self): """NXfield fill value.""" return self.get_h5opt('fillvalue') @fillvalue.setter def fillvalue(self, value): self.set_h5opt('fillvalue', value) @property def fletcher32(self): """True if Fletcher32 checksum used.""" return self.get_h5opt('fletcher32') @fletcher32.setter def fletcher32(self, value): self.set_h5opt('fletcher32', value) @property def chunks(self): """NXfield chunk size.""" return self.get_h5opt('chunks') @chunks.setter def chunks(self, value): if is_iterable(value) and len(value) != self.ndim: raise NeXusError( "Number of chunks does not match the no. of array dimensions") self.set_h5opt('chunks', value) @property def maxshape(self): """NXfield maximum shape.""" return self.get_h5opt('maxshape') @maxshape.setter def maxshape(self, value): self.set_h5opt('maxshape', _getmaxshape(value, self.shape)) @property def scaleoffset(self): """NXfield scale offset.""" return self.get_h5opt('scaleoffset') @scaleoffset.setter def scaleoffset(self, value): self.set_h5opt('scaleoffset', value) @property def shuffle(self): """True if the shuffle filter enabled.""" return self.get_h5opt('shuffle') @shuffle.setter def shuffle(self, value): self.set_h5opt('shuffle', value) @property def ndim(self): """Rank of the NXfield.""" try: return len(self.shape) except TypeError: return 0 @property def size(self): """Total size of the NXfield.""" return _getsize(self.shape) @property def nbytes(self): """Number of bytes in the NXfield array.""" return self.size * self.dtype.itemsize @property def human_size(self): """Human readable string of the number of bytes in the field.""" import math unit = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB'] size = self.nbytes magnitude = int(math.floor(math.log(size, 1000))) val = size / math.pow(1000, magnitude) return f"{val:3.1f}{unit[magnitude]}" @property def safe_attrs(self): """Attributes that can be safely copied to derived fields.""" return {key: self.attrs[key] for key in self.attrs if (key != 'target' and key != 'signal' and key != 'axes')} @property def reversed(self): """True if the one-dimensional field has decreasing values.""" if self.ndim == 1 and self.nxdata[-1] < self.nxdata[0]: return True else: return False @property def plot_shape(self): """ Shape of NXfield for plotting. Size-1 axes are removed from the shape for multidimensional data. """ try: _shape = list(self.shape) if len(_shape) > 1: while 1 in _shape: _shape.remove(1) return tuple(_shape) except Exception: return () @property def plot_rank(self): """Rank of the field when plotting.""" return len(self.plot_shape) def is_numeric(self): """True if the field contains numeric data.""" return not is_string_dtype(self.dtype) def is_string(self): """True if the field contains strings.""" return is_string_dtype(self.dtype) def is_plottable(self): """True if the field is plottable.""" if self.plot_rank > 0: return True else: return False def is_image(self): """True if the field is compatible with an RGB(A) image.""" return self.ndim == 3 and (self.shape[2] == 3 or self.shape[2] == 4) def plot(self, fmt='', xmin=None, xmax=None, ymin=None, ymax=None, vmin=None, vmax=None, **kwargs): """ Plot the NXfield. The format argument is used to set the color and type of the markers or lines for one-dimensional plots, using the standard Matplotlib syntax. The default is set to blue circles. All keyword arguments accepted by matplotlib.pyplot.plot can be used to customize the plot. Parameters ---------- fmt : str, optional Matplotlib format string, by default '' xmin : float, optional Minimum x-value in plot, by default None xmax : float, optional Maximum x-value in plot, by default None ymin : float, optional Minimum y-value in plot, by default None ymax : float, optional Maximum y-value in plot, by default None vmin : float, optional Minimum signal value for 2D plots, by default None vmax : float, optional Maximum signal value for 2D plots, by default None Notes ----- In addition to the Matplotlib keyword arguments, the following are defined :: log = True - plot the intensity on a log scale logy = True - plot the y-axis on a log scale logx = True - plot the x-axis on a log scale over = True - plot on the current figure image = True - plot as an RGB(A) image """ if not self.exists(): raise NeXusError( f"'{Path(self.nxfilename).resolve()}' does not exist") try: from __main__ import plotview if plotview is None: raise ImportError except ImportError: from .plot import plotview if self.is_plottable(): data = NXdata(self, self.nxaxes, title=self.nxtitle) if ('interpretation' in self.attrs and 'rgb' in self.attrs['interpretation'] and self.is_image()): kwargs['image'] = True if self.nxroot.nxclass == 'NXroot': signal_path = self.nxroot.nxname + self.nxpath else: signal_path = self.nxpath data.attrs['signal_path'] = signal_path plotview.plot(data, fmt=fmt, xmin=None, xmax=None, ymin=None, ymax=None, vmin=None, vmax=None, **kwargs) else: raise NeXusError("NXfield not plottable") def oplot(self, fmt='', **kwargs): """Plot the field over the current figure.""" self.plot(fmt=fmt, over=True, **kwargs) def logplot(self, fmt='', xmin=None, xmax=None, ymin=None, ymax=None, vmin=None, vmax=None, **kwargs): """Plot the field on a log scale.""" self.plot(fmt=fmt, log=True, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, vmin=vmin, vmax=vmax, **kwargs) def implot(self, fmt='', xmin=None, xmax=None, ymin=None, ymax=None, vmin=None, vmax=None, **kwargs): """Plots the field as an RGB(A) image.""" if self.plot_rank > 2 and (self.shape[-1] == 3 or self.shape[-1] == 4): self.plot(fmt=fmt, image=True, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, vmin=vmin, vmax=vmax, **kwargs) else: raise NeXusError("Invalid shape for RGB(A) image") SDS = NXfield # For backward compatibility class NXvirtualfield(NXfield): """ NeXus Virtual Field This creates a field that is stored as an HDF5 virtual dataset defined by the file path and file names of the source files. """ def __init__(self, target, files, name='unknown', shape=None, idx=None, dtype=None, group=None, attrs=None, abspath=False, create_vds=True, **kwargs): """ Initialize the field containing the virtual dataset. Parameters ---------- target : str or NXfield The field to be added from each source dataset. If it is a string, it defines the path to the field within each source file. If it is a NXfield, the path to the field is used, and its shape and dtype override their respective arguments. files : list of str Paths to the source files. These must either be absolute paths or, if abspath is False, a valid relative path. shape : tuple, optional Shape of each source field, by default None. If None, the shape is derived from the target, which must be a NXfield. idx: slice, optional Slice indices of the target field, by default None dtype : dtype, optional Data type of the virtual dataset, by default None. If None, the data type is derived from the target, which must be a NXfield. group : [type], optional Parent group of NeXus field, by default None attrs : [type], optional Dictionary containing NXfield attributes, by default None """ if isinstance(target, NXfield): shape = target.shape dtype = target.dtype target = target.nxfilepath elif shape is None: raise NeXusError('The shape has not been specified') self._vshape = shape self._vidx = idx self._vpath = target if abspath: self._vfiles = [Path(f).resolve() for f in files] else: self._vfiles = files if idx: shape = (len(self._vfiles),) + slice_shape(idx, self._vshape) else: shape = (len(self._vfiles),) + self._vshape super().__init__(name=name, shape=shape, dtype=dtype, group=group, attrs=attrs, **kwargs) if create_vds and shape and dtype: self._create_virtual_data(shape, idx=idx) def _create_virtual_data(self, shape, idx=None): """ Create the virtual dataset from the source files and layout. Parameters ---------- files : list of str Paths to the source files. path : str Path to the field within each source file. shape : tuple Shape of the virtual field in the source files. idx : tuple, optional Slice indices of the source fields, by default None. """ maxshape = (None,) + shape[1:] layout = h5.VirtualLayout(shape=shape, dtype=self.dtype, maxshape=maxshape) if idx is None: idx = Ellipsis for i, f in enumerate(self._vfiles): vsource = h5.VirtualSource(f, self._vpath, shape=self._vshape) layout[i] = vsource[idx] self._create_memfile() self._memfile.create_virtual_dataset('data', layout) def __deepcopy__(self, memo={}): """Return a deep copy of the virtual field and attributes.""" obj = self dpcpy = obj.__class__(self._vpath, self._vfiles, shape=self._vshape, idx=self._vidx, dtype=self.dtype, create_vds=False) memo[id(self)] = dpcpy dpcpy._name = copy(self.nxname) dpcpy._dtype = copy(obj.dtype) dpcpy._shape = copy(obj.shape) dpcpy._vshape = copy(obj._vshape) dpcpy._vidx = copy(obj._vidx) dpcpy._vpath = copy(obj._vpath) dpcpy._vfiles = copy(obj._vfiles) shape = (len(obj._vfiles),) + slice_shape(obj._vidx, obj._vshape) dpcpy._create_virtual_data(shape=shape, idx=obj._vidx) dpcpy._h5opts = copy(obj._h5opts) dpcpy._changed = True dpcpy._uncopied_data = None for k, v in obj.attrs.items(): dpcpy.attrs[k] = copy(v) if 'target' in dpcpy.attrs: del dpcpy.attrs['target'] dpcpy._group = None return dpcpy class NXgroup(NXobject): """ NeXus group. This is a subclass of NXobject and is the base class for the specific NeXus group classes, *e.g.*, NXentry, NXsample, NXdata. Parameters ---------- name : str The name of the NXgroup. If the NXgroup is initialized as the attribute of a parent group, the name is automatically set to the name of this attribute. If 'nxclass' is specified and has the usual prefix 'NX', the default name is the class name without this prefix. nxclass : str The class of the NXgroup. entries : dict A dictionary containing a list of group entries. This is an alternative way of adding group entries to the use of keyword arguments. group : NXgroup The parent NeXus group, which is accessible as the group attribute 'group'. If the group is initialized as the attribute of a parent group, this is set to the parent group. args : NXfield or NXgroup Positional arguments must be valid NeXus objects, either an NXfield or a NeXus group. These are added without modification as children of this group. kwargs : dict Keyword arguments are used to add children to the group. The keyword values must be valid NeXus objects, either NXfields or NXgroups. The keys are used to set the names within the group. Attributes ---------- nxclass : str The class of the NXgroup. nxname : str The name of the NXfield. entries : dict A dictionary of all the NeXus objects contained within an NXgroup. attrs : AttrDict A dictionary of all the NeXus attributes, *i.e.*, attribute with class NXattr. nxpath : str The path to this object with respect to the root of the NeXus tree. For NeXus data read from a file, this will be a group of class NXroot, but if the NeXus tree was defined interactively, it can be any valid NXgroup. nxroot : NXgroup The root object of the NeXus tree containing this object. For NeXus data read from a file, this will be a group of class NXroot, but if the NeXus tree was defined interactively, it can be any valid NXgroup. Examples -------- Just as in a NeXus file, NeXus groups can contain either data or other groups, represented by NXfield and NXgroup objects respectively. To distinguish them from regular Python attributes, all NeXus objects are stored in the 'entries' dictionary of the NXgroup. However, they can usually be assigned or referenced as if they are Python attributes, *i.e.*, using the dictionary name directly as the group attribute name, as long as this name is not the same as one of the Python attributes defined above or as one of the NXfield Python attributes. 1) Assigning a NeXus object to a NeXus group In the example below, after assigning the NXgroup, the following three NeXus object assignments to entry.sample are all equivalent: >>> entry.sample = NXsample() >>> entry.sample['temperature'] = NXfield(40.0) >>> entry['sample/temperature'] = NXfield(40.0) >>> entry.sample.temperature = 40.0 >>> entry.sample.temperature NXfield(40.0) If the assigned value is not a valid NXobject, then it is cast as an NXfield with a type determined from the Python data type. >>> entry.sample.temperature = 40.0 >>> entry.sample.temperature NXfield(40.0) >>> entry.data.data.x=np.linspace(0,10,11).astype('float32') >>> entry.data.data.x NXfield([ 0. 1. 2. ..., 8. 9. 10.]) 2) Referencing a NeXus object in a NeXus group If the name of the NeXus object is not the same as any of the Python attributes listed above, or the methods listed below, they can be referenced as if they were a Python attribute of the NXgroup. However, it is only possible to reference attributes with one of the proscribed names using the group dictionary, i.e., >>> entry.sample.temperature = 100.0 >>> print(entry.sample.temperature) sample:NXsample temperature = 100.0 >>> entry.sample['temperature'] NXfield(100.0) For this reason, it is recommended to use the group dictionary to reference all group objects within Python scripts. Notes ----- All NeXus attributes are stored in the 'attrs' dictionary of the NXgroup, but can be referenced as if they are Python attributes as long as there is no name clash. >>> entry.sample.temperature = 40.0 >>> entry.sample.attrs['value'] = 10.0 >>> print(entry.sample.value) sample:NXsample @value = 10.0 temperature = 40.0 >>> entry.sample.attrs['value'] NXattr(10.0) Examples -------- >>> x = NXfield(np.linspace(0,2*np.pi,101), units='degree') >>> entry = NXgroup(x, name='entry', nxclass='NXentry') >>> entry.sample = NXgroup(temperature=NXfield(40.0,units='K'), nxclass='NXsample') >>> print(entry.sample.tree) sample:NXsample temperature = 40.0 @units = K All the currently defined NeXus classes are defined as subclasses of the NXgroup class. It is recommended that these are used directly, so that the above examples become: >>> entry = NXentry(x) >>> entry['sample'] = NXsample(temperature=NXfield(40.0,units='K')) or >>> entry['sample/temperature'] = 40.0 >>> entry['sample/temperature'].units='K' """ _class = 'NXgroup' def __init__(self, *args, **kwargs): if "name" in kwargs: self._name = kwargs.pop("name") if "nxclass" in kwargs: self._class = kwargs.pop("nxclass") if "group" in kwargs: self._group = kwargs.pop("group") self._entries = None if "entries" in kwargs: for k, v in kwargs["entries"].items(): self[k] = v del kwargs["entries"] if "attrs" in kwargs: self._attrs = AttrDict(self, attrs=kwargs["attrs"]) del kwargs["attrs"] else: self._attrs = AttrDict(self) for k, v in kwargs.items(): self[k] = v if self.nxclass.startswith("NX"): if self.nxname == "unknown" or self.nxname == "": self._name = self.nxclass[2:] try: # If one exists, set the class to a valid NXgroup subclass self.__class__ = _getclass(self._class) except Exception: pass for arg in args: try: self[arg.nxname] = arg except AttributeError: raise NeXusError( "Non-keyword arguments must be valid NXobjects") self.set_changed() def __dir__(self): return sorted([c for c in dir(super()) if not c.startswith('_')] + list(self)+list(self.attrs), key=natural_sort) def __repr__(self): return f"{self.__class__.__name__}('{self.nxname}')" def __hash__(self): return id(self) def __getattr__(self, name): """ Return attribute looking in the group entries and attributes. If the attribute is the name of a defined NeXus class, a list of group entries of that class are returned. """ if name.startswith('NX'): return self.component(name) elif name in self.entries: return self.entries[name] elif name in self.attrs: return self.attrs[name] raise AttributeError("'"+name+"' not in "+self.nxpath) def __setattr__(self, name, value): """ Set an attribute as an object or regular Python attribute. Parameters ---------- name : str Name of the attribute value : NXfield or NXgroup or NXattr or str or array-like Value to be assigned to the attribute. If the value is a NXattr instance, it is assigned to the group `attrs` dictionary. If the value is a NXfield or NXgroup, it is added to the group entries with the assigned name. Otherwise, the value is converted to a NXfield. The parent group of the attribute is set to the current group. Notes ----- If the attribute name starts with 'nx' or '_', they are assigned as NXgroup attributes without further conversions. """ if name.startswith('_') or name.startswith('nx'): object.__setattr__(self, name, value) elif isinstance(value, NXattr): if self.nxfilemode == 'r': raise NeXusError("NeXus file opened as readonly") elif self.is_linked(): raise NeXusError("Cannot modify an item in a linked group") self._attrs[name] = value else: self[name] = value def __delattr__(self, name): """Delete an entry or attribute in the current group.""" if name in self.entries or name in self.attrs: raise NeXusError( "Members can only be deleted using the group dictionary") else: object.__delattr__(self, name) def __getitem__(self, key): """Return a NeXus field or group in the current group.""" try: path = PurePath(str(key)) except TypeError: raise NeXusError("Invalid index") if path.is_absolute(): node = self.nxroot path = path.relative_to('/') else: node = self for name in path.parts: try: node = node.entries[name] except KeyError: raise NeXusError("Invalid path") return node def __setitem__(self, key, value): """ Add or modify entries to the group dictionary. All dictionary entries must be valid NeXus fields or groups. If the value is a string or a NumPy array, a NeXus field of matching type is created. If the name refers to a NXfield that already exists in the group, the field values are modified, provided that the new values are compatible with the field shape and dtype. Parameters ---------- key : str Name of the added entry. value : NXfield or NXgroup or str or array-like. Value to be added to the group. Notes ----- If the key is a path within the NeXus tree, the value is added to the base group in the path. """ try: path = PurePath(str(key)) except TypeError: raise NeXusError("Invalid key") if len(path.parts) > 1: group = self[path.parent] else: group = self key = path.name if group.nxfilemode == 'r': raise NeXusError("NeXus group marked as readonly") elif isinstance(group, NXlink): raise NeXusError("Cannot modify an item in a linked group") elif isinstance(value, NXroot): raise NeXusError("Cannot assign an NXroot group to another group") elif key in group and group.nxfilemode: if isinstance(value, NXgroup): raise NeXusError( "Cannot assign an NXgroup to an existing group entry") elif isinstance(value, NXlink): raise NeXusError( "Cannot assign an NXlink to an existing group entry") elif isinstance(group.entries[key], NXlink): raise NeXusError("Cannot assign values to an NXlink") elif group.entries[key].is_linked(): raise NeXusError("Cannot modify an item in linked group") group.entries[key].nxdata = value if isinstance(value, NXfield): group.entries[key]._setattrs(value.attrs) elif isinstance(value, NXobject): if group.nxfilemode is None and value._copyfile is not None: raise NeXusError( "Can only copy objects to another NeXus file.") if value._group: value = deepcopy(value) value._group = group value._name = key if isinstance(value, NXlink): value.initialize_link() group.entries[key] = value else: group.entries[key] = NXfield(value=value, name=key, group=group) if isinstance(group.entries[key], NXfield): field = group.entries[key] if field._value is not None: if isinstance(field._value, np.ma.MaskedArray): mask_name = field._create_mask() group[mask_name] = field._value.mask elif field._memfile is not None: if 'mask' in field._memfile: mask_name = field._create_mask() group[mask_name]._create_memfile() field._memfile.copy('mask', group[mask_name]._memfile, 'data') del field._memfile['mask'] elif (isinstance(group.entries[key], NXentry) and not isinstance(group, NXroot)): group.entries[key].nxclass = NXsubentry group.entries[key].update() def __delitem__(self, key): """ Delete an entry in the group dictionary. Parameters ---------- key : str Name of the NeXus field or group to be deleted. Notes ----- If a mask is associated with a deleted field, it is also deleted. """ if self.nxfilemode == 'r': raise NeXusError("NeXus file opened as readonly") if is_text(key): # i.e., deleting a NeXus object group = self if '/' in key: names = [name for name in key.split('/') if name] key = names.pop() for name in names: if name in group: group = group[name] else: raise NeXusError("Invalid path") if key not in group: raise NeXusError("'"+key+"' not in "+group.nxpath) elif group[key].is_linked(): raise NeXusError("Cannot delete an item in a linked group") if group.nxfilemode == 'rw': with group.nxfile as f: if 'mask' in group.entries[key].attrs: del f[group.entries[key].mask.nxpath] del f[group.entries[key].nxpath] if 'mask' in group.entries[key].attrs: del group.entries[group.entries[key].mask.nxname] del group.entries[key] group.set_changed() def __contains__(self, key): """Implements 'k in d' test using the group's entries.""" if isinstance(self, NXroot) and str(key) == '/': return True elif isinstance(key, NXobject): return id(key) in [id(x) for x in self.entries.values()] else: try: return isinstance(self[key], NXobject) except Exception: return False def __eq__(self, other): """Return True if all group entries are the same as another.""" if not isinstance(other, NXgroup): return False elif id(self) == id(other): return True else: return self.entries == other.entries def __iter__(self): """Implement key iteration.""" return self.entries.__iter__() def __len__(self): """Return the number of entries in the group.""" return len(self.entries) def __deepcopy__(self, memo): """Return a deep copy of the group.""" obj = self dpcpy = obj.__class__() dpcpy._name = self._name memo[id(self)] = dpcpy dpcpy._changed = True for k, v in obj.items(): dpcpy.entries[k] = deepcopy(v, memo) dpcpy.entries[k]._group = dpcpy for k, v in obj.attrs.items(): dpcpy.attrs[k] = copy(v) if 'target' in dpcpy.attrs: del dpcpy.attrs['target'] dpcpy._group = None return dpcpy def serialize(self): """Serialize the group to a dictionary.""" if self._entries: entries = {k: v.serialize() for k, v in self._entries.items()} else: entries = None return {'name': self.nxname, 'class': self.__class__.__name__, 'target': self._target, 'filename': self._filename, 'mode': self._mode, 'proxy': self._proxy, 'abspath': self._abspath, 'soft': self._soft, 'entries': entries, 'attrs': {k: v._value for k,v in self.attrs.items()}} @classmethod def deserialize(cls, serialized_group): """Deserialize the group from a dictionary.""" target_cls = _getclass(serialized_group['class']) obj = super(target_cls, target_cls).__new__(target_cls) obj._name = serialized_group['name'] obj._class = serialized_group['class'] obj._target = serialized_group['target'] obj._filename = serialized_group['filename'] obj._mode = serialized_group['mode'] obj._proxy = serialized_group['proxy'] obj._abspath = serialized_group['abspath'] obj._soft = serialized_group['soft'] if 'link' in serialized_group['class']: obj.initialize_link() obj._entries = None return obj if serialized_group['entries'] is not None: obj._entries = {} for serialized_entry in serialized_group['entries']: entry = serialized_group['entries'][serialized_entry] if entry['class'] in ['NXlink', 'NXlinkfield']: obj._entries[entry['name']] = NXlink.deserialize(entry) elif entry['class'] == 'NXfield': obj._entries[entry['name']] = NXfield.deserialize(entry) else: obj._entries[entry['name']] = NXgroup.deserialize(entry) obj._entries[entry['name']]._group = obj else: obj._entries = None obj._attrs = AttrDict(obj) obj._attrs._setattrs(serialized_group['attrs']) return obj def walk(self): """Walk through all the values in the group.""" yield self for node in self.values(): for child in node.walk(): yield child def update(self): """Update the group and its children in the NeXus file.""" if self.nxfilemode == 'rw': with self.nxfile as f: f.update(self) elif self.nxfilemode is None: for node in self.walk(): if isinstance(node, NXfield) and node._uncopied_data: node._value = node._get_uncopied_data() self.set_changed() def get(self, name, default=None): """ Retrieve the group entry. This returns the default value if the entry doesn't exist. """ try: return self.entries[name] except KeyError: return default def keys(self): """Return the names of NeXus objects in the group.""" return self.entries.keys() def iterkeys(self): """Return an iterator over group object names.""" return iter(self.entries) def values(self): """Return the values of NeXus objects in the group.""" return self.entries.values() def itervalues(self): """Return an iterator over group objects.""" for key in self.entries: yield self.entries.get(key) def items(self): """Return a list of the NeXus objects as (key,value) pairs.""" return self.entries.items() def iteritems(self): """Return an iterator over (name, object) pairs.""" for key in self.entries: yield (key, self.entries.get(key)) def has_key(self, name): """True if an object of the specified name is in the group.""" return name in self.entries def clear(self): raise NeXusError("This method is not implemented for NXgroups") def pop(self, *args, **kwargs): raise NeXusError("This method is not implemented for NXgroups") def popitem(self, *args, **kwargs): raise NeXusError("This method is not implemented for NXgroups") def fromkeys(self, *args, **kwargs): raise NeXusError("This method is not implemented for NXgroups") def setdefault(self, *args, **kwargs): raise NeXusError("This method is not implemented for NXgroups") def component(self, nxclass): """ Return a list of entries in the group of the same class. Parameters ---------- nxclass : str Class name Returns ------- list of NXfields or NXgroups List of fields or groups of the same class. """ def class_list(nxclass): return [self.entries[i] for i in self.entries if self.entries[i].nxclass == nxclass] if nxclass == 'NXfield': return class_list('NXfield') elif nxclass == 'NXgroup': return class_list('NXgroup') elif nxclass == 'NXlink': return class_list('NXlink') else: return class_list(nxclass) def move(self, item, group, name=None): """ Move an item in the group to another group in the same tree. Parameters ---------- item : NXobject or str Item to be moved, defined either by the item itself or by its name. group : NXgroup or str New group to contain the item. name : str, optional Name of the item in the new group. By default, the name is unchanged. """ if is_text(item): if item in self: item = self[item] else: raise NeXusError(f"'{item}' not in group") if is_text(group): if group in self: group = self[group] elif group in self.nxroot: group = self.nxroot[group] else: raise NeXusError(f"'{group}' not in tree") if not isinstance(group, NXgroup): raise NeXusError("Destination must be a valid NeXus group") if item.nxroot != group.nxroot: raise NeXusError("The item can only be moved within the same tree") if name is None: name = item.nxname if name in group: raise NeXusError(f"'{name}' already in the destination group") group[name] = item del self[item.nxname] def insert(self, value, name='unknown'): """ Add an NeXus field or group to the current group. If it is not a valid NeXus object, the value is converted to an NXfield. If the object is an internal link within an externally linked file, the linked object in the external file is copied. Parameters ---------- value : NXfield or NXgroup or str or array-like NeXus field or group to be added. name : str, optional Name of the new entry, by default the name of the added object. """ if isinstance(value, NXobject): if name == 'unknown': name = value.nxname if name in self.entries: raise NeXusError(f"'{name}' already exists in group") self[name] = value else: if name in self.entries: raise NeXusError(f"'{name}' already exists in group") self[name] = NXfield(value=value, name=name, group=self) def makelink(self, target, name=None, abspath=False): """ Create a linked NXobject within the group. The root of the target and the child's group must be the same. Parameters ---------- target : NXobject Target object of the link. name : str, optional The name of the linked object, by default the same as the target. abspath : bool, optional True if the target is an absolute path, by default False """ if isinstance(target, NXlink): raise NeXusError("Cannot link to an NXlink object") elif not isinstance(target, NXobject): raise NeXusError("Link target must be an NXobject") elif not isinstance(self.nxroot, NXroot): raise NeXusError( "The group must have a root object of class NXroot") elif target.is_external(): raise NeXusError( "Cannot link to an object in an externally linked group") if name is None: name = target.nxname if name in self: raise NeXusError( f"Object with the same name already exists in '{self.nxpath}'") if self.nxroot == target.nxroot: self[name] = NXlink(target=target) else: self[name] = NXlink(target=target.nxpath, file=target.nxfilename, abspath=abspath) def sum(self, axis=None, averaged=False): """Return a sum of the signal in the group. This function should only be used on NXdata groups. The sum is over a single axis or a tuple of axes using the NumPy sum method. Parameters ---------- axis : int, optional Axis to be summed, by default all of the axes. averaged : bool, optional If True, divide the sum by the signal size, by default False. Returns ------- NXdata Data group containin the summed values. Notes ----- The result contains a copy of all the metadata contained in the NXdata group. """ if self.nxsignal is None: raise NeXusError("No signal to sum") if not hasattr(self, "nxclass"): raise NeXusError("Summing not allowed for groups of unknown class") if axis is None: if averaged: return self.nxsignal.sum() / self.nxsignal.size else: return self.nxsignal.sum() else: if isinstance(axis, numbers.Integral): axis = [axis] axis = tuple(axis) signal = NXfield(self.nxsignal.sum(axis), name=self.nxsignal.nxname, attrs=self.nxsignal.safe_attrs) axes = self.nxaxes averages = [] for ax in axis: summedaxis = deepcopy(axes[ax]) summedaxis.attrs["minimum"] = summedaxis.nxdata[0] summedaxis.attrs["maximum"] = summedaxis.nxdata[-1] summedaxis.attrs["summed_bins"] = summedaxis.size averages.append(NXfield( 0.5*(summedaxis.nxdata[0]+summedaxis.nxdata[-1]), name=summedaxis.nxname, attrs=summedaxis.attrs)) axes = [axes[i] for i in range(len(axes)) if i not in axis] result = NXdata(signal, axes) summed_bins = 1 for average in averages: result.insert(average) summed_bins *= average.attrs["summed_bins"] if averaged: result.nxsignal = result.nxsignal / summed_bins result.attrs["averaged_bins"] = summed_bins else: result.attrs["summed_bins"] = summed_bins if self.nxerrors: errors = np.sqrt((self.nxerrors.nxdata**2).sum(axis)) if averaged: result.nxerrors = NXfield(errors) / summed_bins else: result.nxerrors = NXfield(errors) if self.nxweights: weights = self.nxweights.nxdata.sum(axis) if averaged: result.nxweights = NXfield(weights) / summed_bins else: result.nxweights = NXfield(weights) if self.nxtitle: result.title = self.nxtitle return result def average(self, axis=None): """ Return the average of the signal of the group. This function should only be used on NXdata groups. The sum is over a single axis or a tuple of axes using the NumPy sum method. The result is then divided by the number of summed bins to produce an average. Parameters ---------- axis : int, optional Axis to be averaged, by default all of the axes. Returns ------- NXfield Averaged value. Notes ----- The result contains a copy of all the metadata contained in the NXdata group. """ return self.sum(axis, averaged=True) def moment(self, order=1, center=None): """ Return the central moments of the one-dimensional signal. Parameters ---------- order : int, optional Order of the calculated moment, by default 1. center : float, optional Center if defined externally for use by higher order moments, by default None. Returns ------- NXfield Value of moment. """ signal, axes = self.nxsignal, self.nxaxes if signal is None: raise NeXusError("No signal to calculate") elif len(signal.shape) > 1: raise NeXusError( "Operation only possible on one-dimensional signals") if not hasattr(self, "nxclass"): raise NeXusError( "Operation not allowed for groups of unknown class") y = signal / signal.sum() x = centers(axes[0], y.shape[0]) if center: c = center else: c = (y * x).sum() if order == 1: return c else: return (y * (x - c)**order).sum() def mean(self): """ Return the mean value of one-dimensional data. Returns ------- NXfield The mean of the group signal. """ return self.moment(1) def var(self): """ Return the variance of the one-dimensional data. Returns ------- NXfield The variance of the group signal. """ return np.abs(self.moment(2)) def std(self): """ Return the standard deviation of the one-dimensional data. Returns ------- NXfield The standard deviation of the group signal. """ return np.sqrt(self.var()) def get_default(self): """ Return the default data group if it is defined or None. Returns ------- NXdata Data group to be plotted. """ if 'default' in self.attrs and self.attrs['default'] in self: default = self[self.attrs['default']] return default.get_default() else: return None def set_default(self, over=False): """ Set group as the default for plotting. This will set defaults for parents of the parent group unless they have already been set previously. Parameters ========== over : bool True if previous default should be overwritten """ group = self.nxgroup if group is None: raise NeXusError( "The default cannot be defined without a parent group") else: default = self.attrs.get('default', None) if default and default in self: group.attrs['default'] = self.nxname parent_group = group.nxgroup if parent_group: if over or parent_group.get_default() is None: group.set_default(over=over) else: raise NeXusError( f"The default group has not been defined in {self.nxpath}") def get_validator(self, definitions=None): if definitions is None and NX_CONFIG['definitions'] is not None: definitions = NX_CONFIG['definitions'] from .validate import get_validator return get_validator(self.nxclass, definitions=definitions) def valid_groups(self, definitions=None, deprecated=False): """ Return the valid groups of the group. Parameters ---------- definitions : str, optional The path to the directory containing the NeXus base class definitions (default is None). deprecated : bool, optional True if deprecated fields should be included Returns ------- dict A dictionary containing the valid groups of the group. """ validator = self.get_validator(definitions=definitions) if deprecated: return validator.valid_groups else: return remove_deprecations(validator.valid_groups) def valid_fields(self, definitions=None, deprecated=False): """ Return the valid fields of the group. Parameters ---------- definitions : str, optional The path to the directory containing the NeXus base class definitions (default is None). deprecated : bool, optional True if deprecated fields should be included Returns ------- dict A dictionary containing the valid fields of the group. """ validator = self.get_validator(definitions=definitions) if deprecated: return validator.valid_fields else: return remove_deprecations(validator.valid_fields) def valid_attributes(self, field=None, definitions=None, deprecated=False): """ Return a list of valid attributes for the group or field. Parameters ---------- field : str or NXfield, optional The name of the field or the field object itself. definitions : str, optional The path to the directory containing the NeXus base class definitions (default is None). deprecated : bool, optional True if deprecated attributes should be included Returns ------- list A list of valid attributes for the specified field. """ validator = self.get_validator(definitions=definitions) if field is not None: if isinstance(field, NXfield): field = field.nxname if field in validator.valid_fields: if 'attribute' in validator.valid_fields[field]: attributes = validator.valid_fields[field]['attribute'] if deprecated: return attributes else: return remove_deprecations(attributes) else: return {} return validator.valid_attributes def valid_values(self, field=None, attribute=None, definitions=None): """ Return a list of valid values for the specified field or attribute. Parameters ---------- field : str or NXfield, optional The name of the field or the field object itself. attribute : str, optional The name of the attribute. definitions : str, optional The path to the directory containing the NeXus base class definitions (default is None). Returns ------- list A list of valid values for the specified field or attribute. """ validator = self.get_validator(definitions=definitions) if field is not None: if isinstance(field, NXfield): field = field.nxname if field in validator.valid_fields: valid_fields = validator.valid_fields if attribute is not None: if 'attribute' in valid_fields[field]: valid_attributes = valid_fields[field]['attribute'] if (attribute in valid_attributes and 'enumeration' in valid_attributes[attribute]): return valid_attributes[attribute]['enumeration'] elif 'enumeration' in valid_fields[field]: return valid_fields[field]['enumeration'] elif attribute is not None: if (attribute in validator.valid_attributes and 'enumeration' in validator.valid_attributes[attribute]): return validator.valid_attributes[attribute]['enumeration'] return [] def check(self, level='warning', definitions=None): """ Checks the group for compliance with the NeXus base classes. Parameters ---------- level : str, optional The minimum level of warnings to be reported. Can be one of 'warning', 'error', or 'all'. Default is 'warning'. definitions : str, optional The path to the directory containing the NeXus definitions (default is None). Returns ------- tuple A tuple containing the total number of warnings and errors encountered while validating the file. """ from .validate import log_header, log_summary validator = self.get_validator(definitions=definitions) log_header(validator, path=self.nxpath) validator.validate(self, level=level) return log_summary() def validate(self, level='warning', application=None, definitions=None): """ Validate the group against a NeXus application definition. Note that this can only be used on NXroot and NXentry groups. Parameters ---------- level : str, optional The minimum level of warnings to be reported. Can be one of 'warning', 'error', or 'all'. Default is 'warning'. application : str, optional The name of the application definition validating the group (default is None). If not specified, the value in the entry's 'definition' attribute will be used. definitions : str, optional The path to the directory containing the NeXus base class definitions (default is None). Returns ------- tuple A tuple containing the total number of warnings and errors encountered while validating the file. """ if not isinstance(self, NXroot) and not isinstance(self, NXentry): raise NeXusError( "Validation can only be used on NXroot and NXentry groups") if isinstance(self, NXroot): entry = self.NXentry[0] else: entry = self if definitions is None and NX_CONFIG['definitions'] is not None: definitions = NX_CONFIG['definitions'] if application is None and 'definition' in entry: application = entry['definition'].nxvalue elif application is None: raise NeXusError( f'No application definition is defined in "{entry.nxpath}"') from .validate import ApplicationValidator, log_header, log_summary validator = ApplicationValidator(application, definitions=definitions) log_header(validator, path=entry.nxpath, application=application) validator.validate(entry, level=level) return log_summary() def inspect(self, definitions=None): """ Print the valid components of the group's base class. Parameters ---------- definitions : str, optional The path to the directory containing the NeXus base class definitions (default is None). """ if definitions is None and NX_CONFIG['definitions'] is not None: definitions = NX_CONFIG['definitions'] from .validate import inspect_base_class inspect_base_class(self.nxclass, definitions=definitions) def is_plottable(self): """Return True if the group contains plottable data.""" plottable = False for entry in self: if self[entry].is_plottable(): plottable = True break return plottable @property def plottable_data(self): """Return the first NXdata group within the group's tree.""" default = self.get_default() if default is not None: return self[default] else: return None def plot(self, **kwargs): """Plot data contained within the group. Valid keyword arguments are passed to Matplotlib. """ plotdata = self.plottable_data if plotdata: plotdata.plot(**kwargs) else: raise NeXusError("There is no plottable data") def oplot(self, **kwargs): """Overplot the group signal over the current figure.""" plotdata = self.plottable_data if plotdata: plotdata.oplot(**kwargs) else: raise NeXusError("There is no plottable data") def logplot(self, **kwargs): """Plot the group signal on a log scale.""" plotdata = self.plottable_data if plotdata: plotdata.logplot(**kwargs) else: raise NeXusError("There is no plottable data") def implot(self, **kwargs): """Plot the group signal as an RGB(A) image.""" plotdata = self.plottable_data if plotdata: plotdata.implot(**kwargs) else: raise NeXusError("There is no plottable data") def signals(self): """ Return a dictionary of NXfield's containing signal data. The key is the value of the signal attribute. """ signals = {} for obj in self.values(): if 'signal' in obj.attrs: signals[obj.attrs['signal']] = obj return signals def _str_name(self, indent=0): return " " * indent + self.nxname + ':' + self.nxclass def _str_tree(self, indent=0, attrs=False, recursive=False): result = [self._str_name(indent=indent)] if self.attrs and (attrs or indent == 0): result.append(self._str_attrs(indent=indent+2)) entries = self.entries if entries: names = sorted(entries, key=natural_sort) if recursive: if recursive is True or recursive >= indent: for k in names: result.append(entries[k]._str_tree(indent=indent+2, attrs=attrs, recursive=recursive) ) else: for k in names: result.append(entries[k]._str_name(indent=indent+2)) return "\n".join(result) @property def nxtitle(self): """ The group title. If there is no title field in the group or its parent group, the group's path is returned. """ if 'title' in self: return text(self.title) elif self.nxgroup and 'title' in self.nxgroup: return text(self.nxgroup.title) else: root = self.nxroot if root.nxname != '' and root.nxname != 'root': return (root.nxname + '/' + self.nxpath.lstrip('/')).rstrip('/') else: fname = self.nxfilename if fname is not None: return str(Path(fname).name) + ':' + self.nxpath else: return self.nxpath @property def entries(self): """ Dictionary of NeXus objects in the group. If the NeXus data is stored in a file that was loaded with the 'recursive' keyword set to False, only the root entries will have been read. This property automatically reads any missing entries as they are referenced. Returns ------- dict of NXfields and/or NXgroups Dictionary of group objects. """ if self._entries is None: if self.nxfile: with self.nxfile as f: self._entries = f.readentries(self) else: self._entries = {} self.set_changed() return self._entries @property def entries_loaded(self): """True if the NXgroup entries have been initialized.""" return self._entries is not None nxsignal = None nxaxes = None nxerrors = None class NXlink(NXobject): """ Parent class for NeXus linked objects. The link is initialized by specifying the path to the link target and, if the link is to an external file, the filename. When it is possible to access the target, the class of the link is changed to NXlinkfield or NXlinkgroup. Attributes ---------- nxlink : NXfield or NXgroup Target of link. """ _class = 'NXlink' def __init__(self, target=None, file=None, name=None, group=None, abspath=False, soft=False): self._class = 'NXlink' self._name = name self._group = group self._abspath = abspath self._soft = soft self._entries = None if file is not None: self._filename = str(file) self._mode = 'r' else: self._filename = self._mode = None if isinstance(target, NXobject): if isinstance(target, NXlink): raise NeXusError("Cannot link to another NXlink object") if name is None: self._name = target.nxname self._target = target.nxpath if isinstance(target, NXfield): self._setclass(NXlinkfield) elif isinstance(target, NXgroup): self._setclass(_getclass(target.nxclass, link=True)) else: if name is None and is_text(target): self._name = target.rsplit('/', 1)[1] self._target = text(target) self._link = None def __repr__(self): if self._filename: return f"NXlink(target='{self._target}', file='{self._filename}')" else: return f"NXlink('{self._target}')" def __getattr__(self, name): """ Return the requested attribute from the target object. The value of the corresponding target attribute is returned, reading from the external file if necessary. """ try: return getattr(self.nxlink, name) except Exception: raise AttributeError( f"Cannot resolve the link to '{self._target}'") def __setattr__(self, name, value): """ Set an attribute of the link target. This is not allowed when the target is in an external file. Parameters ---------- name : str Name of the attribute value : NXfield or NXgroup or NXattr or str or array-like Value to be assigned to the attribute. """ if name.startswith('_') or name == 'nxtarget': object.__setattr__(self, name, value) elif self.is_external(): raise NeXusError("Cannot modify an external link") else: try: self.nxlink.setattr(name, value) except Exception: raise NeXusError("Unable to modify link target") def __setitem__(self, idx, value): """ Assign values to a slice of the target NXfield. Parameters ---------- idx : slice Slice to be modified. value Value to be added. The value must be compatible with the NXfield dtype and it must be possible to broadcast it to the shape of the specified slice. """ if self.is_external(): raise NeXusError("Cannot modify an externally linked file") else: self.nxlink.__setitem__(idx, value) def __contains__(self, key): return self.nxlink.__contains__(key) def __eq__(self, other): """Return True if two linked objects share the same target.""" if isinstance(other, NXlink): return ((self._target == other._target) and (self._filename == other._filename)) else: return False def __deepcopy__(self, memo={}): """Return a deep copy of the link.""" obj = self dpcpy = obj.__class__() memo[id(self)] = dpcpy dpcpy._name = copy(self.nxname) dpcpy._target = copy(obj._target) if obj._filename: dpcpy._filename = copy(obj.nxfilename) else: dpcpy._filename = None dpcpy._abspath = copy(obj._abspath) dpcpy._soft = copy(obj._soft) dpcpy._link = None dpcpy._group = None return dpcpy def serialize(self): """Serialize the link to a dictionary.""" return {'name': self.nxname, 'class': self.__class__.__name__, 'target': self._target, 'filename': self._filename, 'mode': self._mode, 'abspath': self._abspath, 'soft': self._soft} @classmethod def deserialize(cls, serialized_link): """Deserialize the link from a dictionary.""" target_cls = _getclass(serialized_link['class'], link=True) obj = super(target_cls, target_cls).__new__(target_cls) obj._name = serialized_link['name'] obj._class = serialized_link['class'] obj._target = serialized_link['target'] obj._filename = serialized_link['filename'] obj._mode = serialized_link['mode'] obj._abspath = serialized_link['abspath'] obj._soft = serialized_link['soft'] obj.initialize_link() return obj def _str_name(self, indent=0): if self._filename: return (" " * indent + self.nxname + ' -> ' + text(self._filename) + "['" + text(self._target) + "']") else: return " " * indent + self.nxname + ' -> ' + text(self._target) def _str_tree(self, indent=0, attrs=False, recursive=False): return self._str_name(indent=indent) def update(self): """Update the NeXus file if necessary.""" root = self.nxroot filename, mode = root.nxfilename, root.nxfilemode if (filename is not None and Path(filename).exists() and mode == 'rw'): with root.nxfile as f: f.update(self) self.set_changed() @property def nxtarget(self): """Path to the target of the link.""" return self._target @nxtarget.setter def nxtarget(self, value): if self.nxroot.nxfilemode != 'rw': raise NeXusError("NeXus file opened as readonly") elif isinstance(value, NXlink): raise NeXusError("Cannot link to another NXlink object") elif is_text(value): _target = value _filename = self._filename elif isinstance(value, NXfield) or isinstance(value, NXgroup): if value.nxfilename == self.nxroot.nxfilename: _target = value.nxpath _filename = None else: _target = value.nxpath _filename = value.nxfilename elif ((isinstance(value, tuple) or isinstance(value, list)) and len(value) == 2): _target = value[0] _filename = value[1] else: raise NeXusError("Invalid link target") if _target != self._target or _filename != self._filename: if not self.is_external(): original_target = self.nxroot[self.nxlink.nxpath] self._target = _target self._filename = _filename self._file = None self._link = None self.update() if not self.is_external(): self.nxlink.update() if original_target.rc == 1 and not self.is_soft(): del original_target.attrs['target'] original_target.update() @property def nxlink(self): """ Target of link. If called for the first time, this attempts to initialize the link class (NXlinkfield or NXlinkgroup) and attributes if the target is accessible. """ self.initialize_link() if self._link is None: if self.is_external(): self._link = self.external_link else: self._link = self.internal_link return self._link def initialize_link(self): """ Resolve the link class and read in key attributes. Returns ------- NXfield or NXgroup Target of link. """ if self.nxclass == 'NXlink': if self.is_external(): if self.path_exists(): with self.nxfile as f: item = f.readpath(self.nxfilepath) else: return elif self._target in self.nxroot: item = self.nxroot[self._target] else: return if isinstance(item, NXfield): self._setclass(NXlinkfield) elif isinstance(item, NXgroup): self._setclass(_getclass(item.nxclass, link=True)) else: return @property def internal_link(self): """Return NXfield or NXgroup targeted by an internal link.""" if PurePath(self._target).is_absolute(): return self.nxroot[self._target] else: try: return self.nxgroup[self._target] except NeXusError: return self.nxroot[self._target] @property def external_link(self): """Return NXfield or NXgroup targeted by an external link.""" try: with self.nxfile as f: item = f.readpath(self.nxfilepath) item._target = self.nxfilepath item._filename = self.nxfilename item._mode = 'r' return item except Exception: raise NeXusError( f"Cannot read the external link to '{self._filename}'") def is_external(self): """True if the link points to an external file.""" if self.nxroot is self and self._filename: return True else: return super().is_external() def is_soft(self): """True if the link is a soft link.""" return self._soft and not self.is_external() @property def attrs(self): """Return attributes of the linked NXfield or NXgroup.""" try: return self.nxlink.attrs except NeXusError: return AttrDict() @property def nxfilemode(self): """ Read/write mode of the NeXus file if saved to a file. Notes ----- External links are always read-only. """ try: if self.is_external(): return 'r' else: return self.nxlink.nxfilemode except Exception: return 'r' @property def abspath(self): """True if the filename is to be stored as an absolute path.""" return self._abspath class NXlinkfield(NXlink, NXfield): """Class for NeXus linked fields.""" def __init__(self, target=None, file=None, name=None, abspath=False, soft=False, **kwargs): NXlink.__init__(self, target=target, file=file, name=name, abspath=abspath, soft=soft) self._class = 'NXfield' def __getitem__(self, idx): """ Return the slab of the linked field defined by the index. Parameters ---------- idx : slice Slice index or indices. Returns ------- NXfield Field containing the slice values. """ result = self.nxlink.__getitem__(idx) if isinstance(result, NXfield): result._name = self._name return result @property def nxdata(self): """Data of linked NXfield.""" return self.nxlink.nxdata class NXlinkgroup(NXlink, NXgroup): """Class for NeXus linked groups.""" def __init__(self, target=None, file=None, name=None, abspath=False, soft=False, **kwargs): NXlink.__init__(self, target=target, file=file, name=name, abspath=abspath, soft=soft) if 'nxclass' in kwargs: self._setclass(_getclass(kwargs['nxclass'], link=True)) else: self._class = 'NXlink' def __getattr__(self, name): """ Return attribute looking in the group entries and attributes. If the attribute is the name of a defined NeXus class, a list of group entries of that class are returned. """ return NXgroup(self).__getattr__(name) def _str_name(self, indent=0): if self._filename: return (" " * indent + self.nxname + ':' + self.nxclass + ' -> ' + text(self._filename) + "['" + text(self._target) + "']") else: return (" " * indent + self.nxname + ':' + self.nxclass + ' -> ' + text(self._target)) def _str_tree(self, indent=0, attrs=False, recursive=False): try: return NXgroup._str_tree(self, indent=indent, attrs=attrs, recursive=recursive) except Exception: return NXlink(self)._str_tree(self, indent=indent) @property def entries(self): """ Dictionary of NeXus objects in the linked group. Returns ------- dict of NXfields and/or NXgroups Dictionary of group objects. """ _linked_entries = self.nxlink.entries _entries = {} if self.is_external(): for entry in _linked_entries: _entries[entry] = _linked_entries[entry] _entries[entry]._group = self else: for entry in _linked_entries: _entries[entry] = deepcopy(_linked_entries[entry]) _entries[entry]._group = self if _entries != self._entries: self._entries = _entries self.set_changed() return _entries class NXroot(NXgroup): """ NXroot group, a subclass of the `NXgroup` class. This group has additional methods to lock or unlock the tree. """ def __init__(self, *args, **kwargs): self._class = 'NXroot' self._backup = None self._mtime = None self._file_modified = False NXgroup.__init__(self, *args, **kwargs) def __repr__(self): """Customize display of NXroot when associated with a file.""" if self.nxfilename: return f"NXroot('{Path(self.nxfilename).stem}')" else: return f"NXroot('{self.nxname}')" def __enter__(self): """ Open a NeXus file for multiple operations. Returns ------- NXroot Current NXroot instance. """ if self.nxfile: self.nxfile.__enter__() return self def __exit__(self, *args): """Close the NeXus file.""" if self.nxfile: self.nxfile.__exit__() def serialize(self): """Serialize the root group to a dictionary.""" serialized_root = super().serialize() serialized_root['mtime'] = self.mtime return serialized_root @classmethod def deserialize(self, serialized_root): """Deserialize the root group from a dictionary.""" obj = NXgroup.deserialize(serialized_root) obj._mtime = serialized_root['mtime'] if ('filename' in serialized_root and Path(serialized_root['filename']).is_file()): obj._file = NXFile(obj._filename, 'r') return obj def reload(self): """Reload the NeXus file from disk.""" if self.nxfilemode: with self.nxfile as f: f.reload() self.set_changed() else: raise NeXusError( f"'{self.nxname}' has no associated file to reload") def is_modified(self): """True if the file has been modified by an external process.""" if self._file is None: self._file_modified = False else: _mtime = self._file.mtime if self._mtime and _mtime > self._mtime: self._file_modified = True else: self._file_modified = False return self._file_modified def lock(self): """Make the tree readonly.""" if self._filename: if self.file_exists(): self._mode = self._file.mode = 'r' self.set_changed() else: raise NeXusError( f"'{Path(self.nxfilename).resolve()}' does not exist") def unlock(self): """Make the tree modifiable.""" if self._filename: if self.file_exists(): if not os.access(self.nxfilename, os.W_OK): self._mode = self._file.mode = 'r' raise NeXusError( f"Not permitted to write to '{self._filename}'") if self.is_modified(): raise NeXusError("File modified. Reload before unlocking") self._mode = self._file.mode = 'rw' else: self._mode = None self._file = None raise NeXusError( f"'{Path(self.nxfilename).resolve()}' does not exist") self.set_changed() def backup(self, filename=None, dir=None): """ Backup the NeXus file. Parameters ---------- filename : str, optional Name of file to contain the backup. If not specified, the backup is saved with a randomized name. dir : str, optional Directory to contain the backup, by default the current directory. """ if self.nxfilemode is None: raise NeXusError( "Only data saved to a NeXus file can be backed up") if filename is None: if dir is None: dir = Path.cwd() import tempfile prefix = Path(self.nxfilename).stem suffix = Path(self.nxfilename).suffix prefix = prefix + '_backup_' backup = tempfile.mkstemp(prefix=prefix, suffix=suffix, dir=dir)[1] else: if dir is not None: filename = Path(dir).joinpath(filename) if Path(filename).exists(): raise NeXusError( f"'{Path(filename).resolve()}' already exists") else: backup = Path(filename).resolve() import shutil shutil.copy2(self.nxfilename, backup) self._backup = backup def restore(self, filename=None, overwrite=False): """ Restore a backup. Parameters ---------- filename : str, optional Name of file to restore the backup to. If no file name is given, the backup replaces the current NeXus file, provided 'overwrite' has been set to True. overwrite : bool, optional True if the file is to be overwritten, by default False """ if self._backup is None: raise NeXusError("No backup exists") if filename is None: filename = self.nxfilename if Path(filename).exists() and not overwrite: raise NeXusError( f"To overwrite '{Path(filename).resolve()}', set 'overwite' " "to True") import shutil shutil.copy2(self._backup, filename) self.reload() def close(self): """Close the underlying HDF5 file.""" if self.nxfile: self.nxfile.close() @property def plottable_data(self): """ The default data group to be plotted in this tree. This will return the default group if the `default` attribute has been set. Otherwise, the first NXdata, NXmonitor, or NXlog group will be returned. Returns ------- NXdata Data group to be plotted. """ default = self.get_default() if default is not None: return default elif self.NXdata: return self.NXdata[0] elif self.NXmonitor: return self.NXmonitor[0] elif self.NXlog: return self.NXlog[0] elif self.NXentry: for entry in self.NXentry: data = entry.plottable_data if data is not None: return data return None def targets(self): targets = [] for node in self.walk(): if node.nxtarget is not None and node.nxtarget != node.nxpath: targets.append(node.nxtarget) return targets @property def nxfile(self): """NXFile storing the NeXus data.""" if self._file: return self._file elif self._filename: self._file = NXFile(self._filename, self._mode) return self._file else: return None @nxfile.setter def nxfile(self, filename): if Path(filename).exists(): self._filename = Path(filename).resolve() with NXFile(self._filename, 'r') as f: root = f.readfile() self._entries = root._entries for entry in self._entries: self._entries[entry]._group = self self._attrs._setattrs(root.attrs) self._file = NXFile(self._filename, self._mode) self._mtime = self._file.mtime self.set_changed() else: raise NeXusError(f"'{Path(filename).resolve()}' does not exist") @property def nxbackup(self): """Path to the backup file if it exists.""" return self._backup @property def mtime(self): """Modification time of the last change to root group.""" return self._mtime class NXentry(NXgroup): """NXentry group, a subclass of the NXgroup class.""" def __init__(self, *args, **kwargs): self._class = 'NXentry' NXgroup.__init__(self, *args, **kwargs) def __add__(self, other): """ Add two NXentry groups. All NXdata groups are added together. All other entries are copied from the current NXentry. Parameters ---------- other : NXentry Entry to be added. Returns ------- NXentry Group after addition. """ result = NXentry(attrs=self.attrs) try: names = [name for name in self if (isinstance(self[name], NXdata) or isinstance(self[name], NXmonitor))] for name in names: if isinstance(other[name], NXdata): result[name] = self[name] + other[name] else: raise KeyError for name in [name for name in self if name not in names]: result[name] = self[name] return result except KeyError: raise NeXusError("Inconsistency between two NXentry groups") def __sub__(self, other): """ Subtract another NXentry group from the current NXentry. All NXdata groups are subtracted. All other entries are copied from the current NXentry. Parameters ---------- other : NXentry Entry to be subtracted. Returns ------- NXentry Group after subtraction. """ result = NXentry(attrs=self.attrs) try: names = [name for name in self if isinstance(self[name], NXdata)] for name in names: if isinstance(other[name], NXdata): result[name] = self[name] - other[name] else: raise KeyError for name in [name for name in self if not isinstance(self[name], NXdata)]: result[name] = self[name] return result except KeyError: raise NeXusError("Inconsistency between two NXentry groups") @property def plottable_data(self): """ The default data group to be plotted in this entry. This will return the default group if the `default` attribute has been set. Otherwise, the first NXdata, NXmonitor, or NXlog group will be returned. """ default = self.get_default() if default is not None: return default elif self.NXdata: return self.NXdata[0] elif self.NXmonitor: return self.NXmonitor[0] elif self.NXlog: return self.NXlog[0] else: return None class NXsubentry(NXentry): """NXsubentry group, a subclass of the NXentry class.""" def __init__(self, *args, **kwargs): self._class = 'NXsubentry' NXgroup.__init__(self, *args, **kwargs) class NXdata(NXgroup): """ NXdata group, a subclass of the NXgroup class. The constructor assumes that the first argument contains the signal and the second contains either the axis, for one-dimensional data, or a list of axes, for multidimensional data. These arguments can either be NXfield objects or NumPy arrays, which are converted to NXfield objects with default names. Alternatively, the signal and axes NXfields can be defined using the 'nxsignal' and 'nxaxes' properties. See the examples below. Various arithmetic operations (addition, subtraction, multiplication, and division) have been defined for combining NXdata groups with other NXdata groups, NumPy arrays, or constants, raising a NeXusError if the shapes don't match. Data errors are propagated in quadrature if they are defined, i.e., if the 'nexerrors' attribute is not None, Parameters ---------- signal : NXfield Field defining the data to be plotted. axes : tuple of NXfields Tuple of one-dimensional fields defining the plot axes in the order of the corresponding signal dimensions. errors : NXfield, optional Field containing the standard deviations of the signal values. Attributes ---------- nxsignal : NXfield The NXfield containing the data to be plotted. nxaxes : tuple of NXfields A tuple of NXfields containing the plot axes nxerrors : NXfield The NXfield containing the standard deviations of the signal values. nxweights : NXfield The NXfield containing signal value weights. Examples -------- There are three methods of creating valid NXdata groups with the signal and axes NXfields defined according to the NeXus standard. 1) Create the NXdata group with NumPy arrays that will be assigned default names. >>> x = np.linspace(0, 2*np.pi, 101) >>> line = NXdata(sin(x), x) data:NXdata signal = float64(101) @axes = x @signal = 1 axis1 = float64(101) 2) Create the NXdata group with NXfields that have their internal names already assigned. >>> x = NXfield(linspace(0,2*pi,101), name='x') >>> y = NXfield(linspace(0,2*pi,101), name='y') >>> X, Y = np.meshgrid(x, y) >>> z = NXfield(sin(X) * sin(Y), name='z') >>> entry = NXentry() >>> entry.grid = NXdata(z, (x, y)) >>> grid.tree() entry:NXentry grid:NXdata x = float64(101) y = float64(101) z = float64(101x101) @axes = x:y @signal = 1 3) Create the NXdata group with keyword arguments defining the names and set the signal and axes using the nxsignal and nxaxes properties. >>> x = linspace(0,2*pi,101) >>> y = linspace(0,2*pi,101) >>> X, Y = np.meshgrid(x, y) >>> z = sin(X) * sin(Y) >>> entry = NXentry() >>> entry.grid = NXdata(z=sin(X)*sin(Y), x=x, y=y) >>> entry.grid.nxsignal = entry.grid.z >>> entry.grid.nxaxes = [entry.grid.x,entry.grid.y] >>> grid.tree() entry:NXentry grid:NXdata x = float64(101) y = float64(101) z = float64(101x101) @axes = x:y @signal = 1 """ def __init__(self, signal=None, axes=None, errors=None, weights=None, *args, **kwargs): self._class = 'NXdata' NXgroup.__init__(self, *args, **kwargs) attrs = {} if axes is not None: if not is_iterable(axes): axes = [axes] axis_names = {} i = 0 for axis in axes: i += 1 if isinstance(axis, NXfield) or isinstance(axis, NXlink): if axis.nxname == 'unknown' or axis.nxname in self: axis_name = f'axis{i}' else: axis_name = axis.nxname else: axis_name = f'axis{i}' self[axis_name] = axis axis_names[i] = axis_name attrs['axes'] = list(axis_names.values()) if signal is not None: if isinstance(signal, NXfield) or isinstance(signal, NXlink): if signal.nxname == 'unknown' or signal.nxname in self: signal_name = 'signal' else: signal_name = signal.nxname else: signal_name = 'signal' self[signal_name] = signal attrs['signal'] = signal_name if errors is not None: errors_name = signal_name+'_errors' self[errors_name] = errors if weights is not None: weights_name = signal_name+'_weights' self[weights_name] = weights self.attrs._setattrs(attrs) def __setattr__(self, name, value): """ Set a group attribute. This sets attributes the same way as the `NXgroup` class, unless the name is "mask", which is set by its property setter. Parameters ---------- name : str Name of the attribute. value : NXfield or NXgroup or NXattr or str or array-like Value of the attribute. """ if name == 'mask': object.__setattr__(self, name, value) else: super().__setattr__(name, value) def __getitem__(self, key): """ Return a group entry for a data group containing a slice. Parameters ---------- key : str or slice If 'key' is a string, the entry of the same name is returned. If 'key' is a slice, a NXdata group containing requested slab is returned. Returns ------- NXfield or NXgroup or NXdata Nexus entry in the group or a group containing sliced data. Notes ----- In most cases, the slice values are applied to the NXfield array and returned within a new NXfield with the same metadata. However, if any of the index start or stop values are real, the NXfield is returned with values between the limits set by the corresponding axes. """ if is_text(key): # i.e., requesting a dictionary value return NXgroup.__getitem__(self, key) elif self.nxsignal is not None: idx, axes = self.slab(key) removed_axes = [] for axis in axes: if (axis.shape == () or axis.shape == (0,) or axis.shape == (1,)): removed_axes.append(axis) axes = [ax for ax in axes if ax not in [rax for rax in removed_axes if rax is ax]] signal = self.nxsignal[idx] if self.nxerrors: errors = self.nxerrors[idx] else: errors = None if self.nxweights: weights = self.nxweights[idx] else: weights = None if 'axes' in signal.attrs: del signal.attrs['axes'] result = NXdata(signal, axes, errors, weights, *removed_axes) if errors is not None: result.nxerrors = errors if weights is not None: result.nxweights = weights if self.nxsignal.mask is not None: if isinstance(self.nxsignal.mask, NXfield): result[self.nxsignal.mask.nxname] = signal.mask if self.nxtitle: result.title = self.nxtitle return result else: raise NeXusError("No signal specified") def __setitem__(self, idx, value): """ Set the values of a slab defined by a slice Parameters ---------- idx : slice Index of values to be assigned the value. value : array-like The values to be assigned. Their shape should match the index or be compatible with the usual NumPy broadcasting rules. Notes ----- In most cases, the slice values define the indices of the signal slab. However, if the index start or stop values of any dimension are real, that dimension's slice is determined from the indices of the corresponding axis with the requested values. """ if is_text(idx): NXgroup.__setitem__(self, idx, value) elif self.nxsignal is not None: if isinstance(idx, numbers.Integral) or isinstance(idx, slice): axis = self.nxaxes[0] if self.nxsignal.shape[0] == axis.shape[0]: axis = axis.boundaries() idx = convert_index(idx, axis) self.nxsignal[idx] = value else: slices = [] axes = self.nxaxes for i, ind in enumerate(idx): if self.nxsignal.shape[i] == axes[i].shape[0]: axis = axes[i].boundaries() else: axis = axes[i] ind = convert_index(ind, axis) if isinstance(ind, slice) and ind.stop is not None: ind = slice(ind.start, ind.stop-1, ind.step) slices.append(ind) self.nxsignal[tuple(slices)] = value else: raise NeXusError("Invalid index") def __delitem__(self, key): """ Delete an entry in the current group. If the entry is a signal, the 'signal' attribute is also deleted. If the entry is an axis, its entry in the 'axes' attribute array is replaced by '.', designating an undefined axis. Parameters ---------- key : str Name of the group entry to be deleted. """ super().__delitem__(key) if 'signal' in self.attrs and self.attrs['signal'] == key: del self.attrs['signal'] elif 'axes' in self.attrs: self.attrs['axes'] = [ax if ax != key else '.' for ax in _readaxes(self.attrs['axes'])] def __add__(self, other): """ Add the current data group to another NXdata group or an array. The result contains a copy of all the metadata contained in the first NXdata group. The module checks that the dimensions are compatible, but does not check that the NXfield names or values are identical. This is so that spelling variations or rounding errors do not make the operation fail. However, it is up to the user to ensure that the results make sense. Parameters ---------- other : NXdata or array-like NXdata group to be added to the current group or values to be added to the signal. Returns ------- NXdata NXdata group with the summed data. """ result = deepcopy(self) if isinstance(other, NXdata): if self.nxsignal and self.nxsignal.shape == other.nxsignal.shape: result[self.nxsignal.nxname] = self.nxsignal + other.nxsignal if self.nxerrors: if other.nxerrors: result.nxerrors = np.sqrt(self.nxerrors**2 + other.nxerrors**2) else: result.nxerrors = self.nxerrors if self.nxweights: if other.nxweights: result.nxweights = self.nxweights + other.nxweights else: result.nxweights = self.nxweights return result elif isinstance(other, NXgroup): raise NeXusError("Cannot add two arbitrary groups") else: result[self.nxsignal.nxname] = self.nxsignal + other return result def __sub__(self, other): """ Subtract NXdata group or array values from the current group. The result contains a copy of all the metadata contained in the first NXdata group. The module checks that the dimensions are compatible, but does not check that the NXfield names or values are identical. This is so that spelling variations or rounding errors do not make the operation fail. However, it is up to the user to ensure that the results make sense. Parameters ---------- other : NXdata or array-like Values to be subtracted from the current group. Returns ------- NXdata NXdata group containing the subtracted data. """ result = deepcopy(self) if isinstance(other, NXdata): if self.nxsignal and self.nxsignal.shape == other.nxsignal.shape: result[self.nxsignal.nxname] = self.nxsignal - other.nxsignal if self.nxerrors: if other.nxerrors: result.nxerrors = np.sqrt(self.nxerrors**2 + other.nxerrors**2) else: result.nxerrors = self.nxerrors if self.nxweights: if other.nxweights: result.nxweights = self.nxweights - other.nxweights else: result.nxweights = self.nxweights return result elif isinstance(other, NXgroup): raise NeXusError("Cannot subtract two arbitrary groups") else: result[self.nxsignal.nxname] = self.nxsignal - other return result def __mul__(self, other): """ Multiply the current group by another NXdata group or an array. The result contains a copy of all the metadata contained in the first NXdata group. The module checks that the dimensions are compatible, but does not check that the NXfield names or values are identical. This is so that spelling variations or rounding errors do not make the operation fail. However, it is up to the user to ensure that the results make sense. Parameters ---------- other : NXdata or array-like Other values to multiply the data by. Returns ------- NXdata NXdata group with the multiplied data. """ result = deepcopy(self) if isinstance(other, NXdata): # error here signal not defined in this scope # if self.nxsignal and signal.shape == other.nxsignal.shape: if self.nxsignal and self.nxsignal.shape == other.nxsignal.shape: result[self.nxsignal.nxname] = self.nxsignal * other.nxsignal if self.nxerrors: if other.nxerrors: result.nxerrors = np.sqrt( (self.nxerrors * other.nxsignal)**2 + (other.nxerrors * self.nxsignal)**2) else: result.nxerrors = self.nxerrors if self.nxweights: if other.nxweights: result.nxweights = self.nxweights * other.nxweights else: result.nxweights = self.nxweights return result elif isinstance(other, NXgroup): raise NeXusError("Cannot multiply two arbitrary groups") else: result[self.nxsignal.nxname] = self.nxsignal * other if self.nxerrors: result.nxerrors = self.nxerrors * other if self.nxweights: result.nxweights = self.nxweights * other return result def __rmul__(self, other): """ Multiply the current group by another NXdata group or an array. This variant makes __mul__ commutative. Parameters ---------- other : NXdata or array-like Other values to multiply the data by. Returns ------- NXdata NXdata group with the multiplied data. """ return self.__mul__(other) def __truediv__(self, other): """ Divide the current group by another NXdata group or an array. The result contains a copy of all the metadata contained in the first NXdata group. The module checks that the dimensions are compatible, but does not check that the NXfield names or values are identical. This is so that spelling variations or rounding errors do not make the operation fail. However, it is up to the user to ensure that the results make sense. Parameters ---------- other : NXdata or array-like Other values to divide the data by. Returns ------- NXdata NXdata group with the multiplied data. """ result = deepcopy(self) if isinstance(other, NXdata): if self.nxsignal and self.nxsignal.shape == other.nxsignal.shape: result[self.nxsignal.nxname] = self.nxsignal / other.nxsignal if self.nxerrors: if other.nxerrors: result.nxerrors = ( np.sqrt( self.nxerrors ** 2 + (result[self.nxsignal.nxname] * other.nxerrors) ** 2) / other.nxsignal) else: result.nxerrors = self.nxerrors return result elif isinstance(other, NXgroup): raise NeXusError("Cannot divide two arbitrary groups") else: result[self.nxsignal.nxname] = self.nxsignal / other if self.nxerrors: result.nxerrors = self.nxerrors / other if self.nxweights: result.nxweights = self.nxweights / other return result def weighted_data(self): """Return group with the signal divided by the weights""" signal, errors, weights = (self.nxsignal, self.nxerrors, self.nxweights) if signal and weights: result = deepcopy(self) with np.errstate(divide='ignore'): result[signal.nxname] = np.where(weights > 0, signal/weights, 0.0) if errors: result[errors.nxname] = np.where(weights > 0, errors/weights, 0.0) del result[weights.nxname] elif signal is None: raise NeXusError("No signal defined for this NXdata group") elif weights is None: raise NeXusError("No weights defined for this NXdata group") result._group = self._group return result def prepare_smoothing(self): """Create an interpolation function for one-dimensional data.""" if self.nxsignal.ndim > 1: raise NeXusError("Can only smooth 1D data") from scipy.interpolate import interp1d signal, axes = self.nxsignal, self.nxaxes x, y = centers(axes[0], signal.shape[0]), signal self._smoothing = interp1d(x, y, kind='cubic') def smooth(self, n=1001, factor=None, xmin=None, xmax=None): """Return a NXdata group containing interpolations of 1D data. The number of point is either set by `n` or by decreasing the average step size by `factor` - if `factor` is not None, it overrides the value of `n``. Parameters ---------- n : int, optional Number of x-values in interpolation, by default 1001 factor: int, optional Factor by which the step size will be reduced, by default None xmin : float, optional Minimum x-value, by default None xmax : float, optional Maximum x-value, by default None Returns ------- NXdata NeXus group containing the interpolated data """ if self._smoothing is None: self.prepare_smoothing() signal, axis = self.nxsignal, self.nxaxes[0] x = centers(axis, signal.shape[0]) if xmin is None: xmin = x.min() else: xmin = max(xmin, x.min()) if xmax is None: xmax = x.max() else: xmax = min(xmax, x.max()) if factor: step = np.average(x[1:] - x[:-1]) / factor n = int((xmax - xmin) / step) + 1 xs = NXfield(np.linspace(xmin, xmax, n), name=axis.nxname) ys = NXfield(self._smoothing(xs), name=signal.nxname) return NXdata(ys, xs, title=self.nxtitle) def select(self, divisor=1.0, offset=0.0, symmetric=False, smooth=False, max=False, min=False, tol=1e-8): """ Return a group with axis values divisible by a given value. This function only applies to one-dimensional data. Parameters ---------- divisor : float, optional Divisor used to select axis values, by default 1.0 offset : float, optional Offset to add to selected values, by default 0.0 symmetric : bool, optional True if the offset is to be applied symmetrically about selections, by default False smooth : bool, optional True if data are to be smoothed before the selection, by default False max : bool, optional True if the local maxima should be selected, by default False min : bool, optional True if the local minima should be selected, by default False tol : float, optional Tolerance to be used in defining the remainder, by default 1e-8 Returns ------- NXdata NeXus group containing the selected data Notes ----- It is assumed that the offset changes sign when the axis values are negative. So if `divisor=1` and `offset=0.2`, the selected values close to the origin are -1.2, -0.2, 0.2, 1.2, etc. When `symmetric` is True, the selected values are -1.2, -0.8, -0.2, 0.2, 0.8, 1.2, etc. The `min` and `max` keywords are mutually exclusive. If both are set to True, only the local maxima are returned. """ if self.ndim > 1: raise NeXusError( "This function only works on one-dimensional data") if smooth: data = self.smooth(factor=10) else: data = self x = data.nxaxes[0] if symmetric: condition = np.where( np.isclose( np.remainder(x-offset, divisor), 0.0, atol=tol) | np.isclose( np.remainder(x+offset, divisor), 0.0, atol=tol) | np.isclose( np.remainder(x-offset, divisor), divisor, atol=tol) | np.isclose( np.remainder(x+offset, divisor), divisor, atol=tol)) else: def sign(x): return np.where(x != 0.0, np.sign(x), 1) condition = np.where( np.isclose( np.remainder( sign(x)*(np.abs(x)-offset), divisor), 0.0, atol=tol) | np.isclose( np.remainder( sign(x)*(np.abs(x)-offset), divisor), divisor, atol=tol)) if min and max: raise NeXusError("Select either 'min' or 'max', not both") elif min or max: def consecutive(idx): return np.split(idx, np.where(np.diff(idx) != 1)[0]+1) signal = data.nxsignal unique_idx = [] if max: for idx in consecutive(condition[0]): unique_idx.append(idx[0]+signal.nxvalue[idx].argmax()) else: for idx in consecutive(condition[0]): unique_idx.append(idx[0]+signal.nxvalue[idx].argmin()) condition = (np.array(unique_idx),) return data[condition] def project(self, axes, limits=None, summed=True): """ Return a projection of the data. This function is used to create two-dimensional projections of two- or higher-dimensional data. The axes can be in any order. The limits are defined for all the dimensions. They either define the axis limits in the two-dimensional projection or the range over which the data are summed or averaged for additional dimensions. Parameters ---------- axes : tuple of ints Axes to be used in the two-dimensional projection. limits : tuple A tuple of minimum and maximum values for each dimension. By default, all values are set to None. For signals of greater than two dimensions, this sums all the data in the orthogonal dimensions. summed : bool, optional True if the data is summed over the limits, False if the data is averaged, by default True. Returns ------- NXdata NXdata group containing the projection. Notes ----- Using the default `limits=None` should be used with caution, since it requires reading the entire data set into memory. """ signal_rank = self.ndim if not is_iterable(axes): axes = [axes] if limits is None: limits = [(None, None)] * signal_rank elif len(limits) < signal_rank: raise NeXusError("Too few limits specified") elif len(axes) > 2: raise NeXusError( "Projections to more than two dimensions not supported") elif any([np.isclose(limits[axis][1]-limits[axis][0], 0) for axis in axes]): raise NeXusError("One of the projection axes has zero range") projection_axes = sorted([x for x in range(len(limits)) if x not in axes], reverse=True) idx, _ = self.slab([slice(_min, _max) for _min, _max in limits]) result = self[idx] idx, slab_axes = list(idx), list(projection_axes) for slab_axis in slab_axes: if isinstance(idx[slab_axis], numbers.Integral): idx.pop(slab_axis) projection_axes.pop(projection_axes.index(slab_axis)) for i in range(len(projection_axes)): if projection_axes[i] > slab_axis: projection_axes[i] -= 1 if projection_axes: if summed: result = result.sum(projection_axes) else: result = result.average(projection_axes) if len(axes) > 1 and axes[0] > axes[1]: signal = result.nxsignal errors = result.nxerrors weights = result.nxweights result[signal.nxname].replace(signal.transpose()) result.nxsignal = result[signal.nxname] if errors: result[errors.nxname].replace(errors.transpose()) result.nxerrors = result[errors.nxname] if weights: result[weights.nxname].replace(weights.transpose()) result.nxweights = result[weights.nxname] result.nxaxes = result.nxaxes[::-1] return result def transpose(self, axes=None): """ Transpose the signal array and axes. Parameters ---------- axes : tuple or list of ints, optional If specified, it must be a tuple or list which contains a permutation of [0,1,..,N-1] where N is the number of axes. If not specified, defaults to range(self.ndim)[::-1]. Returns ------- NXdata NXdata group containing the data with transposed axes. """ if axes is None: axes = list(range(self.ndim)[::-1]) result = NXdata(self.nxsignal.transpose(axes=axes), [self.nxaxes[i] for i in axes], title=self.nxtitle) if self.nxangles: if self.ndim == 3: result.nxangles = [self.nxangles[i] for i in axes] else: result.nxangles = self.nxangles return result def slab(self, idx): """ Return a tuple containing the signal slice and sliced axes. Real values in the slice objects are converted to array indices given by the axis values of the corresponding dimension. Parameters ---------- idx : slice Indices of the slab. Returns ------- tuple Tuple containing the signal slice and a list of sliced axes. """ if (isinstance(idx, numbers.Real) or isinstance(idx, numbers.Integral) or isinstance(idx, slice)): idx = [idx] signal = self.nxsignal axes = self.nxaxes slices = [] for i, ind in enumerate(idx): if isinstance(ind, np.ndarray): slices.append(ind) axes[i] = axes[i][ind] elif is_real_slice(ind): if signal.shape[i] == axes[i].shape[0]: axis = axes[i].boundaries() else: axis = axes[i] ind = convert_index(ind, axis) if signal.shape[i] < axes[i].shape[0]: axes[i] = axes[i][ind] if isinstance(ind, slice) and ind.stop is not None: ind = slice(ind.start, ind.stop-1, ind.step) elif (signal.shape[i] == axes[i].shape[0]): if isinstance(ind, slice) and ind.stop is not None: ind = slice(ind.start, ind.stop-1, ind.step) axes[i] = axes[i][ind] slices.append(ind) else: ind = convert_index(ind, axes[i]) slices.append(ind) if (isinstance(ind, slice) and ind.stop is not None and signal.shape[i] < axes[i].shape[0]): ind = slice(ind.start, ind.stop+1, ind.step) axes[i] = axes[i][ind] return tuple(slices), axes def get_default(self): """Return this NXdata group as the default for plotting.""" return self def set_default(self, over=False): """Set group as the default for plotting. Parameters ========== over : bool True if previous default should be overwritten """ group = self.nxgroup if group is None: raise NeXusError( "The default cannot be defined without a parent group") else: group.attrs['default'] = self.nxname parent_group = group.nxgroup if parent_group: if over or parent_group.get_default() is None: group.set_default(over=over) @property def plottable_data(self): """True if the NXdata group is plottable.""" if self.nxsignal is not None: return self else: return None @property def plot_shape(self): """ Shape of plottable data. Size-one axes are removed from the shape. """ if self.nxsignal is not None: return self.nxsignal.plot_shape else: return None @property def plot_rank(self): """ Rank of the plottable data. Size-one axes are removed from the rank. """ if self.nxsignal is not None: return self.nxsignal.plot_rank else: return None @property def plot_axes(self): """ Plottable axes. Size-one axes are removed. """ signal = self.nxsignal if signal is not None: if len(signal.shape) > len(signal.plot_shape): axes = self.nxaxes newaxes = [] for i in range(signal.ndim): if signal.shape[i] > 1: newaxes.append(axes[i]) return newaxes else: return self.nxaxes else: return None def is_image(self): """True if the data are compatible with an RGB(A) image.""" signal = self.nxsignal if signal is not None: return signal.is_image() else: return False def plot(self, fmt='', xmin=None, xmax=None, ymin=None, ymax=None, vmin=None, vmax=None, **kwargs): """ Plot the NXdata group. The format argument is used to set the color and type of the markers or lines for one-dimensional plots, using the standard Matplotlib syntax. The default is set to blue circles. All keyword arguments accepted by matplotlib.pyplot.plot can be used to customize the plot. Parameters ---------- fmt : str, optional Matplotlib format string, by default '' xmin : float, optional Minimum x-value in plot, by default None xmax : float, optional Maximum x-value in plot, by default None ymin : float, optional Minimum y-value in plot, by default None ymax : float, optional Maximum y-value in plot, by default None vmin : float, optional Minimum signal value for 2D plots, by default None vmax : float, optional Maximum signal value for 2D plots, by default None Notes ----- In addition to the Matplotlib keyword arguments, the following are defined :: log = True - plot the intensity on a log scale logy = True - plot the y-axis on a log scale logx = True - plot the x-axis on a log scale over = True - plot on the current figure image = True - plot as an RGB(A) image """ signal = self.nxsignal if signal is None: raise NeXusError("No plotting signal defined") elif not signal.exists(): raise NeXusError(f"Data for '{signal.nxpath}' does not exist") elif not signal.is_plottable(): raise NeXusError(f"'{signal.nxpath}' is not plottable") else: axes = self.plot_axes if axes is not None and not self.nxsignal.valid_axes(axes): raise NeXusError("Defined axes not compatible with the signal") if ('interpretation' in signal.attrs and 'rgb' in signal.attrs['interpretation'] and signal.is_image()): kwargs['image'] = True # Plot with the available plotter try: from __main__ import plotview if plotview is None: raise ImportError except ImportError: from .plot import plotview plotview.plot(self, fmt, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, vmin=vmin, vmax=vmax, **kwargs) def oplot(self, fmt='', **kwargs): """Plot the data over the current figure.""" self.plot(fmt=fmt, over=True, **kwargs) def logplot(self, fmt='', xmin=None, xmax=None, ymin=None, ymax=None, vmin=None, vmax=None, **kwargs): """Plot the data intensity on a log scale.""" self.plot(fmt=fmt, log=True, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, vmin=vmin, vmax=vmax, **kwargs) def implot(self, fmt='', xmin=None, xmax=None, ymin=None, ymax=None, vmin=None, vmax=None, **kwargs): """Plot the data intensity as an RGB(A) image.""" if (self.nxsignal.plot_rank > 2 and (self.nxsignal.shape[-1] == 3 or self.nxsignal.shape[-1] == 4)): self.plot(fmt=fmt, image=True, xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, vmin=vmin, vmax=vmax, **kwargs) else: raise NeXusError("Invalid shape for RGB(A) image") @property def ndim(self): """Rank of the NXdata signal.""" signal = self.nxsignal if signal is None: raise NeXusError("No signal defined for NXdata group") else: return signal.ndim @property def shape(self): """Shape of the NXdata signal.""" signal = self.nxsignal if signal is None: raise NeXusError("No signal defined for NXdata group") else: return signal.shape @property def nxsignal(self): """NXfield containing the signal data.""" if len(self) == 1 and self.NXfield: return self.NXfield[0] elif 'signal' in self.attrs and self.attrs['signal'] in self: return self[self.attrs['signal']] for obj in self.values(): if 'signal' in obj.attrs and text(obj.attrs['signal']) == '1': if isinstance(self[obj.nxname], NXlink): return self[obj.nxname].nxlink else: return self[obj.nxname] return None @nxsignal.setter def nxsignal(self, signal): if isinstance(signal, NXfield) or isinstance(signal, NXlink): self.attrs['signal'] = signal.nxname if signal not in self: self[signal.nxname] = signal elif isinstance(signal, str): self.attrs['signal'] = signal else: raise NeXusError("Signal value must be a NXfield or string") @property def nxaxes(self): """List of NXfields containing the axes.""" def empty_axis(i): return NXfield(np.arange(self.nxsignal.shape[i]), name=f'Axis{i}') def plot_axis(axis): return NXfield(axis.nxdata, name=axis.nxname, attrs=axis.attrs) try: if 'axes' in self.attrs: axis_names = _readaxes(self.attrs['axes']) elif self.nxsignal is not None and 'axes' in self.nxsignal.attrs: axis_names = _readaxes(self.nxsignal.attrs['axes']) axes = [None] * len(axis_names) for i, axis_name in enumerate(axis_names): axis_name = axis_name.strip() if axis_name == '' or axis_name == '.': axes[i] = empty_axis(i) else: axes[i] = plot_axis(self[axis_name]) return axes except (AttributeError, IndexError, KeyError, UnboundLocalError): axes = [] for entry in self: if 'axis' in self[entry].attrs: axis = self[entry].attrs['axis'] if axis not in axes and self[entry] is not self.nxsignal: axes[axis] = self[entry] else: return None if axes: return [plot_axis(axes[axis]) for axis in sorted(axes)] elif self.nxsignal is not None: return [NXfield(np.arange(self.nxsignal.shape[i]), name=f'Axis{i}') for i in range(self.nxsignal.ndim)] return None @nxaxes.setter def nxaxes(self, axes): if not is_iterable(axes): axes = [axes] axes_attr = [] for axis in axes: if axis is None: axes_attr.append('.') elif isinstance(axis, NXfield): axes_attr.append(axis.nxname) if axis not in self: self[axis.nxname] = axis elif isinstance(axis, str): axes_attr.append(axis) else: raise NeXusError("Axis values must be NXfields or strings") self.attrs['axes'] = axes_attr @property def nxerrors(self): """NXfield containing the signal errors.""" signal = self.nxsignal errors = None if signal is None: raise NeXusError("No signal defined for NXdata group") else: if signal.nxname+'_errors' in self: errors = self[signal.nxname+'_errors'] elif ('uncertainties' in signal.attrs and signal.attrs['uncertainties'] in self): errors = self[signal.attrs['uncertainties']] elif 'errors' in self: errors = self['errors'] if errors and errors.shape == signal.shape: return errors return None @nxerrors.setter def nxerrors(self, errors): signal = self.nxsignal if signal is None: raise NeXusError("No signal defined for NXdata group") else: if errors.shape != signal.shape: raise NeXusError("Error shape incompatible with the signal") name = signal.nxname+'_errors' self[name] = errors @property def nxweights(self): """NXfield containing the signal weights.""" signal = self.nxsignal weights = None if signal is None: raise NeXusError("No signal defined for NXdata group") else: if signal.nxname+'_weights' in self: weights = self[signal.nxname+'_weights'] elif ('weights' in signal.attrs and signal.attrs['weights'] in self): weights = self[signal.attrs['weights']] elif 'weights' in self: weights = self['weights'] if weights and weights.shape == signal.shape: return weights return None @nxweights.setter def nxweights(self, weights): signal = self.nxsignal if signal is None: raise NeXusError("No signal defined for NXdata group") else: if weights.shape != signal.shape: raise NeXusError("Weights shape incompatible with the signal") name = signal.nxname+'_weights' self[name] = weights @property def nxangles(self): """Attribute containing angles between the axes in degrees.""" if 'angles' in self.attrs: try: return self.attrs['angles'].tolist() except AttributeError: return self.attrs['angles'] else: return None @nxangles.setter def nxangles(self, angles): if self.ndim == 2: try: self.attrs['angles'] = float(angles) except TypeError: raise NeXusError("Specify a single number for 2D data") elif self.ndim == 3: try: if len(angles) == 3: self.attrs['angles'] = [float(a) for a in angles] else: raise NeXusError("Specify three numbers for 3D data") except TypeError: raise NeXusError("Specify three numbers for 3D data") else: raise NeXusError("Angles only supported for 2D and 3D data") @property def mask(self): """ NXfield containing the signal mask if one exists. This is set to a value of None or np.ma.nomask to remove the mask. """ signal = self.nxsignal if signal is not None: return signal.mask else: return None @mask.setter def mask(self, value): signal = self.nxsignal if signal is None: return if value is None: value = np.ma.nomask if value is np.ma.nomask and signal.mask is not None: signal.mask = np.ma.nomask if isinstance(signal.mask, NXfield): del self[signal.mask.nxname] if 'mask' in signal.attrs: del signal.attrs['mask'] @property def nxsignals(self): """List of all signals in the NXdata group.""" signals = [] if self.nxsignal is not None: signals.append(self.nxsignal.nxname) signals.extend([signal.nxname for signal in self.nxauxiliary_signals if signal.nxname != self.nxsignal.nxname]) return [self[signal] for signal in signals] @property def nxauxiliary_signals(self): """List of auxiliary signals in the NXdata group.""" signals = [] if 'auxiliary_signals' in self.attrs: if isinstance(self.attrs['auxiliary_signals'], str): signals.append(self.attrs['auxiliary_signals']) else: signals.extend([signal for signal in self.attrs['auxiliary_signals']]) return [self[signal] for signal in signals] @nxauxiliary_signals.setter def nxauxiliary_signals(self, signals): if isinstance(signals, str): self.attrs['auxiliary_signals'] = signals else: signals = list(signals) if all(isinstance(signal, str) for signal in signals): self.attrs['auxiliary_signals'] = signals elif all(isinstance(signal, NXfield) for signal in signals): self.attrs['auxiliary_signals'] = [signal.nxname for signal in signals] else: raise NeXusError( "Signals must be a list of strings or NXfields") @property def nxindices(self): """Dictionary of fields defined with axis indices.""" indices = [axis for axis in self.attrs if axis.endswith('_indices')] return {axis.strip('_indices'): self.attrs[axis] for axis in indices} @nxindices.setter def nxindices(self, indices): for axis, index in indices.items(): self.attrs[axis+'_indices'] = index @property def nxcoordinates(self): """ List of NXfields defined as signal coordinates. Note that the use of the coordinates attribute is under discussion and has not been formally approved by the NeXus standard. However, the attribute can be added to NeXus files without violating the existing standard. """ if 'coordinates' in self.attrs: return [self[coordinate] for coordinate in self.attrs['coordinates']] else: return [] @nxcoordinates.setter def nxcoordinates(self, coordinates): if all(isinstance(coordinate, str) for coordinate in coordinates): self.attrs['coordinates'] = coordinates elif all(isinstance(coordinate, NXfield) for coordinate in coordinates): self.attrs['coordinates'] = [coordinate.nxname for coordinate in coordinates] else: raise NeXusError( "Coordinates must be a list of strings or NXfields") class NXmonitor(NXdata): """NXmonitor group, a subclass of the NXdata class.""" def __init__(self, signal=None, axes=None, *args, **kwargs): NXdata.__init__(self, signal=signal, axes=axes, *args, **kwargs) self._class = 'NXmonitor' if "name" not in kwargs: self._name = "monitor" class NXlog(NXgroup): """NXlog group, a subclass of the NXgroup class.""" def __init__(self, *args, **kwargs): self._class = 'NXlog' NXgroup.__init__(self, *args, **kwargs) def plot(self, **kwargs): """ Plot the logged values against the elapsed time. Valid Matplotlib parameters, specifying markers, colors, etc, can be specified using the 'kwargs' dictionary. """ title = NXfield(f"{self.nxname} Log") if 'start' in self['time'].attrs: title = title + ' - starting at ' + self['time'].attrs['start'] NXdata(self['value'], self['time'], title=title).plot(**kwargs) class NXprocess(NXgroup): """NXprocess group, a subclass of the NXgroup class.""" def __init__(self, *args, **kwargs): self._class = 'NXprocess' NXgroup.__init__(self, *args, **kwargs) if "date" not in self: from datetime import datetime as dt self.date = dt.isoformat(dt.today()) class NXnote(NXgroup): """NXnote group, a subclass of the NXgroup class.""" def __init__(self, *args, **kwargs): self._class = 'NXnote' NXgroup.__init__(self, **kwargs) for arg in args: if is_text(arg): if "description" not in self: self.description = arg elif "data" not in self: self.data = arg elif isinstance(arg, NXobject): setattr(self, arg.nxname, arg) else: raise NeXusError( "Non-keyword arguments must be valid NXobjects") if "date" not in self: from datetime import datetime as dt self.date = dt.isoformat(dt.today()) # ------------------------------------------------------------------------- # Add remaining base classes as subclasses of NXgroup and append to __all__ for cls in nxclasses: if cls not in globals(): globals()[cls] = _makeclass(cls) __all__.append(cls) # ------------------------------------------------------------------------- def is_real_slice(idx): """True if the slice contains real values.""" def is_real(x): if isinstance(x, slice): x = [x if x is not None else 0 for x in [x.start, x.stop, x.step]] x = np.array(x) return not (np.issubdtype(x.dtype, np.integer) or x.dtype == bool) if idx is None or idx is Ellipsis: return False elif isinstance(idx, slice): return is_real(idx) elif is_iterable(idx): return any([is_real(i) for i in idx]) else: return is_real(idx) def convert_index(idx, axis): """Convert floating point limits to a valid array index. This is for one-dimensional axes only. If the index is a tuple of slices, i.e., for two or more dimensional data, the index is returned unchanged. Parameters ---------- idx : slice Slice to be converted. axis : NXfield Axis used to define the indices of the float values. Returns ------- slice Converted slice. """ if is_real_slice(idx) and axis.ndim > 1: raise NeXusError( "NXfield must be one-dimensional for floating point slices") elif is_iterable(idx) and len(idx) > axis.ndim: raise NeXusError("Slice dimension incompatible with NXfield") if axis.size == 1: idx = 0 elif isinstance(idx, slice) and not is_real_slice(idx): if idx.start is not None and idx.stop is not None: if idx.stop == idx.start or idx.stop == idx.start + 1: idx = idx.start elif isinstance(idx, slice): if isinstance(idx.start, NXfield) and isinstance(idx.stop, NXfield): idx = slice(idx.start.nxdata, idx.stop.nxdata, idx.step) if (idx.start is not None and idx.stop is not None and ((axis.reversed and idx.start < idx.stop) or (not axis.reversed and idx.start > idx.stop))): idx = slice(idx.stop, idx.start, idx.step) if idx.start is None: start = None else: start = axis.index(idx.start) if idx.stop is None: stop = None else: stop = axis.index(idx.stop, max=True) + 1 if start is None or stop is None: idx = slice(start, stop, idx.step) elif stop <= start+1 or np.isclose(idx.start, idx.stop): idx = start else: idx = slice(start, stop, idx.step) elif (not isinstance(idx, numbers.Integral) and isinstance(idx, numbers.Real)): idx = axis.index(idx) return idx def slice_shape(idx, shape): """ Calculate the shape of a slice. Parameters ---------- idx : slice Slice object. shape : tuple Shape of the array being sliced. Returns ------- tuple Shape of the slice. """ def slice_length(slc, dim_size): start = slc.start if slc.start is not None else 0 stop = slc.stop if slc.stop is not None else dim_size step = slc.step if slc.step is not None else 1 if start < 0: start += dim_size if stop < 0: stop += dim_size start = max(0, min(start, dim_size)) stop = max(0, min(stop, dim_size)) if step > 0: length = max(0, (stop - start + step - 1) // step) else: length = max(0, (start - stop - (-step) - 1) // (-step)) return length return tuple(slice_length(slc, dim) for slc, dim in zip(idx, shape)) def centers(axis, dimlen): """ Return the centers of the axis bins. This works regardless if the axis contains bin boundaries or centers. Parameters ---------- dimlen : int Size of the signal dimension. If this is one more than the axis size, it is assumed the axis contains bin boundaries. """ ax = axis.astype(np.float64) if ax.shape[0] == dimlen+1: return (ax[:-1] + ax[1:])/2 else: assert ax.shape[0] == dimlen return ax def getconfig(parameter=None): """ Return configuration parameter. Parameters ---------- parameter : str Name of configuration parameter """ if parameter is None: return NX_CONFIG else: try: return NX_CONFIG[parameter] except KeyError: raise NeXusError(f"'{parameter}' is not a valid parameter") def setconfig(**kwargs): """ Set configuration parameter. Parameters ---------- kwargs : dictionary Key/value pairs of configuration parameters """ global NX_CONFIG for (parameter, value) in kwargs.items(): if parameter not in NX_CONFIG: raise NeXusError(f"'{parameter}' is not a valid parameter") if value == 'None': value = None elif (parameter == 'lock' or parameter == 'lockexpiry' or parameter == 'maxsize' or parameter == 'memory'): try: value = int(value) except TypeError: raise NeXusError(f"'{parameter} must be an integer") elif parameter == 'lockdirectory': if value in [None, 'None', 'none', '']: value = None else: value = str(value) if not NX_CONFIG['lock']: NX_CONFIG['lock'] = 10 elif parameter == 'recursive': if value in ['True', 'true', 'Yes', 'yes', 'Y', 'y', '1']: value = True else: value = False NX_CONFIG[parameter] = value # Update configuration parameters that are defined as environment variables. for parameter in NX_CONFIG: if 'NX_' + parameter.upper() in os.environ: value = os.environ['NX_'+parameter.upper()] setconfig(**{parameter: value}) # If a lock directory is defined, locking should be turned on by default. if NX_CONFIG['lockdirectory'] and not NX_CONFIG['lock']: NX_CONFIG['lock'] = 10 nxgetconfig = getconfig nxsetconfig = setconfig def getcompression(): """Return default compression filter.""" return NX_CONFIG['compression'] def setcompression(value): """Set default compression filter.""" global NX_CONFIG if value == 'None': value = None NX_CONFIG['compression'] = value nxgetcompression = getcompression nxsetcompression = setcompression def getencoding(): """Return the default encoding for strings (usually 'utf-8').""" return NX_CONFIG['encoding'] def setencoding(value): """Set the default encoding for strings (usually 'utf-8').""" global NX_CONFIG NX_CONFIG['encoding'] = value nxgetencoding = getencoding nxsetencoding = setencoding def getlock(): """ Return the number of seconds before a lock acquisition times out. If the value is 0, file locking is disabled. Returns ------- int Number of seconds before a lock acquisition times out. """ return NX_CONFIG['lock'] def setlock(value=10): """ Initialize NeXus file locking. This creates a file with `.lock` appended to the NeXus file name. Parameters ---------- value : int, optional Number of seconds before a lock acquisition times out, by default 10. If the value is set to 0, file locking is disabled. """ global NX_CONFIG try: NX_CONFIG['lock'] = int(value) except ValueError: raise NeXusError("Invalid value for file lock time") nxgetlock = getlock nxsetlock = setlock def getlockexpiry(): """ Return the number of seconds before a file lock expires. If the value is 0, the file lock persists indefinitely. Returns ------- int Number of seconds before a file lock expires. """ return NX_CONFIG['lockexpiry'] def setlockexpiry(value=28800): """ Sets the lock file expiry. This creates a file with `.lock` appended to the NeXus file name. Parameters ---------- value : int, optional Number of seconds before a lock file is considered stale, by default 8*3600. If the value is set to 0, the file lock persists indefinitely. """ global NX_CONFIG try: NX_CONFIG['lockexpiry'] = int(value) except ValueError: raise NeXusError("Invalid value for file lock expiry") nxgetlockexpiry = getlockexpiry nxsetlockexpiry = setlockexpiry def getlockdirectory(): """ Return the path to the lock directory. If the value is None, lock files are stored in the same directory as the file. Returns ------- str Path to the lock directory. """ return NX_CONFIG['lockdirectory'] def setlockdirectory(value): """ Define a directory to store lock files. If the value is None, lock files are stored in the same directory as the file. Parameters ---------- value : str, optional Path to the lock directory. """ global NX_CONFIG if value is not None: value = Path(value).resolve(strict=True) NX_CONFIG['lockdirectory'] = value nxgetlockdirectory = getlockdirectory nxsetlockdirectory = setlockdirectory def getmaxsize(): """ Return the default maximum array size in memory. If the array size is larger than this value, it will be stored in core memory instead. Returns ------- int Maximum array size in memory. """ return NX_CONFIG['maxsize'] def setmaxsize(value): """Set the default maximum array size in memory.""" global NX_CONFIG try: NX_CONFIG['maxsize'] = int(value) except ValueError: raise NeXusError("Invalid value for maximum array size") nxgetmaxsize = getmaxsize nxsetmaxsize = setmaxsize def getmemory(): """Return the memory limit for data arrays (in MB).""" return NX_CONFIG['memory'] def setmemory(value): """Set the memory limit for data arrays (in MB).""" global NX_CONFIG try: NX_CONFIG['memory'] = int(value) except ValueError: raise NeXusError("Invalid value for memory limit") nxgetmemory = getmemory nxsetmemory = setmemory def getrecursive(): """ Return True if files are opened recursively by default. Returns ------- bool True if files are to be opened recursively. """ return bool(NX_CONFIG['recursive']) def setrecursive(value): """ Set whether files are opened recursively by default. The default can be overridden by setting the 'recursive' keyword when opening a file. Parameters ---------- value : bool True if files are to be opened recursively by default. """ global NX_CONFIG if value in [True, 'True', 'true', 'Yes', 'yes', 'Y', 'y', 1]: value = True else: value = False try: NX_CONFIG['recursive'] = value except ValueError: raise NeXusError("Invalid value for setting default recursion.") nxgetrecursive = getrecursive nxsetrecursive = setrecursive # File level operations def load(filename, mode='r', recursive=None, **kwargs): """ Open or create a NeXus file and load its tree. Notes ----- This is aliased to `nxload` to avoid name clashes with other packages, such as NumPy. `nxload` is the version included in wild card imports. Parameters ---------- filename : str Name of the file to be opened or created. mode : {'r', 'rw', 'r+', 'w', 'a'}, optional File mode, by default 'r' recursive : bool, optional If True, the file tree is loaded recursively, by default True. If False, only the entries in the root group are read. Other group entries will be read automatically when they are referenced. Returns ------- NXroot NXroot object containing the NeXus tree. """ if recursive is None: recursive = NX_CONFIG['recursive'] with NXFile(filename, mode, recursive=recursive, **kwargs) as f: root = f.readfile() return root nxload = nxopen = load def save(filename, group, mode='w', **kwargs): """ Write a NeXus file from a tree of NeXus objects. Parameters ---------- filename : str or Path Name of the file to be saved. group : NXgroup Group containing the tree to be saved. mode : {'w', 'w-', 'a'}, optional Mode to be used opening the file, by default 'w'. """ if group.nxclass == 'NXroot': root = group elif group.nxclass == 'NXentry': root = NXroot(group) else: root = NXroot(NXentry(group)) with NXFile(filename, mode, **kwargs) as f: f.writefile(root) f.close() nxsave = save def duplicate(input_file, output_file, mode='w-', **kwargs): """ Duplicate an existing NeXus file. Parameters ---------- input_file : str Name of file to be copied. output_file : str Name of the new file. mode : {'w', 'w-', 'a'}, optional Mode to be used in opening the new file, by default 'w-'. """ with NXFile(input_file, 'r') as input, NXFile(output_file, mode) as output: output.copyfile(input, **kwargs) nxduplicate = duplicate def directory(filename, short=False): """ Print the contents of the named NeXus file. Parameters ---------- filename : str Name of the file to be read. short : bool, optional True if only a short tree is to be printed, by default False """ root = load(filename) if short: print(root.short_tree) else: print(root.tree) nxdir = directory def consolidate(files, data_path, scan_path=None, idx=None): """ Create NXdata using a virtual field to combine multiple files. Parameters ---------- files : list of str or NXroot List of files to be consolidated. If a scan variable is defined, the files are sorted by its values. data_path : str or NXdata Path to the NXdata group to be consolidated. If the argument is a NXdata group, its path within the NeXus file is used. scan_path : str or NXfield, optional Path to the scan variable in each file, by default None. If the argument is a NXfield, its path within the NeXus file is used. If not specified, the scan is constructed from file indices. idx : int, optional Data slice to be used in the virtual field, by default None """ if isinstance(files[0], str): files = [nxload(f) for f in files] if isinstance(data_path, NXdata): data_path = data_path.nxpath if scan_path: if isinstance(scan_path, NXfield): scan_path = scan_path.nxpath scan_files = [f for f in files if data_path in f and scan_path in f and f[data_path].nxsignal.exists()] else: scan_files = [f for f in files if data_path in f and f[data_path].nxsignal.exists()] scan_file = scan_files[0] if scan_path: scan_values = [f[scan_path] for f in scan_files] scan_values, scan_files = list( zip(*(sorted(zip(scan_values, scan_files))))) scan_axis = NXfield(scan_values, name=scan_file[scan_path].nxname) if 'long_name' in scan_file[scan_path].attrs: scan_axis.attrs['long_name'] = ( scan_file[scan_path].attrs['long_name']) if 'units' in scan_file[scan_path].attrs: scan_axis.attrs['units'] = scan_file[scan_path].attrs['units'] else: scan_axis = NXfield(range(len(scan_files)), name='file_index', long_name='File Index') signal = scan_file[data_path].nxsignal axes = scan_file[data_path].nxaxes if idx is not None: axes = [axis[s] for axis, s in zip(axes, idx)] sources = [f[signal.nxpath].nxfilename for f in scan_files] scan_field = NXvirtualfield(signal, sources, shape=signal.shape, idx=idx, name=signal.nxname) scan_data = NXdata(scan_field, [scan_axis] + axes, name=scan_file[data_path].nxname) scan_data.title = data_path return scan_data nxconsolidate = consolidate def demo(argv): """ Process a list of command line commands. Parameters ---------- argv : list of str List of commands. """ if len(argv) > 1: op = argv[1] else: op = 'help' if op == 'ls': for f in argv[2:]: dir(f) elif op == 'copy' and len(argv) == 4: tree = load(argv[2]) save(argv[3], tree) elif op == 'plot' and len(argv) == 4: tree = load(argv[2]) for entry in argv[3].split('.'): tree = getattr(tree, entry) tree.plot() tree._plotter.show() else: usage = f""" usage: {argv[0]} cmd [args] copy fromfile.nxs tofile.nxs ls *.nxs plot file.nxs entry.data """ print(usage) nxdemo = demo if __name__ == "__main__": import sys nxdemo(sys.argv) ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1757359830.0 nexusformat-2.0.0/src/nexusformat/nexus/utils.py0000644000077000000000000004360015057627326020473 0ustar00rosborn# ----------------------------------------------------------------------------- # Copyright (c) 2024-2025, Kaitlyn Marlor, Ray Osborn, Justin Wozniak. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING, distributed with this software. # ----------------------------------------------------------------------------- import logging import os import re import shutil import sys from pathlib import Path if sys.version_info < (3, 10): from importlib_resources import files as package_files else: from importlib.resources import files as package_files import numpy as np from colored import Fore, Style from dateutil.parser import parse name_pattern = re.compile(r'^[a-zA-Z0-9_]([a-zA-Z0-9_.]*[a-zA-Z0-9_])?$') def get_logger(): """ Returns a logger instance and sets the log level to DEBUG. The logger has a stream handler that writes to sys.stdout. Returns ------- logger : logging.Logger A logger instance. """ logger = logging.getLogger("NXValidate") logger.setLevel(logging.WARNING) logger.propagate = False nexpy_running = False try: from nexpy.gui.pyqt import QtWidgets app = QtWidgets.QApplication.instance() if app and app.applicationName() == "nexpy": nexpy_running = True except Exception: pass if nexpy_running: from nexpy.gui.utils import NXValidationHandler gui_handler = NXValidationHandler(capacity=1000) gui_handler.setFormatter(NXFormatter('%(message)s')) logger.addHandler(gui_handler) else: stream_handler = logging.StreamHandler(stream=sys.stdout) stream_handler.setFormatter(NXFormatter('%(message)s')) logger.addHandler(stream_handler) logger.total = {'warning': 0, 'error': 0} return logger def get_log_level(level='warning'): """ Converts a given log level to its corresponding logging constant. Parameters ---------- level : str or int The log level to be converted. Can be 'info', 'debug', 'warning', or 'error', or the corresponding logging constants. Returns ------- log_level : int The converted log level. """ if level == 'info' or level == logging.INFO: return logging.INFO elif level == 'debug' or level == logging.DEBUG: return logging.DEBUG elif level == 'warning' or level == 'warnings' or level == logging.WARNING: return logging.WARNING elif level == 'error' or level == 'errors' or level == logging.ERROR: return logging.ERROR def is_valid_name(name): """ Checks if a given name is valid according to the defined name pattern. Parameters ---------- name : str The name to be validated. Returns ------- bool True if the name is valid, False otherwise. """ if re.match(name_pattern, name): return True else: return False def is_valid_iso8601(date_string): """ Checks if a given date is valid according to the ISO 8601 standard. Parameters ---------- date_string : str The date string to be validated. Returns ------- bool True if the date string is valid, False otherwise. """ try: parse(date_string) return True except ValueError: return False def is_valid_int(dtype): """ Checks if a given data type is a valid integer type. Parameters ---------- dtype : type The data type to be validated. Returns ------- bool True if the data type is a valid integer type, False otherwise. """ return np.issubdtype(dtype, np.integer) def is_valid_float(dtype): """ Checks if a given data type is a valid floating point type. Parameters ---------- dtype : type The data type to be validated. Returns ------- bool True if the data type is a valid floating point type, False otherwise. """ return np.issubdtype(dtype, np.floating) def is_valid_bool(dtype): """ Checks if a given data type is a valid boolean type. Parameters ---------- dtype : type The data type to be validated. Returns ------- bool True if the data type is a valid boolean type, False otherwise. """ return np.issubdtype(dtype, np.bool_) def is_valid_char(dtype): """ Checks if a given data type is a valid character type. Parameters ---------- dtype : type The data type to be validated. Returns ------- bool True if the data type is a valid character type, False otherwise. """ from .tree import string_dtype return (np.issubdtype(dtype, np.str_) or np.issubdtype(dtype, np.bytes_) or dtype == string_dtype) def is_valid_char_or_number(dtype): """ Checks if a given data type is a valid character or number type. Parameters ---------- dtype : type The data type to be validated. Returns ------- bool True if the data type is a valid character or number type, False otherwise. """ return is_valid_char(dtype) or is_valid_number(dtype) def is_valid_complex(dtype): """ Checks if a given data type is a valid complex number type. Parameters ---------- dtype : type The data type to be validated. Returns ------- bool True if the data type is a valid complex type, False otherwise. """ return np.issubdtype(dtype, np.complex) def is_valid_number(dtype): """ Checks if a given data type is a valid number type. Parameters ---------- dtype : type The data type to be validated. Returns ------- bool True if the data type is a valid number type, False otherwise. """ return np.issubdtype(dtype, np.number) def is_valid_posint(dtype): """ Checks if a given data type is a valid positive integer type. Parameters ---------- dtype : type The data type to be validated. Returns ------- bool True if the data type is a valid positive integer type, False otherwise. """ if np.issubdtype(dtype, np.integer): info = np.iinfo(dtype) return info.max > 0 return False def is_valid_uint(dtype): """ Checks if a given data type is a valid unsigned integer type. Parameters ---------- dtype : type The data type to be validated. Returns ------- bool True if the data type is a valid unsigned integer type, False otherwise. """ return np.issubdtype(dtype, np.unsignedinteger) def all_dtypes(): """ Returns a list of all valid data types. Returns ------- list of str A list of all valid data types. """ return ["str", "bytes", "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float32", "float64", "complex64", "complex128"] def map_dtype(nexus_type): """ Maps a given NeXus data type to a string representation. Parameters ---------- nexus_type : str The NeXus data type . Returns ------- str The string representation of the data type. """ nexus_dtypes = {"NX_BINARY": ["uint8"], "NX_BOOLEAN": ["uint8"], "NX_CHAR": ["str", "bytes"], "NX_COMPLEX": ["complex64", "complex128"], "NX_DATE_TIME": ["char"], "NX_FLOAT": ["float64", "float32"], "NX_INT": ["int64", "int32", "int16", "int8", "uint64", "uint32", "uint16", "uint8"], "NX_NUMBER": ["float64", "float32", "int64", "int32", "int16", "int8", "uint64", "uint32", "uint16", "uint8"], "NX_PCOMPLEX": ["complex128", "complex64"], "NX_POSINT": ["uint64", "uint32", "uint16", "uint8"], "NX_QUATERNION": ["complex128", "complex64"], "NX_UINT": ["uint8", "uint16", "uint32", "uint64"], "NX_CHAR_OR_NUMBER": ["str", "bytes", "float64", "float32", "int64", "int32", "int16", "int8", "uint64", "uint32", "uint16", "uint8"]} return nexus_dtypes[nexus_type] def strip_namespace(element): """ Recursively strips namespace from an XML element and its children. Parameters ---------- element : xml.etree.ElementTree.Element The XML element to strip namespace from. """ if '}' in element.tag: element.tag = element.tag.split('}', 1)[1] for child in element: strip_namespace(child) def convert_xml_dict(xml_dict): """ Convert an XML dictionary to a more readable format. Parameters ---------- xml_dict : dict The XML dictionary to be converted. Returns ------- dict The converted XML dictionary. Notes ----- If the XML dictionary contains '@type' and '@name', it will be converted to a dictionary with '@name' as the key. If the XML dictionary contains only '@type', it will be converted to a dictionary with '@type' as the key. If the XML dictionary does not contain '@type' or '@name', it will be returned as is. """ if '@type' in xml_dict: if '@name' in xml_dict: key = '@name' else: key = '@type' elif '@name' in xml_dict: key = '@name' else: return xml_dict return {xml_dict[key]: {k: v for k, v in xml_dict.items() if k != key}} def xml_to_dict(element): """ Convert an XML element to a dictionary. Parameters ---------- element : xml element The XML element to be converted. Returns ------- dict A dictionary representation of the XML element. """ result = {} if element.attrib: attrs = element.attrib for attr in attrs: result[f"@{attr}"] = attrs[attr] for child in element: if child.tag == 'doc' and child.text: result[child.tag] = re.sub(r'[\t\n]+', ' ', child.text.strip()) elif child.tag == 'enumeration': result[child.tag] = [item.attrib['value'] for item in child] elif child.tag == 'dimensions': result[child.tag] = {} if 'rank' in child.attrib: result[child.tag].update({'rank': child.attrib['rank']}) result[child.tag]['dim'] = {} for item in [c for c in child if c.tag == 'dim']: if 'index' in item.attrib and 'value' in item.attrib: result[child.tag]['dim'].update( {int(item.attrib['index']): item.attrib['value']}) else: child_dict = convert_xml_dict(xml_to_dict(child)) if child.tag in result: result[child.tag].update(child_dict) else: result[child.tag] = child_dict return result def merge_dicts(dict1, dict2): """ Recursively merges two dictionaries into one. Parameters ---------- dict1 : dict The dictionary to be updated. dict2 : dict The dictionary to update with. Returns ------- dict The updated dictionary. """ for key, value in dict2.items(): if (key in dict1 and isinstance(dict1[key], dict) and isinstance(value, dict)): merge_dicts(dict1[key], value) else: dict1[key] = value return dict1 def readaxes(axes): """Return a list of axis names stored in the 'axes' attribute. If the input argument is a string, the names are assumed to be separated by a delimiter, which can be white space, a comma, or a colon. If it is a list of strings, they are converted to strings. Parameters ---------- axes : str or list of str Value of 'axes' attribute defining the plotting axes. Returns ------- list of str Names of the axis fields. """ if isinstance(axes, str): return list(re.split(r'[,:; ]', str(axes).strip('[]()').replace('][', ':'))) else: return [str(axis) for axis in axes] def match_strings(pattern_string, target_string): # Create regular expression patterns for both cases """ Check if a target string matches a given pattern string, allowing for uppercase letters at the start or end of the pattern string. Parameters ---------- pattern_string : str The string to be matched against. target_string : str The string to be matched. Returns ------- bool True if the target string matches the pattern string, False otherwise. """ start_pattern = r'^([A-Z]+)([a-z_]+)$' end_pattern = r'^([a-z_]+)([A-Z]+)$' start_match = re.match(start_pattern, pattern_string) end_match = re.match(end_pattern, pattern_string) if start_match: lowercase_part = start_match.group(2) target_pattern = f'^[a-z_]+{re.escape(lowercase_part)}$' if re.match(target_pattern, target_string): return True elif end_match: lowercase_part = end_match.group(1) target_pattern = f'^{re.escape(lowercase_part)}[a-z_]+$' if re.match(target_pattern, target_string): return True return False def get_base_classes(definitions=None): """ Return a list of all base class names. Parameters ---------- definitions : str or Path or None The path to the NeXus definitions directory (default is None). Returns ------- list of str A list of NeXus base class names. """ definitions = get_definitions(definitions=definitions) base_class_path = definitions.joinpath('base_classes') return sorted( [str(c.stem[:-5]) for c in base_class_path.glob('*.nxdl.xml')]) def get_definitions(definitions=None): """ Return the path to the NeXus definitions directory. If the input argument is given, it is converted to a Path object. If it is a string, it is resolved to a full path. If it is None, the path is determined from the 'NX_DEFINITIONS' environment variable or, if that variable is not set, from the location of the nexusformat package. Parameters ---------- definitions : str or Path or None The path to the NeXus definitions directory (default is None). Returns ------- Path The path to the NeXus definitions directory. """ if definitions is not None: if isinstance(definitions, str): definitions = Path(definitions).resolve() elif isinstance(definitions, Path): definitions = definitions.resolve() elif 'NX_DEFINITIONS' in os.environ: definitions = Path(os.environ['NX_DEFINITIONS']).resolve() else: definitions = multiplex_path(package_files('nexusformat.definitions')) return definitions def multiplex_path(path): """ Convert a MultiplexedPath object to a Path object. Parameters ---------- path : str or MultiplexedPath The path to be converted. Returns ------- Path The converted path. """ return Path(re.sub(r"MultiplexedPath\('(.*)'\)", r"\1", str(path))) def truncate_path(path, max_width=None): """Truncate a file path to fit within max_width characters.""" if max_width is None: max_width = terminal_width() - 20 path = Path(path) full_path = path.resolve() site_packages = None for parent in full_path.parents: if parent.name == "site-packages" or parent.name == "src": site_packages = parent break if site_packages: full_path = str(full_path.relative_to(site_packages)) else: full_path = str(full_path) if len(full_path) > max_width: return "..." + full_path[-max_width:] return full_path def terminal_width(): """ Returns the width of the terminal in characters. Returns ------- int The width of the terminal in characters. """ try: terminal_width = shutil.get_terminal_size().columns except OSError: terminal_width = 80 return terminal_width def check_nametype(item): """ Return the value of the 'nameType' attribute for a given item. Parameters ---------- item : dict The dictionary representation of the item. Returns ------- str The value of the 'nameType' attribute. """ if '@nameType' in item: return item['@nameType'] else: return 'specified' def check_dimension_sizes(dimensions): """ Check if a list of values are all within one of each other. This handles the case where axis bin boundaries are stored. Parameters ---------- dimensions : list The list of dimensions to be checked. Returns ------- bool True if dimensions are the same to within ± 1, False otherwise. """ if not dimensions: return False min_dimension = min(dimensions) max_dimension = max(dimensions) return max_dimension - min_dimension <= 1 def remove_deprecations(items): valid_items = {} for item in items: if '@deprecated' not in items[item]: valid_items[item] = items[item] return valid_items class NXFormatter(logging.Formatter): COLORS = { 'DEBUG': Fore.blue, 'INFO': Style.reset, 'WARNING': Fore.rgb(255, 165, 0) + Style.BOLD, 'ERROR': Fore.red + Style.BOLD, 'CRITICAL': Style.reset } def format(self, record): """Format the specified record as text.""" log_color = self.COLORS.get(record.levelname, Style.reset) message = super().format(record) return f"{log_color}{message}{Style.reset}" ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1748719305.0 nexusformat-2.0.0/src/nexusformat/nexus/validate.py0000644000077000000000000014512415016653311021114 0ustar00rosborn# ----------------------------------------------------------------------------- # Copyright (c) 2024-2025, Kaitlyn Marlor, Ray Osborn, Justin Wozniak. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING, distributed with this software. # ----------------------------------------------------------------------------- import logging import xml.etree.ElementTree as ET from pathlib import Path from . import NeXusError, NXentry, NXfield, NXgroup, NXlink, NXsubentry, nxopen from .utils import (check_dimension_sizes, check_nametype, get_definitions, get_log_level, get_logger, is_valid_bool, is_valid_char, is_valid_char_or_number, is_valid_complex, is_valid_float, is_valid_int, is_valid_iso8601, is_valid_name, is_valid_number, is_valid_posint, is_valid_uint, match_strings, merge_dicts, readaxes, strip_namespace, truncate_path, xml_to_dict) logger = get_logger() validators = {} def get_validator(nxclass, definitions=None): """ Retrieves a validator instance for a given NeXus class. Validators are stored in a global dictionary. If a validator has not already been created yet, it is created. Parameters ---------- nxclass : str The name of the NeXus class to retrieve a validator for. definitions : str, optional The path to the directory containing the NeXus base class definitions (default is None). Returns ------- Validator A validator instance for the specified NeXus class. """ if nxclass not in validators: validator = GroupValidator(nxclass, definitions=definitions) nxclass = validator.nxclass validators[nxclass] = validator elif (definitions is not None and Path(definitions).resolve() != validators[nxclass].definitions): validators[nxclass] = GroupValidator(nxclass, definitions=definitions) return validators[nxclass] class Validator(): def __init__(self, definitions=None): """ Initializes a new Validator instance. """ self.definitions = get_definitions(definitions=definitions) self.baseclasses = self.definitions / 'base_classes' if not self.baseclasses.exists(): raise NeXusError(f'"{self.baseclasses}" does not exist') self.applications = self.definitions / 'applications' if not self.applications.exists(): self.applications = None self.contributions = self.definitions / 'contributed_definitions' if not self.contributions.exists(): self.contributions = None self.filepath = None self.parent = None self.logged_messages = [] self.indent = 0 def __repr__(self): return f'{self.__class__.__name__}({self.filepath.stem})' def get_attributes(self, element): """ Retrieves the attributes of a given XML item as a dictionary. Parameters ---------- element : XML.Element The item from which to retrieve attributes. Returns ------- dict A dictionary containing the item's attributes. """ try: result = {} result = {f"@{k}": v for k, v in element.attrib.items()} for child in element: if child.tag == 'enumeration': result[child.tag] = [item.attrib['value'] for item in child] elif child.tag != 'doc': result[child.tag] = self.get_attributes(child) return result except Exception: return {} def is_valid_link(self, item): """ Checks if the target to an external link exists. Parameters ---------- item : NXlink or NXfield The item to check. Returns ------- bool True if the target exists, False otherwise. """ if item.is_external(): target = f'{item._filename}[{item._target}]' else: target = item._target if item.exists(): if isinstance(item, NXfield): self.log(f'This field is linked to "{target}"', level='info') elif isinstance(item, NXgroup): self.log(f'This group is linked to "{target}"', level='info') return True else: self.log(f'This is a broken link to "{target}"', level='error') return False def log(self, message, level='info', indent=None): """ Logs a message with a specified level and indentation. Parameters ---------- message : str The message to be logged. level : str, optional The level of the message (default is 'info'). indent : int, optional The indentation level of the message (default is None). """ if indent is None: indent = self.indent self.logged_messages.append((message, level, indent)) def output_log(self): """ Outputs the logged messages and resets the log. This function iterates over the logged messages, counts the number of messages at each level, and logs each message using the log function. If the logger level is set to WARNING or ERROR and there are no messages at that level, the function resets the log and returns without logging any messages. """ warning = 0 error = 0 for item in self.logged_messages: if item[1] == 'warning': warning += 1 elif item[1] == 'error': error += 1 if ((logger.level == logging.WARNING and warning == 0 and error == 0) or (logger.level == logging.ERROR and error == 0)): self.logged_messages = [] return if self.parent is None: for message, level, indent in self.logged_messages: log(message, level=level, indent=indent) else: self.parent.logged_messages.extend(self.logged_messages) self.logged_messages = [] class GroupValidator(Validator): def __init__(self, nxclass, definitions=None): """ Initializes the GroupValidator instance. Parameters ---------- nxclass : str The name of the NeXus class for which to create a validator. definitions : str, optional The path to the directory containing the NeXus base class definitions (default is None). """ super().__init__(definitions=definitions) self.nxclass = nxclass if self.nxclass is None or self.nxclass == 'NXgroup': self.xml_dict = None self.valid_class = False else: self.xml_dict = self.get_xml_dict() self.get_valid_fields() self.get_valid_groups() self.get_valid_attributes() def get_xml_dict(self): """ Retrieves the root element of the NeXus class XML file. If the NeXus class is specified and the corresponding XML file exists, this method parses the file and returns its root element. Otherwise, it returns None. Returns ------- root : ElementTree.Element or None The root element of the NeXus class definition XML file, or None if the class is not specified or the file does not exist. """ class_path = None if self.nxclass: if Path(self.nxclass).exists(): class_path = Path(self.nxclass) self.nxclass = Path(self.nxclass).stem.replace('.nxdl', '') else: class_path = self.baseclasses / (f'{self.nxclass}.nxdl.xml') if not class_path.exists(): if self.contributions is not None: class_path = ( self.contributions / (f'{self.nxclass}.nxdl.xml')) if class_path is not None and class_path.exists(): self.filepath = class_path.resolve() tree = ET.parse(class_path) root = tree.getroot() strip_namespace(root) xml_dict = xml_to_dict(root) self.valid_class = True if '@ignoreExtraAttributes' in xml_dict: self.ignoreExtraAttributes = True else: self.ignoreExtraAttributes = False if '@ignoreExtraFields' in xml_dict: self.ignoreExtraFields = True else: self.ignoreExtraFields = False if '@ignoreExtraGroups' in xml_dict: self.ignoreExtraGroups = True else: self.ignoreExtraGroups = False if '@extends' in xml_dict: parent_validator = get_validator( xml_dict['@extends'], definitions=self.definitions) xml_extended_dict = parent_validator.get_xml_dict() xml_dict = merge_dicts(xml_dict, xml_extended_dict) if 'symbols' in xml_dict: self.symbols = xml_dict['symbols']['symbol'] else: self.symbols = {} else: xml_dict = None self.valid_class = False return xml_dict def get_valid_fields(self): """ Retrieves valid fields from the NXDL file. This instantiates two dictionaries. The valid_fields dictionary contains fields that are defined in the NXDL file with fixed names. The partial_fields dictionary contains fields whose names have uppercase characters that can be substituted for the actual name in a NeXus file. """ valid_fields = {} partial_fields = {} if self.xml_dict is not None: if 'field' not in self.xml_dict: self.valid_fields = valid_fields self.partial_fields = partial_fields return fields = self.xml_dict['field'] for field in fields: nameType = check_nametype(fields[field]) if nameType == 'any': valid_fields[field] = fields[field] self.ignoreExtraFields = True elif nameType == 'partial': partial_fields[field] = fields[field] partial_fields[field]['@name'] = field elif nameType == 'specified': valid_fields[field] = fields[field] else: self.log(f'The NXDL file uses an invalid name type ' f'"{nameType}"', level='error') self.valid_fields = valid_fields self.partial_fields = partial_fields def get_valid_groups(self): """ Retrieves valid groups from the NXDL file. This instantiates two dictionaries. The valid_groups dictionary contains groups that are defined in the NXDL file with fixed names. The partial_groups dictionary contains groups whose names have uppercase characters that can be substituted for the actual name in a NeXus file """ valid_groups = {} partial_groups = {} if self.xml_dict is not None: if 'group' not in self.xml_dict: self.valid_groups = valid_groups self.partial_groups = partial_groups return groups = self.xml_dict['group'] for group in groups: nameType = check_nametype(groups[group]) if nameType =='any': valid_groups[group] = groups[group] self.ignoreExtraGroups = True elif nameType == 'partial': partial_groups[group] = groups[group] partial_groups[group]['@name'] = group elif nameType == 'specified': valid_groups[group] = groups[group] else: self.log(f'The NXDL file uses an invalid name type ' f'"{nameType}"', level='error') self.valid_groups = valid_groups self.partial_groups = partial_groups def get_valid_attributes(self): """ Retrieves valid group attributes from the NXDL file. This instantiates two dictionaries. The valid_attributes dictionary contains attributes that are defined in the NXDL file with fixed names. The partial_attributes dictionary contains attributes whose names have uppercase characters that can be substituted for the actual name in a NeXus file """ valid_attributes = {} partial_attributes = {} if self.xml_dict is not None: if 'attribute' not in self.xml_dict: self.valid_attributes = valid_attributes self.partial_attributes = partial_attributes return attributes = self.xml_dict['attribute'] for attribute in attributes: nameType = check_nametype(attributes[attribute]) if nameType == 'any': valid_attributes[attribute] = attributes[attribute] self.ignoreExtraAttributes = True elif nameType == 'partial': partial_attributes[attribute] = attributes[attribute] partial_attributes[attribute]['@name'] = attribute elif nameType == 'specified': valid_attributes[attribute] = attributes[attribute] else: self.log(f'The NXDL file uses an invalid name type ' f'"{nameType}"', level='error') self.valid_attributes = valid_attributes self.partial_attributes = partial_attributes def check_data(self, group): """ Checks that the signal and axes are present in the group. This method also checks that the axes have the correct length and that the axis sizes match the signal shape. Parameters ---------- group : NXgroup The group to be checked. """ if 'signal' in group.attrs: signal = group.attrs['signal'] if signal in group.entries: self.log(f'Signal "{signal}" is present in the group', level='info') signal_field = group[signal] else: self.log(f'Signal "{signal}" is not present in the group', level='warning') signal = None else: self.log('"@signal" is not present in the group', level='error') signal = None if 'axes' in group.attrs: axes = readaxes(group.attrs['axes']) if signal in group and group[signal].exists(): if len(axes) != group[signal].ndim: self.log('"@axes" length does not match the signal rank', level='error') else: self.log('"@axes" has the correct length') for i, axis in enumerate(axes): if axis in group.entries: self.log(f'Axis "{axis}" is present in the group', level='info') axis_field = group[axis] if signal in group and group[signal].exists(): if check_dimension_sizes( [signal_field.shape[i], axis_field.shape[0]]): self.log(f'Axis "{axis}" size is consistent ' 'with the signal shape', level='info') else: self.log(f'Axis "{axis}" size is inconsistent ' 'with the signal shape', level='error') elif axis != '.': self.log(f'Axis "{axis}" is not present in the group', level='error') else: self.log('"@axes" is not present in the group', level='warning') def reset_symbols(self): """ Resets all symbols dictionaries to be empty. This is used to initialize the dictionaries before validating a NeXus group. """ for symbol in self.symbols: self.symbols[symbol] = {} def check_symbols(self, indent=None): """ Checks the values of all symbols in the symbols dictionary. This checks for consistency of values of all symbols in the symbols dictionary. If the values are all the same, a message is logged at the "info" level. If the values are not all the same, but all differ by at most 1, a message is logged at the "info" level. Otherwise, a message is logged at the "warning" level. Parameters ---------- indent : int, optional The indentation level for logging (default is 0). """ if indent is not None: self.indent = indent for symbol in self.symbols: values = [] for entry in [e for e in self.symbols[symbol] if e != 'doc']: values.append(self.symbols[symbol][entry]) if not values: continue if len(set(values)) == 1: self.log(f'All values for "{symbol}" are the same') self.indent += 1 for entry in self.symbols[symbol]: self.log(f'{entry}: {self.symbols[symbol][entry]}') self.indent -= 1 elif check_dimension_sizes(values): self.log(f'All values for "{symbol}" are the same (to ±1)') self.indent += 1 for entry in self.symbols[symbol]: self.log(f'{entry}: {self.symbols[symbol][entry]}') self.indent -= 1 else: self.log(f'Values for "{symbol}" are not unique', level='warning') self.indent += 1 for entry in self.symbols[symbol]: self.log(f'{entry}: {self.symbols[symbol][entry]}', level='warning') self.indent -= 1 def validate(self, group, parent=None, indent=0, level=None): """ Validates a given group against the NeXus standard. This function checks the validity of a group's name, class, and attributes. It also recursively validates the group's entries. Parameters ---------- group : object The group to be validated. indent : int, optional The indentation level for logging (default is 0). level : str, optional The logging level (default is None). """ self.parent = parent self.indent = indent if level is not None: logger.setLevel(get_log_level(level)) self.log(f'{group.nxclass}: {group.nxpath}', level='all') self.indent += 1 if group.nxclass == 'NXgroup': if parent.nxclass == 'NXroot': self.log('This group has no NeXus base class assigned ' 'and will not be inspected') else: self.log('This group has no NeXus base class assigned', level='error') self.output_log() return if not is_valid_name(group.nxname): self.log(f'"{group.nxname}" is an invalid name', level='error') if isinstance(group, NXlink): if not self.is_valid_link(group): self.output_log() return if not self.valid_class: self.log(f'{group.nxclass} is not a valid base class', level='error') self.output_log() return parent_group = group.nxgroup if group.nxclass != 'NXroot' and group.nxgroup is not None: parent_group = group.nxgroup parent_validator = get_validator(parent_group.nxclass, definitions=self.definitions) parsed = False if group.nxname in parent_validator.valid_groups: cls = parent_validator.valid_groups[group.nxname]['@type'] if group.nxclass != cls: self.log(f'{group.nxname} should have a class of ' f'{cls}, not {group.nxclass}', level='error') parsed = True elif parent_validator.partial_groups: for partial_name in parent_validator.partial_groups: if match_strings(partial_name, group.nxname): self.log(f'This group name matches "{partial_name}", ' f'which is allowed in {parent_group.nxclass}') parsed = True if not parsed: if group.nxclass in parent_validator.valid_groups: self.log('This group is a valid class in ' f'{parent_group.nxclass}') elif group.nxclass not in parent_validator.valid_groups: if parent_validator.ignoreExtraGroups: self.log(f'{group.nxclass} is not defined in ' f'{parent_group.nxclass}. ' 'Additional classes are allowed.') else: self.log(f'{group.nxclass} is an invalid class in ' f'{parent_group.nxclass}', level='error') for attribute in group.attrs: if attribute == 'target': continue parsed = False if attribute in self.valid_attributes: self.log( f'"@{attribute}" is a valid attribute in {group.nxclass}') parsed = True elif self.partial_attributes: for partial_name in self.partial_attributes: if match_strings(partial_name, attribute): self.log( f'"@{attribute}" matches "{partial_name}", ' f'which is allowed in {group.nxclass}') parsed = True if not parsed: if self.ignoreExtraAttributes: self.log( f'"@{attribute}" is not defined as an attribute in ' f'{group.nxclass}. Additional attributes are allowed.') else: self.log( f'"@{attribute}" is not defined as an attribute' f' in {group.nxclass}', level='warning') if group.nxclass == 'NXdata': self.check_data(group) self.reset_symbols() for entry in group.entries: item = group.entries[entry] if isinstance(item, NXfield): if entry in self.valid_fields: tag = self.valid_fields[entry] else: tag = None for partial_name in self.partial_fields: if match_strings(partial_name, entry): tag = self.partial_fields[partial_name] break field_validator.validate(tag, item, parent=self, indent=self.indent) elif isinstance(item, NXgroup): validator = get_validator(item.nxclass, definitions=self.definitions) validator.validate(item, parent=self, indent=self.indent) self.check_symbols() self.output_log() self.indent -= 1 class FieldValidator(Validator): def __init__(self): """ Initializes a FieldValidator instance. """ super().__init__() def check_type(self, field, dtype): """ Checks the data type of a given field. Parameters ---------- field : object The field to be validated. dtype : str The NeXus data type to validate against. """ if dtype == 'NX_DATE_TIME': if is_valid_iso8601(field.nxvalue): self.log('The field value is a valid NX_DATE_TIME') else: self.log('The field value is not a valid NX_DATE_TIME', level='warning') elif dtype == 'NX_INT': if is_valid_int(field.dtype): self.log('The field value is a valid NX_INT') else: self.log('This field is not a valid NX_INT', level='warning') elif dtype == 'NX_FLOAT': if is_valid_float(field.dtype): self.log('The field value is a valid NX_FLOAT') else: self.log('The field value is not a valid NX_FLOAT', level='warning') elif dtype == 'NX_BOOLEAN': if is_valid_bool(field.dtype): self.log('The field value is a valid NX_BOOLEAN') else: self.log('The field value is not a valid NX_BOOLEAN', level='warning') elif dtype == 'NX_CHAR': if is_valid_char(field.dtype): self.log('The field value is a valid NX_CHAR') else: self.log('The field value is not a valid NX_CHAR', level='warning') elif dtype == 'NX_CHAR_OR_NUMBER': if is_valid_char_or_number(field.dtype): self.log('TThe field value is a valid NX_CHAR_OR_NUMBER') else: self.log('The field value is not a valid NX_CHAR_OR_NUMBER', level='warning') elif dtype == 'NX_COMPLEX': if is_valid_complex(field.dtype): self.log('The field value is a valid NX_COMPLEX value') else: self.log('The field value is not a valid NX_COMPLEX value', level='warning') elif dtype == 'NX_PCOMPLEX': if is_valid_complex(field.dtype): self.log('The field value is a valid NX_PCOMPLEX value') else: self.log('The field value is not a valid NX_PCOMPLEX value', level='warning') elif dtype == 'NX_NUMBER': if is_valid_number(field.dtype): self.log('The field value is a valid NX_NUMBER') else: self.log('The field value is not a valid NX_NUMBER', level='warning') elif dtype == 'NX_POSINT': if is_valid_posint(field.dtype): self.log('The field value is a valid NX_POSINT') else: self.log('The field value is not a valid NX_POSINT', level='warning') elif dtype == 'NX_UINT': if is_valid_uint(field.dtype): self.log('The field value is a valid NX_UINT') else: self.log('The field value is not a valid NX_UINT', level='warning') def check_dimensions(self, field, dimensions): """ Checks the field dimensions against the specified dimensions. Parameters ---------- field : The field to check dimensions for. dimensions : The base class attribute containing the dimensions to check against. """ if 'rank' in dimensions: rank = dimensions['rank'] if rank in self.parent.symbols: self.parent.symbols[rank].update({field.nxname: field.ndim}) else: try: rank = int(dimensions['rank']) except ValueError: return if field.ndim == rank: self.log(f'The field has the correct rank of {rank}') else: self.log(f'The field has rank {field.ndim}, ' f'should be {rank}', level='warning') if 'dim' in dimensions: for i, s in dimensions['dim'].items(): if s in self.parent.symbols: if len(field.shape) > i-1: self.parent.symbols[s].update( {field.nxname: field.shape[i-1]}) else: self.log( f'The field rank is {len(field.shape)}, ' f'but the dimension index of "{s}" = {i}', level='warning') else: try: s = int(s) except ValueError: pass if len(field.shape) > i and field.shape[i-1] == s: self.log(f'The field has the correct size of {s}') else: self.log(f'The field has size {field.shape}, ' f'should be {s}', level='warning') def check_enumeration(self, field, enumerations): """ Checks if a field's value is a valid member of an enumerated list. Parameters ---------- field : The field to check the value for. enumerations : The list of valid enumerated values. """ if field.nxvalue in enumerations: self.log( 'The field value is a member of the enumerated list') else: self.log( 'The field value is not a member of the enumerated list', level='error') def check_attributes(self, field, attributes=None, units=None): """ Checks the attributes of a given field. Parameters ---------- field : The field to check attributes for. units : optional The units of the field. If provided, checks if the units are specified in the field attributes. """ if 'signal' in field.attrs: self.log( 'Using "signal" as a field attribute is no longer valid. ' 'Use the group attribute "signal"', level='error') elif 'axis' in field.attrs: self.log('Using "axis" as a field attribute is no longer valid. ' 'Use the group attribute "axes"', level='error') if 'units' in field.attrs: if units: self.log( f'"{field.attrs["units"]}" are specified ' f'as units of {units}') else: self.log(f'"{field.attrs["units"]}" are specified as units') elif units: self.log(f'Units of {units} not specified', level='warning') checked_attributes = ['axis', 'signal', 'units'] if attributes: for attr in attributes: if attr in field.attrs: self.log(f'The defined attribute "@{attr}" is present') checked_attributes.append(attr) elif ('@nameType' in attributes[attr] and attributes[attr]['@nameType'] == 'partial'): for field_attribute in field.attrs: if match_strings(attr, field_attribute): self.log( f'"@{field_attribute}" matches the defined ' f'attribute "{attr}"') checked_attributes.append(attr) checked_attributes.append(field_attribute) if attr not in checked_attributes: self.log( f'The defined attribute "@{attr}" is not present') for attr in [a for a in field.attrs if a not in checked_attributes]: self.log(f'The attribute "@{attr}" is present') def validate(self, tag, field, parent=None, minOccurs=None, link=False, indent=0): """ Validates a field in a NeXus group. Parameters ---------- tag : dict A dictionary containing information about the field. field : object The field to be validated. parent : object, optional The parent object. Defaults to None. minOccurs : int, optional The minimum number of occurrences. Defaults to None. link : bool, optional True if the field is required to be a link. Defaults to False. indent : int, optional The indentation level. Defaults to 0. """ self.parent = parent self.indent = indent group = field.nxgroup if isinstance(field, NXlink): self.log(f'Link: {field.nxpath}', level='all') else: self.log(f'Field: {field.nxpath}', level='all') self.indent += 1 if not is_valid_name(field.nxname): self.log(f'"{field.nxname}" is an invalid name', level='error') if link and not isinstance(field, NXlink): self.log('This field is not a link as required', level='error') if isinstance(field, NXlink): if not self.is_valid_link(field): self.output_log() return if minOccurs is not None: if minOccurs > 0: self.log('This is a required field in the NeXus file') else: self.log('This is an optional field in the NeXus file') elif tag is not None: if '@name' in tag: self.log(f'This field name matches "{tag["@name"]}", ' f'which is allowed in {group.nxclass}') else: self.log(f'This is a valid field in {group.nxclass}') if tag is None: if self.parent.ignoreExtraFields is True: self.log(f'This field is not defined in {group.nxclass} ' 'groups, but additional fields are allowed') else: self.log(f'This field is not defined in {group.nxclass}', level='warning') else: if '@deprecated' in tag: self.log(f'This field is now deprecated. {tag["@deprecated"]}', level='warning') if field.exists(): if '@type' in tag: self.check_type(field, tag['@type']) if 'dimensions' in tag: self.check_dimensions(field, tag['dimensions']) if 'enumeration' in tag: self.check_enumeration(field, tag['enumeration']) if 'attribute' in tag: attributes = tag['attribute'] else: attributes = None if '@units' in tag: units = tag['@units'] else: units = None self.check_attributes(field, attributes=attributes, units=units) self.output_log() field_validator = FieldValidator() class FileValidator(Validator): def __init__(self, filename, definitions=None): """ Initializes a FileValidator instance. Parameters ---------- filename : str The path to the NeXus file to validate. definitions : str, optional The path to the directory containing the NeXus base class definitions (default is None). """ super().__init__(definitions=definitions) self.filepath = Path(filename).resolve() def validate(self, path=None): """ Validates a NeXus file by walking through its tree structure. Each group is validated by its corresponding GroupValidator. Parameters ---------- path : str, optional The path to the group to start validation from (default is None, which means the entire file will be validated). """ with nxopen(self.filepath) as root: if path: parent_group = root[path] else: parent_group = root if not isinstance(parent_group, NXgroup): logger.error(f'{parent_group.nxpath} is not a NeXus group') return validator = get_validator(parent_group.nxclass, definitions=self.definitions) validator.validate(parent_group, parent=self) self.output_log() def validate_file(filename, path=None, definitions=None): """ Validates a NeXus file by walking through its tree structure. Each group is validated by its corresponding GroupValidator. Parameters ---------- filename : str The path to the NeXus file to validate. path : str, optional The path to the group to start validation from (default is None, which means the entire file will be validated). definitions : str, optional The path to the directory containing the NeXus base class definitions (default is None). Returns ------- tuple A tuple containing the total number of warnings and errors encountered while validating the file. """ if not Path(filename).exists(): logger.error(f'File "{filename}" does not exist') return if path is None: path = '/' try: validator = FileValidator(filename, definitions=definitions) except NeXusError as e: logger.error(e) return log_header(validator, filename=filename, path=path) validator.validate(path) return log_summary() class ApplicationValidator(Validator): def __init__(self, application, definitions=None): """ Initializes an ApplicationValidator instance. Parameters ---------- application : str The name of the application definition to load. definitions : str, optional The path to the directory containing the NeXus base class definitions (default is None). """ super().__init__(definitions=definitions) self.symbols = {} self.xml_dict = self.load_application(application) def load_application(self, application): """ Loads an application definition from an XML file. Parameters ---------- application : str, optional The name of the application to be loaded. If not provided, the application name stored in the instance will be used. Returns ------- dict A dictionary representation of the application definition. """ if Path(application).exists(): app_path = Path(application).resolve() elif self.applications is not None: app_path = self.applications / (f'{application}.nxdl.xml') if not app_path.exists() and self.contributions is not None: app_path = self.contributions / (f'{application}.nxdl.xml') elif self.contributions is not None: app_path = self.contributions / (f'{application}.nxdl.xml') else: app_path = None if app_path is not None and app_path.exists(): tree = ET.parse(app_path) else: raise NeXusError( f'The application definition "{application}" does not exist') xml_root = tree.getroot() strip_namespace(xml_root) if xml_root.tag != 'definition': raise NeXusError( f'The application definition "{application}"' 'does not contain the correct root tag.') symbols = xml_root.find('symbols') if symbols is not None: self.symbols.update(xml_to_dict(symbols)['symbol']) xml_dict = xml_to_dict(xml_root.find('group')) if xml_root.attrib['extends'] != 'NXobject': xml_extended_dict = self.load_application( xml_root.attrib['extends']) xml_dict = merge_dicts(xml_extended_dict, xml_dict) self.filepath = app_path.resolve() return xml_dict def validate_group(self, xml_dict, nxgroup, indent=0): """ Validates a NeXus group against an XML definition. This function checks if the provided NeXus group matches the structure defined in the given XML dictionary. It recursively validates all subgroups and fields within the group, ensuring that the required components are present and correctly formatted. Parameters ---------- xml_dict : dict The XML dictionary containing the definition of the group. nxgroup : NXgroup The NeXus group to be validated. indent : int, optional The current indentation level (default is 0). """ self.indent = indent group_validator = get_validator(nxgroup.nxclass, definitions=self.definitions) group_validator.parent = self for key, value in xml_dict.items(): if key == 'group': for group in value: if '@minOccurs' in value[group]: minOccurs = int(value[group]['@minOccurs']) else: minOccurs = 1 if '@type' in value[group]: name = group group = value[group]['@type'] self.log(f'Group: {name}: {group}', level='all', indent=self.indent) nxgroups = [g for g in nxgroup.component(group) if g.nxname == name] else: name = None self.log(f'Group: {group}', level='all', indent=self.indent) nxgroups = nxgroup.component(group) self.indent += 1 if len(nxgroups) < minOccurs: self.log( f'{len(nxgroups)} {group} group(s) ' f'are in the NeXus file. At least {minOccurs} ' 'are required', level='error') elif minOccurs == 0: self.log( 'This optional group is not in the NeXus file') for i, nxsubgroup in enumerate(nxgroups): if name: if i != 0: self.log(f'Group: {name}: {group}', level='all', indent=self.indent) self.validate_group( value[name], nxsubgroup, indent=self.indent) else: if i != 0: self.log(f'Group: {group}', level='all', indent=self.indent) self.validate_group( value[group], nxsubgroup, indent=self.indent) self.indent -= 1 self.output_log() elif key == 'field' or key == 'link': for field in value: if '@minOccurs' in value[field]: minOccurs = int(value[field]['@minOccurs']) else: minOccurs = 1 if field in nxgroup.entries: group_validator.symbols.update(self.symbols) field_validator.validate( value[field], nxgroup[field], link=(key=='link'), parent=self, minOccurs=minOccurs, indent=self.indent) else: field_path = nxgroup.nxpath + '/' + field self.log(f'{key.capitalize()}: {field_path}', level='all') self.indent += 1 if minOccurs > 0: self.log(f'This required {key} is not ' 'in the NeXus file', level='error') else: self.log(f'This optional {key}) is not ' 'in the NeXus file') self.indent -= 1 self.output_log() group_validator.check_symbols(indent=self.indent) self.output_log() def validate(self, entry, level=None): """ Validates a NeXus entry against an XML definition. This function checks if the provided NeXus entry matches the structure defined in the given XML dictionary. It recursively validates all subgroups and fields within the entry, ensuring that the required components are present and correctly formatted. Parameters ---------- entry : object The NeXus entry to be validated. level : str, optional The logging level (default is None). """ root = entry.nxroot nxpath = entry.nxpath if level is not None: logger.setLevel(get_log_level(level)) self.validate_group(self.xml_dict, root[nxpath]) self.output_log() def validate_application(filename, path=None, application=None, definitions=None): """ Validates a NeXus entry against an application definition. This function checks if the provided NeXus entry matches the structure defined in the given application definition. It recursively validates all subgroups and fields within the entry, ensuring that the required components are present and correctly formatted. Parameters ---------- filename : str The path to the NeXus file to validate. path : str, optional The path to the group to start validation from (default is None, which means the entire file will be validated). application : str, optional The name of the application definition to validate against (default is None). definitions : str, optional The path to the directory containing the NeXus base class definitions (default is None). Returns ------- tuple A tuple containing the total number of warnings and errors encountered while validating the file. """ with nxopen(filename) as root: if path is None: nxpath = root.NXentry[0].nxpath else: nxpath = path entry = root[nxpath] if not (isinstance(entry, NXentry) or isinstance(entry, NXsubentry)): logger.error( f'Path "{nxpath}" is not a NXentry or NXsubentry group') return elif application is None and 'definition' in entry: application = entry['definition'].nxvalue elif application is None: logger.error(f'No application definition is defined in "{nxpath}"') return try: validator = ApplicationValidator(application, definitions=definitions) except NeXusError as e: logger.error(e) return log_header(validator, filename, nxpath, application) validator.validate(entry) return log_summary() def inspect_base_class(base_class, definitions=None): """ Prints the valid components of a NeXus base class. Parameters ---------- base_class : str The name of the NeXus base class to inspect. definitions : str or Path, optional The path to the directory containing the NeXus base class definitions (default is None). """ logger.setLevel(logging.INFO) validator = get_validator(base_class, definitions=definitions) if validator.filepath is not None: log(f"\nValid components of the {base_class} base class") log(f"NXDL File: {truncate_path(validator.filepath)}\n") else: log(f'NXDL file for "{base_class}" does not exist') log(f"Definitions: {truncate_path(validator.filepath)}\n") return tree = ET.parse(validator.filepath) root = tree.getroot() strip_namespace(root) from pygments import highlight from pygments.formatters import TerminalFormatter from pygments.lexers import XmlLexer log(highlight(ET.tostring(root, encoding='unicode'), XmlLexer(), TerminalFormatter())) def log(message, level='info', indent=0): """ Logs a message at a specified level with optional indentation. Parameters ---------- message : str The message to be logged. level : str, optional The level of the log message (default is 'info'). indent : int, optional The number of spaces to indent the log message (default is 0). """ if level == 'info': logger.info(f'{4*indent*" "}{message}') elif level == 'debug': logger.log(logging.DEBUG, f'{4*indent*" "}{message}') elif level == 'warning': logger.warning(f'{4*indent*" "}{message}') logger.total['warning'] += 1 elif level == 'error': logger.error(f'{4*indent*" "}{message}') logger.total['error'] += 1 elif level == 'all': logger.critical(f'{4*indent*" "}{message}') def log_header(validator, filename=None, path=None, application=None): log("\n", level='all') if filename is not None: log(f"Filename: {filename}", level='all') if path is not None: log(f"Path: {path}", level='all') log(f"Definitions: {truncate_path(validator.definitions)}", level='all') if application and Path(application).exists(): application = Path(application).stem[:-5] if application is not None: log(f"Application Definition: {application}", level='all') log(f"NXDL File: {truncate_path(validator.filepath)}", level='all') log("\n", level='all') logger.total = {'warning': 0, 'error': 0} def log_summary(): """ Prints a summary of the total number of warnings and errors encountered during validation and returns the total counts. Returns ------- tuple A tuple containing the total number of warnings and errors. """ if logger.level <= logging.WARNING: log(f'\nTotal number of warnings: {logger.total["warning"]}', level='all') log(f'Total number of errors: {logger.total["error"]}\n', level='all') else: log(f'\nTotal number of errors: {logger.total["error"]}\n', level='all') return (logger.total['warning'], logger.total['error']) ././@PaxHeader0000000000000000000000000000005400000000000010214 xustar0017 gid=660979062 27 mtime=1757533568.885458 nexusformat-2.0.0/src/nexusformat/notebooks/0000755000077000000000000000000015060352601017600 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649549.0 nexusformat-2.0.0/src/nexusformat/notebooks/nexusformat.ipynb0000644000077000000000000004250614777236515023250 0ustar00rosborn{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# NeXus Data Format\n", "\n", "NeXus is an international standard for storing neutron, x-ray and muon data. NeXus data are stored in HDF5 files, using a logical design that makes them easy to navigate, and a pre-defined dictionary of groups, fields, and attributes that describe commonly occurring experimental metadata. Further details can be found on the [NeXus website](http://www.nexusformat.org). This notebook provides a tutorial on using the Python [nexusformat package](http://nexpy.github.io/nexpy/pythonshell.html) to read, write, and manipulate NeXus data." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Installation\n", "Before running this notebook, you should make sure that the `nexusformat` package has been installed. If you have an Anaconda Python environment, type:\n", "\n", " >>> conda install -c nexpy nexusformat\n", " \n", "Otherwise, type:\n", "\n", " >>> pip install nexusformat\n", "\n", "> *N.B.* The `nexusformat` package uses [h5py](http://www.h5py.org) to read and write the underlying HDF5 files. It also requires [numpy](http://numpy.scipy.org/) and, if plotting is required, [matplotlib](http://www.matplotlib.org).\n", "\n", "If already installed, you can skip the following cell:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!pip install nexusformat" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once installed, it can be imported using:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from nexusformat.nexus import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> *N.B.* Wildcard imports are usually discouraged, but all the imported names have `NX` or `nx` as a prefix, reducing the risk of name clashes." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## NeXus Fields\n", "NeXus data and metadata are stored as either numeric fields (scalar or array) or text strings. In the `nexusformat` package, fields can be created dynamically created from the command line, even if no NeXus file is open." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "x=NXfield(np.linspace(1,10.0,10))\n", "x" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this case, the `NXfield` object contains the NumPy array, and can be manipulated using standard NumPy operations." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x + 10" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "np.sin(x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x+np.linspace(11,20.0,10)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Like NumPy arrays, NeXus fields have datatypes and shape, which can be manipulated using standard NumPy operations." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x.dtype" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x.reshape((2,5))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is also possible to create large empty arrays and fill them incrementally as slabs. The array is stored in an in-memory HDF5 file until it is saved to disk. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "x=NXfield(shape=(1000,1000), dtype=np.float32, fillvalue=np.nan)\n", "x[0,3:6]=range(3)\n", "x[0,0:7]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "NeXus fields can contain scalars and arrays of any NumPy data type, as well as text, which is stored in NeXus files as variable-length strings, by default." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "title=NXfield('Small-Angle Scattering')\n", "title" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## NeXus Groups\n", "NeXus fields are stored in groups, which have a class that defines the type of content it contains. In `nexusformat`, these are subclasses of the `NXgroup` class." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "instrument=NXgroup(name='instrument', nxclass='NXinstrument')\n", "instrument" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For classes defined by the NeXus standard, the group can be instantiated by its class name. You can find a list of NeXus classes in the [online manual](http://download.nexusformat.org/doc/html/classes/base_classes/)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sample=NXsample()\n", "sample" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Fields and groups can be added to any group, using either attribute (*i.e.*, `a.b=c`) or dictionary (*i.e.*, `a['b']=c`) assignments." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "entry=NXentry()\n", "entry.title=title\n", "entry.sample=sample\n", "entry['instrument']=instrument\n", "print(entry.tree)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> *N.B.* Dictionary assignments are safer when there are potential name clashes with, *e.g.*, NumPy attributes, and should be used when writing scripts. However, attribute assignments are allowed as a convenience as they are quicker to type in interactive sessions.\n", "\n", "Since group entries are defined in a dictionary, the usual dictionary operations are available." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "'sample' in entry" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for name in entry:\n", " if isinstance(entry[name], NXfield):\n", " print(\"'%s' is a field\" % name)\n", " elif isinstance(entry[name], NXgroup):\n", " print(\"'%s' is a group\" % name)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The attribute or dictionary name used in the group assignment overrides any internal name that might have been defined when creating the NeXus object." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "temperature=NXfield(40.0, name='temp')\n", "entry.sample.temperature=temperature\n", "print(entry.sample.tree)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Extended path strings are recognized in dictionary assignments." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "entry['sample/mass']=10.0\n", "print(entry.tree)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Attributes\n", "Both groups and fields can have attributes that provide additional metadata or serve a structural purpose, such as identifying axes. These are stored in the `attrs` dictionary." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "entry.sample.temperature.attrs['units']='K'\n", "print(sample.tree)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the case of NXfields, attributes can be defined using keyword arguments to the NXfield." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "mass=NXfield(10.0,units='g')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## NXData Groups\n", "The NeXus format defines groups, with class `NXdata`, which are designed to contain the results of the experimental measurement and make them easy to plot. To accomplish this, these groups contain a field, containing one-dimensional or multidimensional arrays, that is designated as the **signal** and one or more one-dimensional fields that are designated as the **axes**. \n", "### Creating NXdata Groups\n", "The `nexusformat` API has a special constructor for creating `NXdata` groups, which allows the signal and axes to be specified as the first two positional arguments." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "en=NXfield(np.linspace(10,35,26),name='energy_transfer',dtype=np.float32,units='meV',\n", " long_name='Energy Transfer (meV)')\n", "co=NXfield([26,28,49,52,96,165,369,932,1933,3510,5170,6265,6863,6766,5566,4366,2789,1611,928,635,392,266,169,141,113,73],\n", " name='counts',dtype=np.int16,long_name='Detector Counts')\n", "data1D=NXdata(co, [en], title='Example 1D Data')\n", "print(data1D.tree)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this example, the first two arguments contain fields representing the signal and axes, respectively. \n", "> *N.B.* In the case of one-dimensional data, it is not necessary to specify the axes as a list.\n", "\n", "> *N.B.* We used the keyword argument, `name`, when creating the NXfields. This is the name is used for the field within the NXdata group. Otherwise, default names would have been assigned to the fields, such as `signal`, `axis1`, `axis2`, *etc.*\n", "\n", "If you want to use group assignments to generate the name automatically, you can create an empty NXdata group and define its `nxsignal` and `nxaxes` properties." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "data2D=NXdata()\n", "data2D.xvals=data2D.yvals=np.linspace(0,2.*np.pi,101)\n", "X,Y=np.meshgrid(data2D.xvals,data2D.yvals)\n", "data2D.zvals=np.sin(X)*np.sin(Y)\n", "data2D.nxsignal=data2D.zvals\n", "data2D.nxaxes=[data2D.yvals,data2D.xvals]\n", "data2D.title='Example 2D Data'\n", "print(data2D.tree)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this example, the `signal` and `axes` attributes of the `NXdata` group were automatically set when the `nxsignal` and `nxaxes` properties were specified.\n", "### Plotting NXdata Groups\n", "The information within the NXdata group is sufficient to allow them to be plotted automatically." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "data1D.plot()\n", "data2D.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `nexusformat` package uses Matplotlib for plotting. The first positional argument of the `plot` function can contain a Matplotlib formatting string." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "data1D.plot('r+')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Slicing NXdata Groups\n", "The NXdata groups can be sliced as though they were a NumPy array, since they contain one signal array." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(data2D[0:51,0:51].tree)\n", "data2D[0:51,0:51].plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In an extension of the usual Python slicing syntax, floating point values can be used to extract a slice using the axis values, rather than the signal array indices, to set the limits." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(data2D[0:np.pi,0:np.pi].tree)\n", "data2D[0:np.pi,0:np.pi].plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Manipulating NXdata Groups\n", "The NXdata groups can be used in arithmetic expressions involving addition, subtraction, multiplication, and division, using the same broadcast rules as NumPy arrays." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "bkgd=100.*data1D.energy_transfer\n", "(2*data1D+bkgd).plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Some statistical functions also make use of the information stored within the group. For example, the " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"Sum: \", str(data1D.sum()), \"Average: \", str(data1D.average()), \"Moment: \", str(data1D.moment()))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## NeXus Design\n", "NeXus files should normally follow a standard layout, which is designed to make it easy to understand the contents without any external documentation.\n", "\n", "Here is a typical group hierarchy - the NXinstrument groups that are included will depend on the nature of the instrument:\n", "\n", "* **NXentry**: This typically encapsulates all the data for a specific run or scan. There can be multiple NXentry groups, which don't necessarily have to contain the same types of data\n", " * **NXsample**: Information concerning the measured sample, *e.g.*, temperature or mass\n", " * **NXinstrument**: The components making up the instrument\n", " * **NXmonochromator**: The parameters defining a monochromator, such as the incident energy\n", " * **NXcollimator**: The parameters defining a collimator\n", " * **NXdetector**: The parameters defining the detector(s)\n", " * **NXdata**: The measured data\n", "\n", "This can be easily initialized by the `nexusformat` package. If the default names are acceptable, then just type the following:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "root=NXroot(NXentry(sample,NXinstrument(NXmonochromator(),NXcollimator(),NXdetector()),data1D))\n", "print(root.tree)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "> The `NXroot` is a virtual class that defines the file-level of a NeXus tree.\n", "\n", "Metadata can then be added to the created groups." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once a root group has been defined, it can be saved to a file.\n", "## Saving and Loading NeXus Data\n", "So far, we have created a NeXus file purely in memory, but it can be saved to disk at any time. Afterwards, all subsequent operations on the data will be automatically saved to the file." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(root.tree)\n", "root.save('example.nxs','w')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This data can be reloaded using the `nxload` function. Possible file modes are:\n", "* `r`: Open as read-only\n", "* `rw`: Open as read-write" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "saved_file=nxload('example.nxs','rw')\n", "print(saved_file.tree)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If the file is opened in read-write mode, all changes to the file are saved automatically." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "saved_file['entry/instrument/monochromator/energy']=NXfield(120.0, units='meV')\n", "print(saved_file.tree)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "NeXus files can be backed up if required." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "saved_file.backup()\n", "saved_file['entry/instrument/monochromator/energy']=NXfield(160.0, units='meV')\n", "print(saved_file.nxbackup)\n", "saved_file.restore(overwrite=True)\n", "print(saved_file.tree)" ] } ], "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.8.12" } }, "nbformat": 4, "nbformat_minor": 2 } ././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.8882802 nexusformat-2.0.0/src/nexusformat/scripts/0000755000077000000000000000000015060352601017264 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1418835152.0 nexusformat-2.0.0/src/nexusformat/scripts/__init__.py0000644000077000000000000000000012444332320021362 0ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649549.0 nexusformat-2.0.0/src/nexusformat/scripts/nexusformat.py0000755000077000000000000000134514777236515022242 0ustar00rosborn#!/usr/bin/env python # ----------------------------------------------------------------------------- # Copyright (c) 2019-2021, NeXpy Development Team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING, distributed with this software. # ----------------------------------------------------------------------------- import argparse import nexusformat def main(): parser = argparse.ArgumentParser( description="Determine version number of nexusformat API") parser.add_argument('-v', '--version', action='version', version=f'nexusformat v{nexusformat.__version__}') parser.parse_args(['--version']) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/scripts/nxcheck.py0000755000077000000000000000517214777236751021316 0ustar00rosborn#!/usr/bin/env python # ----------------------------------------------------------------------------- # Copyright (c) 2024-2025, Kaitlyn Marlor, Ray Osborn, Justin Wozniak. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING, distributed with this software. # ----------------------------------------------------------------------------- import argparse import logging import nexusformat from nexusformat.nexus.validate import (logger, validate_application, validate_file) def main(): parser = argparse.ArgumentParser( prog="nxcheck", description="Check NeXus files against the NeXus standard.") parser.add_argument("filename", nargs = 1, help="name of the NeXus file to be validated") parser.add_argument("-p", "--path", nargs = 1, help = "path to group to be validated in the NeXus file") parser.add_argument("-a", "--application", nargs='?', const=True, help = "validate the NeXus file against its application definition") parser.add_argument("-d", "--definitions", nargs = 1, help = "path to the directory containing NeXus definitions") parser.add_argument("-i", "--info", action='store_true', help = "output info messages in addition to warnings and errors") parser.add_argument("-w", "--warning", action='store_true', help = "output warning and error messages (default)") parser.add_argument("-e", "--error", action='store_true', help = "output errors") parser.add_argument('-v', '--version', action='version', version='%(prog)s v'+nexusformat.__version__) args = parser.parse_args() if args.info: logger.setLevel(logging.INFO) elif args.warning: logger.setLevel(logging.WARNING) elif args.error: logger.setLevel(logging.ERROR) else: logger.setLevel(logging.WARNING) if args.definitions: definitions = args.definitions[0] else: definitions = None if args.filename: filename = args.filename[0] if args.path: path = args.path[0] else: path = None if args.application: if args.application is True: application = None else: application = args.application validate_application(filename, path=path, application=application, definitions=definitions) else: validate_file(filename, path=path, definitions=definitions) else: parser.print_help() if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649549.0 nexusformat-2.0.0/src/nexusformat/scripts/nxconsolidate.py0000755000077000000000000000272414777236515022543 0ustar00rosborn#!/usr/bin/env python # ----------------------------------------------------------------------------- # Copyright (c) 2019-2022, NeXpy Development Team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING, distributed with this software. # ----------------------------------------------------------------------------- import argparse from nexusformat import __version__ from nexusformat.nexus import NXentry, NXroot, nxconsolidate def main(): parser = argparse.ArgumentParser( description="Copy a NeXus file to another file") parser.add_argument('files', action='store', nargs='*', help="name of NeXus input files (wild cards allowed)") parser.add_argument('-d', '--data', required=True, help="path to the NXdata group") parser.add_argument('-s', '--scan', help="path to the scan variable") parser.add_argument('-e', '--entry', default='entry', help="name of NXentry group") parser.add_argument('-o', '--output', required=True, help="name of NeXus output file") parser.add_argument('-v', '--version', action='version', version=f'nxconsolidate v{__version__}') args = parser.parse_args() scan_data = nxconsolidate(args.files, args.data, scan_path=args.scan) NXroot(NXentry(scan_data, name=args.entry)).save(args.output, 'w-') if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649549.0 nexusformat-2.0.0/src/nexusformat/scripts/nxdir.py0000755000077000000000000000173214777236515021013 0ustar00rosborn#!/usr/bin/env python # ----------------------------------------------------------------------------- # Copyright (c) 2019-2021, NeXpy Development Team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING, distributed with this software. # ----------------------------------------------------------------------------- import argparse from nexusformat import __version__ from nexusformat.nexus import nxdir def main(): parser = argparse.ArgumentParser( description="Print a NeXus file tree") parser.add_argument('file', action='store', help="name of NeXus file") parser.add_argument('-s', '--short', action='store_true', help="print only the first level") parser.add_argument('-v', '--version', action='version', version=f'nxdir v{__version__}') args = parser.parse_args() nxdir(args.file, short=args.short) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649549.0 nexusformat-2.0.0/src/nexusformat/scripts/nxduplicate.py0000755000077000000000000000263414777236515022211 0ustar00rosborn#!/usr/bin/env python # ----------------------------------------------------------------------------- # Copyright (c) 2019-2021, NeXpy Development Team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING, distributed with this software. # ----------------------------------------------------------------------------- import argparse from nexusformat import __version__ from nexusformat.nexus import nxduplicate def main(): parser = argparse.ArgumentParser( description="Copy a NeXus file to another file") parser.add_argument('input', action='store', help="name of NeXus input file") parser.add_argument('output', action='store', help="name of NeXus output file") parser.add_argument('-e', '--expand_external', action='store_true', help="store external links within the new file") parser.add_argument('-o', '--overwrite', action='store_true', help="overwrite any existing file") parser.add_argument('-v', '--version', action='version', version=f'nxduplicate v{__version__}') args = parser.parse_args() if args.overwrite: mode = 'w' else: mode = 'w-' nxduplicate(args.input, args.output, mode=mode, expand_external=args.expand_external) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/src/nexusformat/scripts/nxinspect.py0000755000077000000000000000244014777236751021701 0ustar00rosborn#!/usr/bin/env python # ----------------------------------------------------------------------------- # Copyright (c) 2024-2025, Kaitlyn Marlor, Ray Osborn, Justin Wozniak. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING, distributed with this software. # ----------------------------------------------------------------------------- import argparse import nexusformat from nexusformat.nexus.validate import inspect_base_class def main(): parser = argparse.ArgumentParser( prog="nxinspect", description="Inspects base classes.") parser.add_argument('baseclass', action='store', nargs=1, help='base class to be inspected') parser.add_argument("-d", "--definitions", nargs = 1, help = "path to the directory containing NeXus definitions") parser.add_argument('-v', '--version', action='version', version='%(prog)s v'+nexusformat.__version__) args = parser.parse_args() if args.definitions: definitions = args.definitions[0] else: definitions = None if args.baseclass: baseclass = args.baseclass[0] inspect_base_class(baseclass, definitions=definitions) else: parser.print_help() if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649549.0 nexusformat-2.0.0/src/nexusformat/scripts/nxstack.py0000755000077000000000000001656214777236515021351 0ustar00rosborn#!/usr/bin/env python # ----------------------------------------------------------------------------- # Copyright (c) 2013-2022, NeXpy Development Team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING, distributed with this software. # ----------------------------------------------------------------------------- import argparse import re import socket import sys import timeit from pathlib import Path import numpy as np from nexusformat.nexus import (NeXusError, NXdata, NXentry, NXfield, NXnote, NXprocess, NXroot, nxsetcompression, nxversion) prefix_pattern = re.compile(r'^([^.]+)(?:(? 1: z = first + np.arange(z_size) z = NXfield(z, dtype=np.uint16, name='frame_number', maxshape=(5000,)) v = NXfield(name='data', shape=(z_size, v0.shape[0], v0.shape[1]), dtype=np.float32, maxshape=(5000, v0.shape[0], v0.shape[1])) data = NXdata(v, (z, y, x)) else: v = NXfield(name='data', shape=(v0.shape[0], v0.shape[1]), dtype=np.float32) data = NXdata(v, (y, x)) root = NXroot(NXentry(data)) root.save(output_file, 'w') return root def write_data(root, filenames): if len(root.entry.data.data.shape) == 2: root.entry.data.data[:, :] = read_image(filenames[0]) else: z_size = root.entry.data.data.shape[0] image_shape = root.entry.data.data.shape[1:3] chunk_size = root.entry.data.data.chunks[0] min_index = get_index(filenames[0]) max_index = get_index(filenames[-1]) k = 0 for i in range(min_index, min_index+z_size, chunk_size): files = [] for j in range(i, min(i+chunk_size, max_index+1)): if j == get_index(filenames[k]): print('Processing', filenames[k]) files.append(filenames[k]) k += 1 elif k < len(filenames): files.append(None) else: break root.entry.data.data[i-min_index:i+len(files)-min_index, :, :] = ( read_images(files, image_shape)) def main(): parser = argparse.ArgumentParser( description="Stack images into a single NeXus file") parser.add_argument('-d', '--directory', default=Path.cwd(), help="directory containing the raw images") parser.add_argument('-p', '--prefix', nargs='+', help="common prefix to all images") parser.add_argument('-e', '--extension', default='.tif', help="file extension of raw images") parser.add_argument('-o', '--output', help="name of NeXus output file") parser.add_argument('-f', '--first', default=0, type=int, help="first frame to be included in the stacked data") parser.add_argument('-l', '--last', type=int, help="last frame to be included in the stacked data") parser.add_argument('-r', '--reverse', action='store_true', help="store images in reverse order") parser.add_argument('-c', '--compression', help="HDF5 compression method") parser.add_argument('-v', '--version', action='version', version=f'nxstack v{nxversion}') args = parser.parse_args() directory = Path(args.directory) extension = args.extension if not extension.startswith('.'): extension = '.' + extension if args.output is not None: output = Path(args.output) if output.suffix == '': output = output.with_suffix('.nxs') else: output = None compression = args.compression if compression: nxsetcompression(compression) first = args.first last = args.last reverse = args.reverse if args.prefix is None: prefixes = get_prefixes(directory) if len(prefixes) > 1 and output is not None: raise NeXusError( "Only one prefix allowed if the output file is specified") else: prefixes = args.prefix for prefix in prefixes: tic = timeit.default_timer() data_files = get_files(directory, prefix, extension, first, last, reverse) if output is None: output_file = Path(prefix + '.nxs') else: output_file = output root = initialize_nexus_file(output_file, data_files, first) write_data(root, data_files) note = NXnote('nxstack '+' '.join(sys.argv[1:]), (f'Current machine: {socket.gethostname()}\n' f'Current working directory: {Path.cwd()}\n' f'Data files: {data_files[0]} to {data_files[-1]}\n')) root.entry['nxstack'] = NXprocess( program='nxstack', sequence_index=len(root.entry.NXprocess) + 1, version=nxversion, note=note) toc = timeit.default_timer() print(toc-tic, 'seconds for', output_file) if __name__ == "__main__": main() ././@PaxHeader0000000000000000000000000000005500000000000010215 xustar0017 gid=660979062 28 mtime=1757533568.8921726 nexusformat-2.0.0/src/nexusformat.egg-info/0000755000077000000000000000000015060352601017267 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1757533568.0 nexusformat-2.0.0/src/nexusformat.egg-info/PKG-INFO0000644000077000000000000001373115060352600020370 0ustar00rosbornMetadata-Version: 2.4 Name: nexusformat Version: 2.0.0 Summary: Python API to access NeXus data Author-email: Raymond Osborn License: Licensing Terms for NeXpy ------------------------- NeXpy is licensed under the terms of the Modified BSD License (also known as New or Revised BSD), as follows: Copyright (c) 2014-2025, NeXpy Development Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the NeXpy Development Team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. About the NeXpy Development Team ---------------------------------- The NeXpy Development Team is the set of all contributors to the NeXpy project on the Github at https://github.com/nexpy. The project is currently led by Ray Osborn. Copyright --------- The following banner should be used in any source code file to indicate the copyright and license terms: # ----------------------------------------------------------------------------- # Copyright (c) 2014-2025, NeXpy Development Team. # # Distributed under the terms of the Modified BSD License. # # The full license is in the file COPYING, distributed with this software. # ----------------------------------------------------------------------------- Project-URL: Homepage, https://nexpy.github.io/nexpy Project-URL: Repository, https://github.com/nexpy/nexusformat.git Project-URL: Issues, https://github.com/nexpy/nexusformat/issues Project-URL: Documentation, https://nexpy.github.io/nexpy/pythonshell.html Project-URL: Changelog, https://github.com/nexpy/nexusformat/releases Keywords: data format,HDF5,neutron scattering,x-ray scattering Classifier: Development Status :: 5 - Production/Stable Classifier: License :: OSI Approved :: BSD License Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Science/Research Classifier: Topic :: Scientific/Engineering Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 Classifier: Topic :: Scientific/Engineering Classifier: Topic :: Scientific/Engineering :: Visualization Requires-Python: >=3.9 Description-Content-Type: text/markdown License-File: COPYING Requires-Dist: colored Requires-Dist: h5py Requires-Dist: hdf5plugin Requires-Dist: numpy Requires-Dist: packaging Requires-Dist: pygments Requires-Dist: python-dateutil Requires-Dist: scipy Requires-Dist: importlib_resources; python_version <= "3.9" Provides-Extra: testing Requires-Dist: pytest; extra == "testing" Dynamic: license-file Introduction ============ This package provides a Python API to open, create, and manipulate [NeXus data](http://www.nexusformat.org/) written in the HDF5 format. The 'nexusformat' package provides the underlying API for [NeXpy](http://nexpy.github.io/nexpy), which provides a GUI interface for visualizing and analyzing NeXus data. The latest development version is always available from [NeXpy's GitHub repository](https://github.com/nexpy/nexusformat). Installing and Running ====================== Released versions of `nexusformat` can be installed using either ``` $ pip install nexusformat ``` or, if you are in a conda environment:: ``` $ conda install -c conda-forge nexusformat ``` The source code can be downloaded from the NeXpy Git repository: ``` $ git clone http://github.com/nexpy/nexusformat.git ``` Prerequisites ============= The following libraries are used by the full installation of NeXpy. There is more details of the nature of these dependencies in the [NeXpy documentation](http://nexpy.github.io/nexpy). * h5py http://www.h5py.org * numpy http://numpy.org * scipy http://scipy.org User Support ============ Consult the [NeXpy documentation](http://nexpy.github.io/nexpy) for details of both the Python command-line API and how to use the NeXpy GUI. If you have any general questions concerning the use of NeXpy, please address them to the [NeXus Mailing List](http://download.nexusformat.org/doc/html/mailinglist.html). If you discover any bugs, please submit a [Github issue](https://github.com/nexpy/nexusformat/issues), preferably with relevant tracebacks. ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1757533568.0 nexusformat-2.0.0/src/nexusformat.egg-info/SOURCES.txt0000644000077000000000000005706115060352600021163 0ustar00rosborn.gitattributes .gitignore COPYING README.md pyproject.toml .github/dependabot.yaml .github/workflows/ci.yml conda-recipe/bld.bat conda-recipe/build.sh conda-recipe/meta.yaml src/nexusformat/__init__.py src/nexusformat/_version.py src/nexusformat.egg-info/PKG-INFO src/nexusformat.egg-info/SOURCES.txt src/nexusformat.egg-info/dependency_links.txt src/nexusformat.egg-info/entry_points.txt src/nexusformat.egg-info/pbr.json src/nexusformat.egg-info/requires.txt src/nexusformat.egg-info/top_level.txt src/nexusformat/definitions/nxdl.xsd src/nexusformat/definitions/nxdlTypes.xsd src/nexusformat/definitions/applications/NXapm.nxdl.xml src/nexusformat/definitions/applications/NXarchive.nxdl.xml src/nexusformat/definitions/applications/NXarpes.nxdl.xml src/nexusformat/definitions/applications/NXcanSAS.nxdl.xml src/nexusformat/definitions/applications/NXdirecttof.nxdl.xml src/nexusformat/definitions/applications/NXellipsometry.nxdl.xml src/nexusformat/definitions/applications/NXfluo.nxdl.xml src/nexusformat/definitions/applications/NXindirecttof.nxdl.xml src/nexusformat/definitions/applications/NXiqproc.nxdl.xml src/nexusformat/definitions/applications/NXlauetof.nxdl.xml src/nexusformat/definitions/applications/NXmonopd.nxdl.xml src/nexusformat/definitions/applications/NXmpes.nxdl.xml src/nexusformat/definitions/applications/NXmpes_arpes.nxdl.xml src/nexusformat/definitions/applications/NXmx.nxdl.xml src/nexusformat/definitions/applications/NXoptical_spectroscopy.nxdl.xml src/nexusformat/definitions/applications/NXraman.nxdl.xml src/nexusformat/definitions/applications/NXrefscan.nxdl.xml src/nexusformat/definitions/applications/NXreftof.nxdl.xml src/nexusformat/definitions/applications/NXsas.nxdl.xml src/nexusformat/definitions/applications/NXsastof.nxdl.xml src/nexusformat/definitions/applications/NXscan.nxdl.xml src/nexusformat/definitions/applications/NXspe.nxdl.xml src/nexusformat/definitions/applications/NXsqom.nxdl.xml src/nexusformat/definitions/applications/NXstxm.nxdl.xml src/nexusformat/definitions/applications/NXtas.nxdl.xml src/nexusformat/definitions/applications/NXtofnpd.nxdl.xml src/nexusformat/definitions/applications/NXtofraw.nxdl.xml src/nexusformat/definitions/applications/NXtofsingle.nxdl.xml src/nexusformat/definitions/applications/NXtomo.nxdl.xml src/nexusformat/definitions/applications/NXtomophase.nxdl.xml src/nexusformat/definitions/applications/NXtomoproc.nxdl.xml src/nexusformat/definitions/applications/NXxas.nxdl.xml src/nexusformat/definitions/applications/NXxasproc.nxdl.xml src/nexusformat/definitions/applications/NXxbase.nxdl.xml src/nexusformat/definitions/applications/NXxeuler.nxdl.xml src/nexusformat/definitions/applications/NXxkappa.nxdl.xml src/nexusformat/definitions/applications/NXxlaue.nxdl.xml src/nexusformat/definitions/applications/NXxlaueplate.nxdl.xml src/nexusformat/definitions/applications/NXxnb.nxdl.xml src/nexusformat/definitions/applications/NXxps.nxdl.xml src/nexusformat/definitions/applications/NXxrot.nxdl.xml src/nexusformat/definitions/applications/nxdlformat.xsl src/nexusformat/definitions/applications/canSAS/2012-minimum.png src/nexusformat/definitions/applications/canSAS/Q-geometry.jpg src/nexusformat/definitions/applications/canSAS/minimum-required.txt src/nexusformat/definitions/applications/xps/xps_cs.png src/nexusformat/definitions/base_classes/NXactivity.nxdl.xml src/nexusformat/definitions/base_classes/NXactuator.nxdl.xml src/nexusformat/definitions/base_classes/NXaperture.nxdl.xml src/nexusformat/definitions/base_classes/NXapm_charge_state_analysis.nxdl.xml src/nexusformat/definitions/base_classes/NXapm_measurement.nxdl.xml src/nexusformat/definitions/base_classes/NXapm_ranging.nxdl.xml src/nexusformat/definitions/base_classes/NXapm_reconstruction.nxdl.xml src/nexusformat/definitions/base_classes/NXapm_simulation.nxdl.xml src/nexusformat/definitions/base_classes/NXatom.nxdl.xml src/nexusformat/definitions/base_classes/NXattenuator.nxdl.xml src/nexusformat/definitions/base_classes/NXbeam.nxdl.xml src/nexusformat/definitions/base_classes/NXbeam_stop.nxdl.xml src/nexusformat/definitions/base_classes/NXbeam_transfer_matrix_table.nxdl.xml src/nexusformat/definitions/base_classes/NXbending_magnet.nxdl.xml src/nexusformat/definitions/base_classes/NXcalibration.nxdl.xml src/nexusformat/definitions/base_classes/NXcapillary.nxdl.xml src/nexusformat/definitions/base_classes/NXchemical_composition.nxdl.xml src/nexusformat/definitions/base_classes/NXcircuit.nxdl.xml src/nexusformat/definitions/base_classes/NXcite.nxdl.xml src/nexusformat/definitions/base_classes/NXcollection.nxdl.xml src/nexusformat/definitions/base_classes/NXcollectioncolumn.nxdl.xml src/nexusformat/definitions/base_classes/NXcollimator.nxdl.xml src/nexusformat/definitions/base_classes/NXcomponent.nxdl.xml src/nexusformat/definitions/base_classes/NXcoordinate_system.nxdl.xml src/nexusformat/definitions/base_classes/NXcrystal.nxdl.xml src/nexusformat/definitions/base_classes/NXcs_computer.nxdl.xml src/nexusformat/definitions/base_classes/NXcs_filter_boolean_mask.nxdl.xml src/nexusformat/definitions/base_classes/NXcs_memory.nxdl.xml src/nexusformat/definitions/base_classes/NXcs_prng.nxdl.xml src/nexusformat/definitions/base_classes/NXcs_processor.nxdl.xml src/nexusformat/definitions/base_classes/NXcs_profiling.nxdl.xml src/nexusformat/definitions/base_classes/NXcs_profiling_event.nxdl.xml src/nexusformat/definitions/base_classes/NXcs_storage.nxdl.xml src/nexusformat/definitions/base_classes/NXcylindrical_geometry.nxdl.xml src/nexusformat/definitions/base_classes/NXdata.nxdl.xml src/nexusformat/definitions/base_classes/NXdeflector.nxdl.xml src/nexusformat/definitions/base_classes/NXdetector.nxdl.xml src/nexusformat/definitions/base_classes/NXdetector_channel.nxdl.xml src/nexusformat/definitions/base_classes/NXdetector_group.nxdl.xml src/nexusformat/definitions/base_classes/NXdetector_module.nxdl.xml src/nexusformat/definitions/base_classes/NXdisk_chopper.nxdl.xml src/nexusformat/definitions/base_classes/NXdistortion.nxdl.xml src/nexusformat/definitions/base_classes/NXelectron_detector.nxdl.xml src/nexusformat/definitions/base_classes/NXelectronanalyzer.nxdl.xml src/nexusformat/definitions/base_classes/NXenergydispersion.nxdl.xml src/nexusformat/definitions/base_classes/NXentry.nxdl.xml src/nexusformat/definitions/base_classes/NXenvironment.nxdl.xml src/nexusformat/definitions/base_classes/NXevent_data.nxdl.xml src/nexusformat/definitions/base_classes/NXevent_data_apm.nxdl.xml src/nexusformat/definitions/base_classes/NXfabrication.nxdl.xml src/nexusformat/definitions/base_classes/NXfermi_chopper.nxdl.xml src/nexusformat/definitions/base_classes/NXfilter.nxdl.xml src/nexusformat/definitions/base_classes/NXfit.nxdl.xml src/nexusformat/definitions/base_classes/NXfit_function.nxdl.xml src/nexusformat/definitions/base_classes/NXflipper.nxdl.xml src/nexusformat/definitions/base_classes/NXfresnel_zone_plate.nxdl.xml src/nexusformat/definitions/base_classes/NXgeometry.nxdl.xml src/nexusformat/definitions/base_classes/NXgoniometer.nxdl.xml src/nexusformat/definitions/base_classes/NXgrating.nxdl.xml src/nexusformat/definitions/base_classes/NXguide.nxdl.xml src/nexusformat/definitions/base_classes/NXhistory.nxdl.xml src/nexusformat/definitions/base_classes/NXimage.nxdl.xml src/nexusformat/definitions/base_classes/NXinsertion_device.nxdl.xml src/nexusformat/definitions/base_classes/NXinstrument.nxdl.xml src/nexusformat/definitions/base_classes/NXinstrument_apm.nxdl.xml src/nexusformat/definitions/base_classes/NXlens_em.nxdl.xml src/nexusformat/definitions/base_classes/NXlog.nxdl.xml src/nexusformat/definitions/base_classes/NXmanipulator.nxdl.xml src/nexusformat/definitions/base_classes/NXmirror.nxdl.xml src/nexusformat/definitions/base_classes/NXmoderator.nxdl.xml src/nexusformat/definitions/base_classes/NXmonitor.nxdl.xml src/nexusformat/definitions/base_classes/NXmonochromator.nxdl.xml src/nexusformat/definitions/base_classes/NXnote.nxdl.xml src/nexusformat/definitions/base_classes/NXobject.nxdl.xml src/nexusformat/definitions/base_classes/NXoff_geometry.nxdl.xml src/nexusformat/definitions/base_classes/NXoptical_lens.nxdl.xml src/nexusformat/definitions/base_classes/NXoptical_window.nxdl.xml src/nexusformat/definitions/base_classes/NXorientation.nxdl.xml src/nexusformat/definitions/base_classes/NXparameters.nxdl.xml src/nexusformat/definitions/base_classes/NXpdb.nxdl.xml src/nexusformat/definitions/base_classes/NXpeak.nxdl.xml src/nexusformat/definitions/base_classes/NXpid_controller.nxdl.xml src/nexusformat/definitions/base_classes/NXpinhole.nxdl.xml src/nexusformat/definitions/base_classes/NXpolarizer.nxdl.xml src/nexusformat/definitions/base_classes/NXpositioner.nxdl.xml src/nexusformat/definitions/base_classes/NXprocess.nxdl.xml src/nexusformat/definitions/base_classes/NXprogram.nxdl.xml src/nexusformat/definitions/base_classes/NXpump.nxdl.xml src/nexusformat/definitions/base_classes/NXreflections.nxdl.xml src/nexusformat/definitions/base_classes/NXregistration.nxdl.xml src/nexusformat/definitions/base_classes/NXresolution.nxdl.xml src/nexusformat/definitions/base_classes/NXroi_process.nxdl.xml src/nexusformat/definitions/base_classes/NXroot.nxdl.xml src/nexusformat/definitions/base_classes/NXsample.nxdl.xml src/nexusformat/definitions/base_classes/NXsample_component.nxdl.xml src/nexusformat/definitions/base_classes/NXsensor.nxdl.xml src/nexusformat/definitions/base_classes/NXshape.nxdl.xml src/nexusformat/definitions/base_classes/NXslit.nxdl.xml src/nexusformat/definitions/base_classes/NXsource.nxdl.xml src/nexusformat/definitions/base_classes/NXspectrum.nxdl.xml src/nexusformat/definitions/base_classes/NXspindispersion.nxdl.xml src/nexusformat/definitions/base_classes/NXsubentry.nxdl.xml src/nexusformat/definitions/base_classes/NXtransformations.nxdl.xml src/nexusformat/definitions/base_classes/NXtranslation.nxdl.xml src/nexusformat/definitions/base_classes/NXunit_cell.nxdl.xml src/nexusformat/definitions/base_classes/NXuser.nxdl.xml src/nexusformat/definitions/base_classes/NXvelocity_selector.nxdl.xml src/nexusformat/definitions/base_classes/NXwaveplate.nxdl.xml src/nexusformat/definitions/base_classes/NXxraylens.nxdl.xml src/nexusformat/definitions/base_classes/nxdlformat.xsl src/nexusformat/definitions/base_classes/aperture/aperture.png src/nexusformat/definitions/base_classes/attenuator/attenuator.png src/nexusformat/definitions/base_classes/beam_stop/beam_stop.png src/nexusformat/definitions/base_classes/collimator/collimator.png src/nexusformat/definitions/base_classes/disk_chopper/disk_chopper.png src/nexusformat/definitions/base_classes/guide/guide.png src/nexusformat/definitions/base_classes/mirror/mirror.png src/nexusformat/definitions/base_classes/moderator/moderator.png src/nexusformat/definitions/base_classes/monitor/monitor.png src/nexusformat/definitions/base_classes/pinhole/pinhole.png src/nexusformat/definitions/base_classes/slit/slit.png src/nexusformat/definitions/base_classes/source/source.png src/nexusformat/definitions/contributed_definitions/NXaberration.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXaberration_model.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXaberration_model_ceos.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXaberration_model_nion.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXadc.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXaperture_em.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_composition_space_results.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_input_ranging.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_input_reconstruction.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_clusterer.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_distancer.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_intersector.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_nanochem.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_ranger.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_selector.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_spatstat.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_surfacer.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_tessellator.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_config_transcoder.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_clusterer.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_distancer.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_intersector.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_nanochem.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_ranger.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_selector.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_spatstat.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_surfacer.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_tessellator.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXapm_paraprobe_results_transcoder.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXbeam_path.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXbeam_splitter.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_alpha_complex.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_cylinder_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_ellipsoid_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_face_list_data_structure.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_geodesic_mesh.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_grid.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_half_edge_data_structure.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_hexahedron_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_marching_cubes.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_parallelogram_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_point_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_polygon_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_polyhedron_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_polyline_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_roi_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_sphere_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_tetrahedron_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_triangle_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_triangulated_surface_mesh.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcg_unit_normal_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXchamber.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXchemical_composition.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcircuit_board.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXclustering.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcollectioncolumn.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcontainer.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcoordinate_system_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcorrector_cs.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcs_computer.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcs_cpu.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcs_filter_boolean_mask.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcs_gpu.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcs_io_obj.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcs_io_sys.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcs_mm_sys.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcs_prng.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcs_profiling.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcs_profiling_event.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcsg.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXcxi_ptycho.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXdac.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXdeflector.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXdelocalization.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXdispersion.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXdispersion_function.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXdispersion_repeated_parameter.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXdispersion_single_parameter.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXdispersion_table.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXdispersive_material.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXebeam_column.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXelectronanalyser.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXelectrostatic_kicker.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXellipsometry.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXem.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXem_ebsd.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXem_ebsd_conventions.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXem_ebsd_crystal_structure_model.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXenergydispersion.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXevent_data_em.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXevent_data_em_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXfiber.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXgraph_edge_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXgraph_node_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXgraph_root.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXibeam_column.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXimage_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXimage_set_em_adf.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXimage_set_em_kikuchi.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXinteraction_vol_em.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXion.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXisocontour.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXiv_temp.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXlab_electro_chemo_mechanical_preparation.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXlab_sample_mounting.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXlens_opt.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXmagnetic_kicker.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXmanipulator.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXmatch_filter.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXmpes.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXms.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXms_feature_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXms_score_config.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXms_score_results.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXms_snapshot.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXms_snapshot_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXopt.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXoptical_system_em.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXorientation_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXpeak.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXpolarizer_opt.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXprogram.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXpulser_apm.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXpump.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXquadric.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXquadrupole_magnet.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXreflectron.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXregion.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXscanbox_em.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXsensor_scan.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXseparator.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXsimilarity_grouping.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXslip_system_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXsnsevent.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXsnshisto.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXsolenoid_magnet.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXsolid_geometry.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXspatial_filter.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXspectrum_set.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXspectrum_set_em_eels.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXspectrum_set_em_xray.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXspin_rotator.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXspindispersion.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXstage_lab.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXsubsampling_filter.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXsubstance.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXtransmission.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXwaveplate.nxdl.xml src/nexusformat/definitions/contributed_definitions/NXxpcs.nxdl.xml src/nexusformat/definitions/contributed_definitions/nxdlformat.xsl src/nexusformat/definitions/contributed_definitions/container/ComplexContainerBeampath.png src/nexusformat/definitions/contributed_definitions/container/ComplexExampleContainer.png src/nexusformat/definitions/contributed_definitions/region/NXregion-example.png src/nexusformat/examples/chopper.nxs src/nexusformat/nexus/__init__.py src/nexusformat/nexus/completer.py src/nexusformat/nexus/lock.py src/nexusformat/nexus/plot.py src/nexusformat/nexus/tree.py src/nexusformat/nexus/utils.py src/nexusformat/nexus/validate.py src/nexusformat/notebooks/nexusformat.ipynb src/nexusformat/scripts/__init__.py src/nexusformat/scripts/nexusformat.py src/nexusformat/scripts/nxcheck.py src/nexusformat/scripts/nxconsolidate.py src/nexusformat/scripts/nxdir.py src/nexusformat/scripts/nxduplicate.py src/nexusformat/scripts/nxinspect.py src/nexusformat/scripts/nxstack.py tests/conftest.py tests/test_data.py tests/test_entry_groups.py tests/test_fields.py tests/test_files.py tests/test_groups.py tests/test_links.py tests/test_locks.py tests/test_masks.py tests/test_paths.py././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1757533568.0 nexusformat-2.0.0/src/nexusformat.egg-info/dependency_links.txt0000644000077000000000000000000115060352600023334 0ustar00rosborn ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1757533568.0 nexusformat-2.0.0/src/nexusformat.egg-info/entry_points.txt0000644000077000000000000000053315060352600022565 0ustar00rosborn[console_scripts] nexusformat = nexusformat.scripts.nexusformat:main nxcheck = nexusformat.scripts.nxcheck:main nxconsolidate = nexusformat.scripts.nxconsolidate:main nxdir = nexusformat.scripts.nxdir:main nxduplicate = nexusformat.scripts.nxduplicate:main nxinspect = nexusformat.scripts.nxinspect:main nxstack = nexusformat.scripts.nxstack:main ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1497388025.0 nexusformat-2.0.0/src/nexusformat.egg-info/pbr.json0000644000077000000000000000005713120051771020746 0ustar00rosborn{"is_release": false, "git_version": "8cac45a"}././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1757533568.0 nexusformat-2.0.0/src/nexusformat.egg-info/requires.txt0000644000077000000000000000021115060352600021660 0ustar00rosborncolored h5py hdf5plugin numpy packaging pygments python-dateutil scipy [:python_version <= "3.9"] importlib_resources [testing] pytest ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1757533568.0 nexusformat-2.0.0/src/nexusformat.egg-info/top_level.txt0000644000077000000000000000001415060352600022013 0ustar00rosbornnexusformat ././@PaxHeader0000000000000000000000000000005400000000000010214 xustar0017 gid=660979062 27 mtime=1757533568.891785 nexusformat-2.0.0/tests/0000755000077000000000000000000015060352601013575 5ustar00rosborn././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649549.0 nexusformat-2.0.0/tests/conftest.py0000644000077000000000000000270414777236515016022 0ustar00rosborn""" Pytest automatically parses this module for fixtures that can be used in its directory, as well as in any of its subdirectories. This module contains fixtures that return generic NXfields. """ from pytest import fixture import numpy as np from nexusformat.nexus.tree import NXfield @fixture def x(): return NXfield(2 * np.linspace(0.0, 10, 11, dtype=np.float64), name="x") @fixture def y(): return NXfield(3 * np.linspace(0.0, 5.0, 6, dtype=np.float64), name="y") @fixture def z(): return NXfield(4 * np.linspace(0.0, 2.0, 3, dtype=np.float64), name="z") @fixture def field1(): return NXfield((1, 2), name="f1") @fixture def field2(): return NXfield((3, 4), name="f2") @fixture def field3(): return NXfield((5, 6), name="f3") @fixture def field4(): return NXfield("a", name="f1") @fixture def arr1D(): return np.linspace(0.0, 100.0, 101, dtype=np.float64) @fixture def arr2D(): return np.array(((1, 2, 3, 4), (5, 6, 7, 8)), dtype=np.int32) @fixture def arr3D(): return np.resize(np.linspace(0.0, 124.0, 125, dtype=np.float64), (5, 5, 5)) @fixture def v(): v = NXfield(np.linspace(0, 99, num=100, dtype=np.float64), name="v") v.resize((2, 5, 10)) return v @fixture def im(): return NXfield(np.ones(shape=(10, 10, 4), dtype=np.float32), name="image") @fixture def peak1D(): x = np.linspace(0.0, 100.0, 101, dtype=np.float64) return NXfield(np.exp(-(x - 50)**2 / 200), name="peak") ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/tests/test_data.py0000644000077000000000000003415414777236751016153 0ustar00rosbornimport os import warnings import numpy as np import pytest from nexusformat.nexus.tree import (NXdata, NXentry, NXfield, NXroot, NXsubentry, NXvirtualfield, nxconsolidate, nxload) @pytest.fixture def data(x, y, z, v): """ Returns a simple NXdata object with a title. """ return NXdata(v, (z, y, x), title="Title") @pytest.fixture def data2(v): """ Returns a different, simple NXdata object with a title. """ v2 = v[0] v2.resize((1, 5, 10)) return NXdata(v2) @pytest.fixture def empty_data(): """ Returns a default NXdata instance. """ return NXdata() @pytest.fixture def NXdata_from_empty_01(empty_data, x, y, z, v): empty_data.nxsignal = v empty_data.nxaxes = (z, y, x) return empty_data @pytest.fixture def NXdata_from_empty_02(empty_data, x, y, z, v): empty_data["v"] = v empty_data["x"] = x empty_data["y"] = y empty_data["z"] = z empty_data.nxsignal = "v" empty_data.nxaxes = ("z", "y", "x") return empty_data def test_data_creation(data): assert "signal" in data.attrs assert "axes" in data.attrs assert len(data.attrs["axes"]) == 3 assert data.ndim == 3 assert data.shape == (2, 5, 10) assert data.nxsignal.nxname == "v" assert data.nxsignal.ndim == 3 assert data.nxsignal.shape == (2, 5, 10) assert data.nxsignal.any() assert not data.nxsignal.all() assert [axis.nxname for axis in data.nxaxes] == ["z", "y", "x"] assert [axis.ndim for axis in data.nxaxes] == [1, 1, 1] assert [axis.shape for axis in data.nxaxes] == [(3,), (6,), (11,)] assert data.nxtitle == "Title" def test_default_data(data): root = NXroot(NXentry(data)) root["entry/data"].set_default() assert root.get_default() is root["entry/data"] assert root["entry"].get_default() is root["entry/data"] assert root["entry/data"].get_default() is root["entry/data"] assert root.plottable_data is root["entry/data"] root["entry/subentry"] = NXsubentry(data) root["entry/subentry/data"].set_default() assert root.get_default() is root["entry/data"] assert root["entry/subentry"].get_default() is root["entry/subentry/data"] assert root["entry/subentry"].plottable_data is root["entry/subentry/data"] root["entry/subentry/data"].set_default(over=True) assert root.get_default() is root["entry/subentry/data"] assert root["entry"].get_default() is root["entry/subentry/data"] assert root["entry/data"].get_default() is root["entry/data"] assert root.plottable_data is root["entry/subentry/data"] def test_plottable_data_01(data): assert data.is_plottable() assert data.plottable_data is data assert data.plot_rank == 3 assert data.plot_rank == data.nxsignal.ndim assert data.plot_axes == data.nxaxes assert data.nxsignal.valid_axes(data.nxaxes) def test_plottable_data_02(data2): assert data2.shape == (1, 5, 10) assert data2.plot_shape == (5, 10) assert data2.plot_rank == 2 assert data2.plot_rank == data2.nxsignal.ndim - 1 @pytest.mark.parametrize( "data_fixture_name", ['NXdata_from_empty_01', 'NXdata_from_empty_02'] ) def test_signal_selection(data_fixture_name, z, v, request): data = request.getfixturevalue(data_fixture_name) assert data.nxsignal.nxname == "v" assert [axis.nxname for axis in data.nxaxes] == ["z", "y", "x"] assert np.array_equal(data.nxsignal, v) assert np.array_equal(data.nxaxes[0], z) def test_rename(NXdata_from_empty_01): data = NXdata_from_empty_01 data["x"].rename("xx") data["y"].rename("yy") data["z"].rename("zz") data["v"].rename("vv") assert data.nxsignal.nxname == "vv" assert [axis.nxname for axis in data.nxaxes] == ["zz", "yy", "xx"] def test_size_one_axis(x, z): y1 = np.array((1), dtype=np.float64) v1 = NXfield(np.linspace(0, 10*1*2, num=10*1*2, dtype=np.int64), name="v") v1.resize((2, 1, 10)) data = NXdata(v1, (z, y1, x)) assert data.is_plottable() assert data.plottable_data is data assert data.plot_rank == 2 assert data.plot_rank == data.nxsignal.ndim - 1 assert len(data.plot_axes) == 2 assert data.plot_shape == (2, 10) assert data.nxsignal.valid_axes(data.plot_axes) def test_data_operations(data, v): new_data = data + 1 assert np.array_equal(new_data.nxsignal.nxvalue, v + 1) assert new_data.nxaxes == data.nxaxes assert new_data.nxsignal.nxname == "v" assert [axis.nxname for axis in data.nxaxes] == ["z", "y", "x"] new_data = data - 1 assert np.array_equal(new_data.nxsignal, v - 1) new_data = data * 2 assert np.array_equal(new_data.nxsignal, v * 2) new_data = 2 * data assert np.array_equal(new_data.nxsignal, v * 2) new_data = data / 2 assert np.array_equal(new_data.nxsignal, v / 2) new_data = 2 * data - data assert np.array_equal(new_data.nxsignal, v) def test_data_errors(): y1 = NXfield(np.linspace(1, 10, 10), name="y") v1 = NXfield(y1**2, name="v") e1 = NXfield(np.sqrt(v1)) data = NXdata(v1, (y1), errors=e1) assert data.nxerrors is not None assert data.nxerrors.nxname == "v_errors" assert np.array_equal(data.nxerrors, e1) data = NXdata(v1, (y1)) data.nxerrors = e1 new_data = 2 * data assert np.array_equal(new_data.nxerrors, 2 * e1) new_data = 2 * data - data assert np.array_equal(new_data.nxerrors, e1 * np.sqrt(5)) new_data = data - data / 2 assert np.array_equal(new_data.nxerrors, e1 * np.sqrt(1.25)) def test_data_weights(): y1 = NXfield(np.linspace(1, 10, 10), name="y") v1 = NXfield(y1**2, name="v") w1 = NXfield(np.sqrt(v1)) data = NXdata(v1, (y1), errors=y1, weights=w1) assert data.nxweights is not None assert data.nxweights.nxname == "v_weights" assert np.array_equal(data.nxweights, w1) weighted_data = data.weighted_data() assert np.array_equal(weighted_data.nxsignal, v1 / w1) assert np.array_equal(weighted_data.nxerrors, y1 / w1) assert weighted_data.nxaxes == data.nxaxes data = NXdata(v1, (y1)) data.nxweights = w1 new_data = 2 * data assert np.array_equal(new_data.nxweights, 2 * w1) new_data = 2 * data - data assert np.array_equal(new_data.nxweights, w1) new_data = data - data / 2 assert np.array_equal(new_data.nxweights, w1/2) def test_data_angles(data): data.nxangles = [120, 90, 90] assert data.nxangles == [120.0, 90.0, 90.0] def test_data_slabs(data, x, y, v): slab = data[0, :, :] assert np.array_equal(slab.nxsignal, v[0]) assert slab.plot_rank == 2 assert slab.plot_shape == v[0].shape assert slab.nxaxes == [y, x] slab = data[0, 3.:12., 2.:18.] assert slab.plot_shape == (v.shape[1]-2, v.shape[2]-2) assert slab.plot_axes == [y[1:-1], x[1:-1]] slab = data[0, 3.5:11.5, 2.5:17.5] assert slab.shape == (v.shape[1]-2, v.shape[2]-2) assert slab.plot_shape == (v.shape[1]-2, v.shape[2]-2) assert slab.plot_axes == [y[1:-1], x[1:-1]] slab1 = data[0:0, 3.5:11.5, 2.5:17.5] slab2 = data[0:1, 3.5:11.5, 2.5:17.5] assert slab1.shape == slab.shape assert slab2.shape == slab.shape def test_data_projections(x, y, z, v): d1 = NXdata(v[0], (y, x)) assert d1.nxaxes == [d1["y"], d1["x"]] p1 = d1.project((1, 0)) p2 = d1.project((0, 1), limits=((3., 9.), (4., 16.))) assert p1.nxaxes == [p1["x"], p1["y"]] assert np.array_equal(p1["x"].nxvalue, d1["x"]) assert p2.nxaxes == [p2["y"], p2["x"]] assert np.array_equal(p2["x"].nxvalue, d1["x"][4.:16.]) assert np.array_equal(p2["x"].nxvalue, d1["x"][2:9]) d2 = NXdata(v, (z, y, x)) p3 = d2.project((0, 1), ((0., 8.), (3., 9.), (4., 16.))) assert p3.nxaxes == [p3["z"], p3["y"]] assert np.array_equal(p3["y"].nxvalue, d2["y"][3.:9.]) assert np.array_equal(p3["y"].nxvalue, d2["y"][1:4]) assert p3["x"] == 10. assert p3["x"].attrs["minimum"] == 4. assert p3["x"].attrs["maximum"] == 16. assert p3["x"].attrs["summed_bins"] == 7 assert p3["v"].sum() == d2.v[:, 1:3, 2:8].sum() p4 = d2.project((0, 1), ((0., 8.), (3., 9.), (4., 16.)), summed=False) assert p4["v"].sum() == d2.v[:, 1:3, 2:8].sum() / \ p4["x"].attrs["summed_bins"] def test_data_transpose(data): signal = data.nxsignal assert data.transpose().shape == signal.shape[::-1] axes = [2, 0, 1] transposed_data = data.transpose(axes) assert transposed_data.shape == signal.transpose(axes).shape assert ([axis.nxname for axis in transposed_data.nxaxes] == [data.nxaxes[i].nxname for i in axes]) def test_data_smoothing(x): warnings.filterwarnings("ignore", message="numpy.ufunc size changed") data = NXdata(np.sin(x), (x)) smooth_data = data.smooth(n=101, xmin=x.min(), xmax=x.max()) assert smooth_data.nxsignal.shape == (101,) assert smooth_data.nxaxes[0].shape == (101,) assert smooth_data.nxsignal[0] == pytest.approx(np.sin(x)[0]) assert smooth_data.nxsignal[-1] == pytest.approx(np.sin(x)[-1]) smooth_data = data.smooth(factor=4) assert smooth_data.nxsignal.shape == (41,) assert smooth_data.nxaxes[0].shape == (41,) assert smooth_data.nxsignal[0] == pytest.approx(np.sin(x)[0]) assert smooth_data.nxsignal[4] == pytest.approx(np.sin(x)[1]) assert smooth_data.nxsignal[-1] == pytest.approx(np.sin(x)[-1]) def test_data_selection(): xx = np.linspace(0, 20.0, 21, dtype=float) yy = np.ones(shape=xx.shape, dtype=float) yy[np.where(np.remainder(xx, 4) == 0.0)] = 2.0 data = NXdata(yy, xx) selected_data = data.select(4.0) assert selected_data.shape == (6,) assert np.all(selected_data.nxsignal == 2.0) yy[(np.array((1, 3, 5, 7, 9, 11, 13, 15, 17, 19)),)] = 1.5 data = NXdata(yy, xx) selected_data = data.select(4.0, offset=1.0) assert selected_data.shape == (5,) assert np.all(selected_data.nxsignal == 1.5) selected_data = data.select(4.0, offset=1.0, symmetric=True) assert selected_data.shape == (10,) assert np.all(selected_data.nxsignal == 1.5) def test_data_moments(peak1D, arr1D): data = NXdata(peak1D, arr1D) assert data.sum() == data.nxsignal.nxvalue.sum() assert np.isclose(data.moment(1), 50.0, rtol=1e-3) assert np.isclose(data.moment(2), 100.0, rtol=1e-3) assert np.isclose(data.std(), 10.0, rtol=1e-3) assert np.isclose(data.average(), data.nxsignal.nxvalue.sum() / 101.0) def test_image_data(x, y, z, v, im): root = NXroot(NXentry(NXdata(im))) root["entry"].attrs["default"] = "data" root["entry/other_data"] = NXdata(v, (z, y, x), title="Title") assert root["entry/data/image"].is_image() assert root["entry/data"].is_image() assert root.plottable_data.is_image() assert root["entry"].plottable_data.is_image() assert not root["entry/other_data"].is_image() def test_smart_indices(x, v): ind = [1, 3, 5] assert all(x[ind].nxvalue == x.nxvalue[ind]) assert all(v[v > 50].nxvalue == v.nxvalue[v.nxvalue > 50]) assert all(v[1, 0, ind].nxvalue == v.nxvalue[1, 0, ind]) x[ind] = 0 assert x.any() and not x[ind].any() ind = np.array([[3, 7], [4, 5]]) assert np.all(x[ind].nxvalue == x.nxvalue[ind]) row = np.array([0, 1, 2]) col = np.array([2, 1, 3]) assert all(v[0][row, col].nxvalue == v[0].nxvalue[row, col]) assert np.all(v[0][row[:, np.newaxis], col].nxvalue == v[0].nxvalue[row[:, np.newaxis], col]) @pytest.mark.parametrize("path", [True, False]) def test_virtual_fields(tmpdir, path, v): s1 = NXroot(NXentry(NXdata(v))) s2 = NXroot(NXentry(NXdata(2*v))) s3 = NXroot(NXentry(NXdata(3*v))) s1.save(os.path.join(tmpdir, "s1.nxs"), "w") s2.save(os.path.join(tmpdir, "s2.nxs"), "w") s3.save(os.path.join(tmpdir, "s3.nxs"), "w") sources = [f.nxfilename for f in [s1, s2, s3]] if path: vds1 = NXvirtualfield("entry/data/v", sources, shape=v.shape, dtype=v.dtype) else: vds1 = NXvirtualfield(s1["entry/data/v"], sources) assert vds1.shape == (3,) + v.shape assert vds1.dtype == v.dtype assert vds1.sum() == 6 * v.sum() vds2 = nxconsolidate(sources, "entry/data") assert vds2.nxsignal.shape == vds1.shape assert vds2.nxsignal.dtype == v.dtype assert vds2.sum() == 6 * v.sum() NXroot(NXentry(vds2)).save(os.path.join(tmpdir, "vds.nxs"), "w") vds3 = nxload(os.path.join(tmpdir, "vds.nxs")) assert "entry/data/v" in vds3 assert vds3["entry/data/v"].shape == vds1.shape assert vds3["entry/data/v"].dtype == v.dtype assert vds3["entry/data/v"].sum() == 6 * v.sum() assert vds3.nxfile["entry/data/v"].is_virtual def test_data_signals(arr1D): x = NXfield(arr1D, dtype=np.float64, name="x") y = NXfield(2 * arr1D, dtype=np.float64, name="y") y1 = NXfield(3 * arr1D, dtype=np.float64, name="y1") y2 = NXfield(4 * arr1D, dtype=np.float64, name="y2") data = NXdata(y, [x], y1=y1, y2=y2) data.nxauxiliary_signals = ["y1", "y2"] assert data.nxauxiliary_signals == [data["y1"], data["y2"]] assert data.nxsignals == [data["y"], data["y1"], data["y2"]] data = NXdata(y, [x], y1=y1, y2=y2) data.nxauxiliary_signals = [data["y1"], data["y2"]] assert data.nxauxiliary_signals == [data["y1"], data["y2"]] assert data.nxsignals == [data["y"], data["y1"], data["y2"]] def test_data_indices(arr2D): v = NXfield(arr2D, dtype=np.float64, name="v") x = NXfield(arr2D[1], dtype=np.float64, name="x") y = NXfield(arr2D[0], dtype=np.float64, name="y") z = NXfield(arr2D, dtype=np.float64, name="z") data = NXdata(v, (y, x), z=z) data.nxindices = {"x": 0, "z": [0, 1]} assert data.nxindices == {"x": 0, "z": [0, 1]} def test_data_coordinates(arr1D): x = NXfield(arr1D, dtype=np.float64, name="x") y = NXfield(arr1D, dtype=np.float64, name="y") z = NXfield(arr1D, dtype=np.float64, name="z") data = NXdata(z, x=x, y=y) data.nxcoordinates = ["y", "x"] assert data.nxcoordinates == [data["y"], data["x"]] data = NXdata(z, x=x, y=y) data.nxcoordinates = [data["y"], data["x"]] assert data.nxcoordinates == [data["y"], data["x"]] ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649549.0 nexusformat-2.0.0/tests/test_entry_groups.py0000644000077000000000000000260114777236515017770 0ustar00rosbornimport numpy as np import pytest from nexusformat.nexus.tree import NXdata, NXentry, NXsample @pytest.fixture def entry_1(x, y, z, v): """Simple entry.""" entry = NXentry(NXdata(2*v, (z, y, x), name='d1'), NXsample(name='s1')) entry.attrs['default'] = 'd1' return entry @pytest.fixture def entry_2(x, y, z, v): """Simple entry, but different to entry_1""" return NXentry(NXdata(v, (z, y, x), name='d1')) @pytest.fixture def entry_3(entry_1, entry_2): """Simple linear combination of entries.""" return entry_1 + entry_2 @pytest.fixture def entry_4(entry_1, entry_2): """Second simple linear combination of entries""" return entry_1 - entry_2 def test_entry_operation_values(entry_3, entry_4, v): assert np.array_equal(entry_3.d1.nxsignal.nxvalue, 3*v) assert np.array_equal(entry_4.d1.nxsignal.nxvalue, v) @pytest.mark.parametrize( "entry", ['entry_3', 'entry_4'] ) def test_entry_operations(entry, entry_1, request): entry = request.getfixturevalue(entry) assert 'd1' in entry assert 's1' in entry assert entry.attrs['default'] == 'd1' assert entry.d1.nxaxes == entry_1.d1.nxaxes assert entry.d1.nxsignal.nxname == "v" assert [axis.nxname for axis in entry.d1.nxaxes] == ["z", "y", "x"] def test_plottable_data(entry_2): assert entry_2.is_plottable() assert entry_2.plottable_data is entry_2['d1'] ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649705.0 nexusformat-2.0.0/tests/test_fields.py0000644000077000000000000001107014777236751016500 0ustar00rosbornimport sys import h5py as h5 import numpy as np import pytest from nexusformat.nexus.tree import NXfield, nxgetconfig @pytest.fixture def string_dtype(): return h5.special_dtype(vlen=str) @pytest.fixture def field(): return NXfield(shape=(10, 5, 5), dtype=np.int16, maxshape=(20, 10, 10), fillvalue=0) @pytest.mark.parametrize("text", ["a", "abc", "αβγ"]) def test_string_field_creation(text, string_dtype): field = NXfield(text) assert field.nxvalue == text assert field.dtype == string_dtype assert field.is_string() assert len(field) == len(text) @pytest.mark.parametrize("text", ["a", "abc", "αβγ"]) def test_byte_field_creation(text, string_dtype): field = NXfield(text, dtype='S') assert field.nxvalue == text assert field.nxdata.decode(nxgetconfig('encoding')) == text assert field.dtype != string_dtype assert field.is_string() assert len(field) == len(text) @pytest.mark.parametrize( "arr", ["arr1D", "arr2D", "arr3D"]) def test_array_field_creation(arr, request): arr = request.getfixturevalue(arr) field = NXfield(arr) assert np.all(field.nxvalue == arr) assert np.all(field.nxdata == arr) assert field.shape == arr.shape assert field.dtype == arr.dtype assert field.size == arr.size assert field.is_numeric() assert len(field) == len(arr) assert field.reshape((field.size)) == NXfield(arr.reshape((arr.size))) @pytest.mark.parametrize( "arr", ["arr1D", "arr2D", "arr3D"]) def test_binary_field_operations(arr, request): arr = request.getfixturevalue(arr) field = NXfield(arr) assert np.all((field+2).nxvalue == arr+2) assert np.all((field-2).nxvalue == arr-2) assert np.all((2*field).nxvalue == 2*arr) @pytest.mark.parametrize( "arr", ["arr1D", "arr2D", "arr3D"]) def test_field_methods(arr, request): arr = request.getfixturevalue(arr) field = NXfield(arr) assert np.array_equal(field**2, arr**2) assert field.min() == np.min(arr) assert field.max() == np.max(arr) assert field.sum() == np.sum(arr) assert field.sum(dtype=np.float32) == np.sum(arr, dtype=np.float32) assert field.average() == np.average(arr) assert field.min(keepdims=True) == np.min(arr, keepdims=True) assert field.max(keepdims=True) == np.max(arr, keepdims=True) assert field.average(keepdims=True) == np.average(arr, keepdims=True) @pytest.mark.parametrize( "arr,idx", [("arr1D", np.s_[2:5]), ("arr2D", np.s_[2:5, 2:5]), ("arr3D", np.s_[2:5, 2:5, 2:5])]) def test_field_slice(arr, idx, request): arr = request.getfixturevalue(arr) field = NXfield(arr) assert np.array_equal(field[idx].nxvalue, arr[idx]) assert field[idx].shape == arr[idx].shape def test_field_index(arr1D): field = NXfield(2*arr1D) assert field.index(10.) == 5 assert field.index(11.) == 5 assert field.index(11., max=True) == 6 assert field.index(12., max=True) == 6 field = NXfield(2*arr1D[::-1]) assert field.index(10.) == 95 assert field.index(11.) == 94 assert field.index(11., max=True) == 95 assert field.index(12., max=True) == 94 def test_field_resize(field): field[9] = 1 assert field.shape == (10, 5, 5) assert field.sum() == 25 field.resize((15, 5, 5)) field[14] = 1 assert field.shape == (15, 5, 5) assert field.sum() == 50 field.resize((15, 5, 10)) field[:, :, 9] = 1 assert field.shape == (15, 5, 10) assert field[:, :, 9].sum() == 75 def test_field_printing(arr1D): assert str(NXfield(arr1D)) == str(arr1D) assert f"{NXfield(arr1D)[10]:g}" == f"{arr1D[10]:g}" def test_field_operations(peak1D): from scipy.stats import moment assert peak1D.sum() == peak1D.nxvalue.sum() assert np.isclose(peak1D.average(), np.average(peak1D.nxvalue), rtol=1e-3) assert np.isclose(peak1D.mean(), np.mean(peak1D.nxvalue), rtol=1e-3) assert np.isclose(peak1D.var(), np.var(peak1D.nxvalue), rtol=1e-3) assert np.isclose(peak1D.std(), np.std(peak1D.nxvalue), rtol=1e-3) assert np.isclose(peak1D.moment(1), moment(peak1D.nxvalue, 1), rtol=1e-3) assert np.isclose(peak1D.moment(2), moment(peak1D.nxvalue, 2), rtol=1e-3) @pytest.mark.parametrize( "arr", ["arr1D", "arr2D", "arr3D"]) def test_numpy_conversion(arr, request): arr = request.getfixturevalue(arr) field = NXfield(arr) assert np.array_equal(field, arr) assert np.array_equal(np.array(field, dtype=np.float32), arr.astype(np.float32)) ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649549.0 nexusformat-2.0.0/tests/test_files.py0000644000077000000000000000443714777236515016343 0ustar00rosbornimport os import pytest from nexusformat.nexus.tree import (NXdata, NXentry, NXFile, NXroot, nxload, nxopen) def test_file_creation(tmpdir): filename = os.path.join(tmpdir, "file.nxs") with NXFile(filename, "w") as f: assert f.mode == "rw" assert f.filename == filename assert not f.is_open() def test_file_save(tmpdir, field1, field2): filename = os.path.join(tmpdir, "file.nxs") w1 = NXroot(NXentry()) w1.entry.data = NXdata(field1, field2) w1.save(filename) assert os.path.exists(filename) assert not w1.nxfile.is_open() assert w1.nxfilename == filename assert w1.nxfilemode == "rw" w2 = nxload(filename) assert w2.nxfilename == filename assert w2.nxfilemode == "r" assert "entry/data/f1" in w2 assert "entry/data/f2" in w2 assert "signal" in w2["entry/data"].attrs assert "axes" in w2["entry/data"].attrs @pytest.mark.parametrize("recursive", ["True", "False"]) def test_file_recursion(tmpdir, field1, field2, recursive): filename = os.path.join(tmpdir, "file.nxs") w1 = NXroot(NXentry()) w1.entry.data = NXdata(field1, field2) w1.save(filename) w2 = nxload(filename, recursive=recursive) if not recursive: assert w2["entry"]._entries is None assert "entry/data" in w2 assert w2["entry"]._entries is not None assert w2["entry/data"]._entries is None assert "entry/data/f1" in w2 assert w2["entry/data"]._entries is not None assert w2["entry/data/f2"] == field2 assert "entry/data/f1" in w2 assert "entry/data/f2" in w2 assert "signal" in w2["entry/data"].attrs assert "axes" in w2["entry/data"].attrs def test_file_context_manager(tmpdir, field1, field2): filename = os.path.join(tmpdir, "file.nxs") with nxopen(filename, "w") as w1: w1["entry"] = NXentry() w1["entry/data"] = NXdata(field1, field2) assert w1.nxfilename == filename assert w1.nxfilemode == "rw" assert os.path.exists(filename) w2 = nxopen(filename) assert w2.nxfilename == filename assert w2.nxfilemode == "r" assert "entry/data/f1" in w2 assert "entry/data/f2" in w2 assert "signal" in w2["entry/data"].attrs assert "axes" in w2["entry/data"].attrs ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1747940355.0 nexusformat-2.0.0/tests/test_groups.py0000644000077000000000000001177515013672003016537 0ustar00rosbornimport os from nexusformat.nexus.tree import NXdata, NXentry, NXgroup, NXlink, NXroot def test_group_creation(field1, field2, field3): group1 = NXgroup(name="group") assert group1 assert len(group1) == 0 assert group1.nxname == "group" assert group1.nxgroup is None group2 = NXgroup(field1) assert group2 assert len(group2) == 1 assert "f1" in group2 group1["f2"] = field2 assert "f2" in group1 group1["g2"] = group2 assert len(group1) == 2 assert "g2" in group1 assert group1["g2/f1"] is group1.g2.f1 group1["g2/f3"] = field3 assert "f3" in group1["g2"] assert "g2/f3" in group1 assert group1["g2/f3"].nxgroup == group1["g2"] group3 = NXgroup(g1=group1) assert "g1/g2/f1" in group3 assert group3["g1"].nxgroup == group3 def test_group_entries(field1, field2, field3, field4, arr1D, arr2D): entries = {"f2": field2, "f3": arr1D, "s1": "string", "g1": NXgroup(field3)} group1 = NXgroup(field1, f4=field4, f5=arr2D, entries=entries) assert "f1" in group1 assert "f2" in group1 assert "f3" in group1 assert "f4" in group1 assert "f5" in group1 assert "s1" in group1 assert "g1" in group1 assert "g1/f3" in group1 assert group1["f1"] == field1 assert group1["f2"] == field2 assert group1["f3"].nxdata.sum() == arr1D.sum() assert group1["f4"].nxdata == field4.nxdata assert group1["f5"].nxdata.sum() == arr2D.sum() assert group1["s1"].nxdata == "string" assert group1["g1/f3"] == field3 def test_group_attrs(): group1 = NXgroup(attrs={"a": "b", "c": 1}) assert "a" in group1.attrs assert "c" in group1.attrs assert group1.attrs["a"] == "b" assert group1.attrs["c"] == 1 def test_group_insertion(field2): group1 = NXgroup() group1.insert(field2, name="f1") assert "f1" in group1 assert len(group1) == 1 def test_group_rename(field1): group = NXgroup(field1) assert "f1" in group group["f1"].rename("f2") assert "f1" not in group assert "f2" in group def test_entry_creation(): group = NXentry() assert group.nxname == "entry" assert group.nxclass == "NXentry" assert isinstance(group, NXentry) def test_group_class(): group = NXgroup() group.nxclass = NXentry assert group.nxclass == "NXentry" assert isinstance(group, NXentry) def test_group_components(): g1 = NXdata(name="g1") g2 = NXdata(name="g2") g3 = NXdata(name="g3") group = NXentry(g1, g2, g3) assert group.component("NXdata") == [group["g1"], group["g2"], group["g3"]] assert group.NXdata == [group["g1"], group["g2"], group["g3"]] def test_group_title(): group = NXentry() group["title"] = "Group Title" assert group.nxtitle == "Group Title" def test_group_move(field1): group = NXentry() group["g1"] = NXgroup() group["g1/f1"] = field1 group["g2"] = NXgroup() group["g1"].move("f1", "g2", name="f2") assert "g1/f1" not in group assert "g2/f2" in group group["g2"].move(group["g2/f2"], group["g1"], name="f1") assert "g2/f2" not in group assert "g1/f1" in group group["g3"] = NXgroup() group["g2/f2"] = NXlink(target="g1/f1") group["g2"].move("f2", "g3", name="f3") assert group["g3/f3"].nxlink == field1 def test_group_copy(tmpdir, field1): filename = os.path.join(tmpdir, "file1.nxs") root = NXroot(NXentry()) root.save(filename, mode="w") external_filename = os.path.join(tmpdir, "file2.nxs") external_root = NXroot( NXentry(NXgroup(field1, name="g1", attrs={"a": "b"}))) external_root.save(external_filename, mode="w") root["entry/g2"] = NXlink(target="entry/g1", file=external_filename) copied_filename = os.path.join(tmpdir, "file3.nxs") copied_root = NXroot() copied_root.save(copied_filename, mode="w") copied_root["entry"] = root["entry"].copy(expand_external=True) assert "entry" in copied_root assert "g2" in copied_root["entry"] assert "entry/g2/f1" in copied_root assert not isinstance(copied_root["entry/g2"], NXlink) assert copied_root["entry/g2/f1"][0] == 1 assert "a" in copied_root["entry/g2"].attrs assert copied_root["entry/g2"].attrs["a"] == "b" def test_field_copy(tmpdir, field1): filename = os.path.join(tmpdir, "file1.nxs") root = NXroot(NXentry(NXgroup(name="g1"))) root.save(filename, mode="w") external_filename = os.path.join(tmpdir, "file2.nxs") external_root = NXroot(NXentry(NXgroup(field1, name="g2"))) external_root.save(external_filename, mode="w") root["entry/g1/f1"] = NXlink(target="entry/g2/f1", file=external_filename) copied_filename = os.path.join(tmpdir, "file3.nxs") copied_root = NXroot(NXentry(NXgroup(name="g3"))) copied_root.save(copied_filename, mode="w") copied_root["entry/g3/f1"] = root["entry/g1/f1"].copy() assert "entry/g3/f1" in copied_root assert not isinstance(copied_root["entry/g3/f1"], NXlink) assert copied_root["entry/g3/f1"][0] == 1 ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1748901238.0 nexusformat-2.0.0/tests/test_links.py0000644000077000000000000002131215017416566016342 0ustar00rosbornimport os import numpy as np import pytest from nexusformat.nexus.tree import (NXentry, NXfield, NXgroup, NXlink, NXroot, nxload, nxsetlock) @pytest.fixture def field1a(): return NXfield((1, 2), name="f1", dtype=np.float32, units='m') @pytest.fixture def field2a(): return NXfield((3, 4), name="f2", dtype=np.int16) def test_link_creation(field1a): root = NXroot() root["g1"] = NXgroup(f1=field1a) root["g2"] = NXgroup() root["g2"].f1_link = NXlink(root["g1/f1"]) assert "g1/f1" in root assert "g2/f1_link" in root assert root["g2/f1_link"].nxlink == root["g1/f1"] assert root["g2/f1_link"].nxtarget == "/g1/f1" root["g2/f2_link"] = NXlink(target="/g1/f1") assert root["g2/f2_link"].nxlink == root["g1/f1"] root["g2"].makelink(root["g1/f1"], name="f3_link") assert root["g2/f3_link"].nxlink == root["g1/f1"] @pytest.mark.parametrize("save", ["False", "True"]) def test_saved_links(tmpdir, field1a, save): root = NXroot() root["g1"] = NXgroup(f1=field1a) root["g2"] = NXgroup() filename = os.path.join(tmpdir, "file1.nxs") root.save(filename, mode="w") root["g2"].f1_link = NXlink(root["g1/f1"]) if save: root = nxload(filename, "rw") assert root["g2/f1_link"].shape == (2,) assert root["g2/f1_link"].dtype == np.float32 root["g1/f1"].attrs["a1"] = 1 assert "a1" in root["g2/f1_link"].attrs assert root["g2/f1_link"].a1 == 1 assert root["g2/f1_link"].nxdata[0] == root["g1/f1"].nxdata[0] @pytest.mark.parametrize("save", ["False", "True"]) def test_linkfield_properties(tmpdir, field1a, save): root = NXroot() root["g1"] = NXgroup(f1=field1a) root["g2"] = NXgroup() root["g2"].f1_link = NXlink(root["g1/f1"]) if save: filename = os.path.join(tmpdir, "file1.nxs") root.save(filename, mode="w") assert root["g2/f1_link"].shape == (2,) assert root["g2/f1_link"].dtype == np.float32 root["g1/f1"].attrs["a1"] = 1 assert "a1" in root["g2/f1_link"].attrs assert root["g2/f1_link"].a1 == 1 assert root["g2/f1_link"].nxdata[0] == root["g1/f1"].nxdata[0] @pytest.mark.parametrize("save", ["False", "True"]) def test_linkgroup_properties(tmpdir, field1a, save): root = NXroot(NXentry()) root["entry/g1"] = NXgroup() root["entry/g1/g2"] = NXgroup(field1a) root["entry/g2_link"] = NXlink("/entry/g1/g2") if save: filename = os.path.join(tmpdir, "file1.nxs") root.save(filename, mode="w") root = nxload(filename) assert "f1" in root["entry/g2_link"] assert len(root["entry/g2_link"]) == len(root["entry/g1/g2"]) assert root["entry/g2_link"].nxtarget == "/entry/g1/g2" assert root["entry/g1/g2/f1"].nxroot is root assert root["entry/g1/g2/f1"].nxgroup is root["entry/g2_link"].nxlink assert root["entry/g2_link"].nxroot is root assert root["entry/g2_link"].nxgroup is root["entry"] assert root["entry/g2_link"].nxlink.entries == root["entry/g1/g2"].entries @pytest.mark.parametrize("save", ["False", "True"]) def test_embedded_links(tmpdir, save, field1a, field2a): root = NXroot(NXentry()) root["entry/g1"] = NXgroup() root["entry/g1/g2"] = NXgroup() root["entry/g1/g2/g3"] = NXgroup(field1a) root["entry/g2_link"] = NXlink("/entry/g1/g2") if save: filename = os.path.join(tmpdir, "file1.nxs") root.save(filename, mode="w") root = nxload(filename, "rw") assert "f1" in root["entry/g2_link/g3"] assert not root["entry/g2_link"].is_linked() assert root["entry/g2_link/g3"].is_linked() assert root["entry/g2_link/g3/f1"].is_linked() assert len(root["entry/g2_link/g3"]) == len(root["entry/g1/g2/g3"]) assert root["entry/g2_link/g3/f1"].nxpath == "/entry/g2_link/g3/f1" assert root["entry/g2_link/g3/f1"].nxfilepath == "/entry/g1/g2/g3/f1" assert root["entry/g2_link/g3/f1"].nxroot is root assert root["entry/g2_link/g3/f1"].nxgroup.nxgroup is root["entry/g2_link"] root["entry/g1/g2/g3/f1"] = [7, 8] root["entry/g1/g2/g3/f1"].attrs["a"] = 1 assert root["entry/g2_link/g3/f1"][0] == 7 assert "a" in root["entry/g2_link/g3/f1"].attrs assert root["entry/g2_link/g3/f1"].attrs["a"] == 1 root["entry/g1/g2/g3/f2"] = field2a assert "f2" in root["entry/g2_link/g3"] del root["entry/g1/g2/g3/f2"] assert "f2" not in root["entry/g2_link/g3"] @pytest.mark.parametrize("save", ["False", "True"]) def test_external_field_links(tmpdir, field1a, save): root = NXroot(NXentry()) if save: filename = os.path.join(tmpdir, "file1.nxs") root.save(filename, mode="w") external_filename = os.path.join(tmpdir, "file2.nxs") external_root = NXroot(NXentry(field1a)) external_root.save(external_filename, mode="w") root["entry/f1_link"] = NXlink(target="/entry/f1", file=external_filename) assert root["entry/f1_link"].nxtarget == "/entry/f1" assert root["entry/f1_link"].nxfilepath == "/entry/f1" assert root["entry/f1_link"].nxfilename == external_filename assert root["entry/f1_link"].nxfilemode == "r" assert root["entry/f1_link"].nxroot == root assert root["entry/f1_link"].nxgroup == root["entry"] assert root["entry/f1_link"].file_exists() assert root["entry/f1_link"].path_exists() assert root["entry/f1_link"].shape == external_root["entry/f1"].shape assert root["entry/f1_link"][0] == external_root["entry/f1"][0] assert "units" in root["entry/f1_link"].attrs @pytest.mark.parametrize("save", ["False", "True"]) def test_external_group_links(tmpdir, field1a, save): root = NXroot(NXentry()) if save: filename = os.path.join(tmpdir, "file1.nxs") root.save(filename, mode="w") external_filename = os.path.join(tmpdir, "file2.nxs") external_root = NXroot( NXentry(NXgroup(field1a, name='g1', attrs={"a": "b"}))) external_root.save(external_filename, mode="w") root["entry/g1_link"] = NXlink(target="/entry/g1", file=external_filename) assert root["entry/g1_link"].nxtarget == "/entry/g1" assert root["entry/g1_link"].nxfilepath == "/entry/g1" assert root["entry/g1_link"].nxfilename == external_filename assert root["entry/g1_link"].nxfilemode == "r" assert root["entry/g1_link"].nxroot == root assert root["entry/g1_link"].nxgroup == root["entry"] assert root["entry/g1_link"].file_exists() assert root["entry/g1_link"].path_exists() assert "f1" in root["entry/g1_link"] assert root["entry/g1_link/f1"].nxfilename == ( root["entry/g1_link"].nxfilename) assert root["entry/g1_link/f1"].nxfilepath == "/entry/g1/f1" assert root["entry/g1_link/f1"].nxroot == root assert root["entry/g1_link/f1"].nxgroup is root["entry/g1_link"] assert root["entry/g1_link/f1"][0] == external_root["entry/g1/f1"][0] assert "a" in root["entry/g1_link"].attrs assert "units" in root["entry/g1_link/f1"].attrs def test_external_group_files(tmpdir, field1a): nxsetlock(10) filename = os.path.join(tmpdir, "file1.nxs") root = NXroot(NXentry()) root.save(filename, mode="w") external_filename = os.path.join(tmpdir, "file2.nxs") external_root = NXroot( NXentry(NXgroup(field1a, name='g1', attrs={"a": "b"}))) external_root.save(external_filename, mode="w") root["entry/g1_link"] = NXlink(target="/entry/g1", file=external_filename) with root.nxfile: assert root.nxfile.filename == filename assert root.nxfile.locked with root["entry/g1_link"].nxfile: assert root["entry/g1_link"].nxfile.filename == external_filename assert root["entry/g1_link"].nxfile.locked assert root.nxfile.locked assert not root["entry/g1_link"].nxfile.locked assert not root.nxfile.locked @pytest.mark.parametrize("save", ["False", "True"]) def test_soft_field_links(tmpdir, field1a, field2a, save): root = NXroot() root["g1"] = NXgroup() root["g1/g2"] = NXgroup(f1=field1a, f2=field2a) root["g1/f1_link"] = NXlink(target="g1/g2/f1", soft=True) root["g1/f2_link"] = NXlink(target="g1/g2/f2", soft=True) if save: filename = os.path.join(tmpdir, "file1.nxs") root.save(filename, mode="w") assert root["g1/f1_link"].shape == (2,) assert root["g1/f1_link"].dtype == np.float32 root["g1/g2/f1"].attrs["a1"] = 1 assert "a1" in root["g1/f1_link"].attrs assert root["g1/f1_link"].a1 == 1 assert root["g1/f1_link"].nxdata[0] == root["g1/g2/f1"].nxdata[0] assert root["g1/f2_link"].shape == (2,) assert root["g1/f2_link"].dtype == np.int16 root["g1/g2/f2"].attrs["a2"] = 2 assert "a2" in root["g1/f2_link"].attrs assert root["g1/f2_link"].a2 == 2 assert root["g1/f2_link"].nxdata[0] == root["g1/g2/f2"].nxdata[0] ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649549.0 nexusformat-2.0.0/tests/test_locks.py0000644000077000000000000001000614777236515016341 0ustar00rosbornimport os import time import pytest from nexusformat.nexus.tree import (NeXusError, NXentry, NXLock, NXroot, nxload, nxsetconfig, text) def test_lock_creation(tmpdir, field4): nxsetconfig(lock=0) filename = os.path.join(tmpdir, "file1.nxs") root = NXroot(NXentry(field4)) root.save(filename) assert root.nxfile.lock is not None root.nxfile.acquire_lock() assert not root.nxfile.locked assert not root.nxfile.is_locked() root.nxfile.release_lock() assert not root.nxfile.locked assert not root.nxfile.is_locked() root.nxfile.lock = True root.nxfile.acquire_lock() assert root.nxfile.locked assert root.nxfile.is_locked() assert root.nxfile.lock.timeout == 10 root["entry/f1"] = "b" assert root["entry/f1"] == "b" assert not root.nxfile.locked assert not root.nxfile.is_locked() def test_locked_assignments(tmpdir, field4): filename = os.path.join(tmpdir, "file1.nxs") root = NXroot(NXentry(field4)) root.save(filename) assert root.nxfile.mtime == os.path.getmtime(filename) original_id = id(root.nxfile) originalmtime = root.mtime root["entry/f1"] = "b" assert root["entry/f1"] == "b" root.nxfile.lock = 10 assert isinstance(root.nxfile.lock, NXLock) assert root.nxfile.lock.timeout == 10 time.sleep(0.1) root["entry/f1"] = "c" assert root["entry/f1"] == "c" assert id(root.nxfile) == original_id assert root.mtime > originalmtime def test_lock_interactions(tmpdir, field4): filename = os.path.join(tmpdir, "file1.nxs") root = NXroot(NXentry(field4)) root.save(filename) assert not root.nxfile.is_open() root1 = nxload(filename, mode="rw") root2 = nxload(filename, mode="r") time.sleep(0.1) root1.nxfile.lock = 10 root1["entry/f1"] = "b" assert root1.mtime > root2.mtime def test_lock_defaults(tmpdir, field4): nxsetconfig(lock=20) filename = os.path.join(tmpdir, "file1.nxs") root = NXroot(NXentry(field4)) root.save(filename, "w") with root.nxfile as f: assert isinstance(root.nxfile.lock, NXLock) assert root.nxfile.lock.timeout == 20 assert root.nxfile.locked assert root.nxfile.is_locked() assert not root.nxfile.locked assert not root.nxfile.is_locked() nxsetconfig(lock=0) root = NXroot(NXentry(field4)) root.save(filename, "w") with root.nxfile as f: assert not root.nxfile.locked assert not root.nxfile.is_locked() def test_nested_locks(tmpdir, field4): filename = os.path.join(tmpdir, "file1.nxs") root = NXroot(NXentry(field4)) root.save(filename, "w") root.nxfile.lock = True assert isinstance(root.nxfile.lock, NXLock) with root.nxfile: assert root.nxfile.locked assert root.nxfile.is_locked() root["entry/f1"] = "b" assert text(root.nxfile["entry/f1"][()]) == "b" with root.nxfile: root["entry/f1"] = "c" assert text(root.nxfile["entry/f1"][()]) == "c" assert root.nxfile.locked assert root.nxfile.is_locked() assert root.nxfile.locked assert root.nxfile.is_locked() assert not root.nxfile.locked assert not root.nxfile.is_locked() def test_stale_locks(tmpdir): nxsetconfig(lock=2, lockexpiry=3600) filename = os.path.join(tmpdir, "file1.nxs") root = NXroot(NXentry()) root.save(filename, "w") with open(root.nxfile.lock_file, 'w'): os.utime(root.nxfile.lock_file, None) assert os.path.exists(root.nxfile.lock_file) with pytest.raises(NeXusError): root.nxfile.acquire_lock() assert not root.nxfile.locked assert root.nxfile.is_locked() stat = os.stat(root.nxfile.lock_file) os.utime(root.nxfile.lock_file, (stat.st_atime, stat.st_mtime - 10000)) with root.nxfile: assert root.nxfile.locked assert root.nxfile.is_locked() assert not root.nxfile.locked assert not root.nxfile.is_locked() ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649549.0 nexusformat-2.0.0/tests/test_masks.py0000644000077000000000000000320714777236515016351 0ustar00rosbornimport os import numpy as np import pytest from nexusformat.nexus.tree import NXfield, NXgroup, NXroot, nxload def test_field_masks(arr1D): field = NXfield(arr1D) field[10:20] = np.ma.masked assert isinstance(field.nxvalue, np.ma.masked_array) assert np.all(field[8:12].mask == np.array([False, False, True, True])) assert np.all(field.mask[8:12] == np.array([False, False, True, True])) assert np.ma.is_masked(field[8:12].nxvalue) assert np.ma.is_masked(field.nxvalue[10]) assert np.ma.is_masked(field[10].nxvalue) assert field[10].mask field.mask[10] = np.ma.nomask assert np.all(field.mask[8:12] == np.array([False, False, False, True])) assert not field[10].mask @pytest.mark.parametrize("save", ["False", "True"]) def test_group_masks(tmpdir, arr1D, save): group = NXgroup(NXfield(arr1D, name='field')) group['field'][10:20] = np.ma.masked if save: root = NXroot(group) filename = os.path.join(tmpdir, "file1.nxs") root.save(filename, mode="w") root = nxload(filename, "rw") group = root['group'] assert isinstance(group['field'].nxvalue, np.ma.masked_array) assert np.all(group['field'].mask[9:11] == np.array([False, True])) assert 'mask' in group['field'].attrs assert group['field'].attrs['mask'] == 'field_mask' assert 'field_mask' in group assert group['field_mask'].dtype == bool assert group['field'].mask == group['field_mask'] group['field'].mask[10] = np.ma.nomask assert np.all(group['field'].mask[10:12] == np.array([False, True])) assert np.all(group['field_mask'][10:12] == np.array([False, True])) ././@PaxHeader0000000000000000000000000000004700000000000010216 xustar0017 gid=660979062 22 mtime=1744649549.0 nexusformat-2.0.0/tests/test_paths.py0000644000077000000000000000231014777236515016344 0ustar00rosbornfrom nexusformat.nexus.tree import NXentry, NXgroup, NXroot def test_attribute_paths(field1): root = NXroot(NXentry()) root.entry.g1 = NXgroup(field1) assert root.entry.g1.nxpath == "/entry/g1" assert root["entry/g1"] is root.entry.g1 assert root["entry/g1/f1"] is root.entry.g1.f1 assert "g1" in root.entry assert "f1" in root.entry.g1 assert "entry/g1/f1" in root assert root.entry.g1.f1.nxroot is root def test_dictionary_paths(field1): root = NXroot(NXentry()) root["entry/g1"] = NXgroup(field1) assert root.entry.g1.nxpath == "/entry/g1" assert root["entry/g1"] is root.entry.g1 assert root["entry/g1/f1"] is root.entry.g1.f1 assert "g1" in root["/entry"] assert "f1" in root["/entry/g1"] assert "/entry/g1/f1" in root assert root["/entry/g1/f1"].nxroot is root def test_relative_paths(field1): root = NXroot(NXentry()) root["entry/g1"] = NXgroup() root["entry/g1/g2"] = NXgroup() root["entry/g1/g2/f1"] = field1 assert "f1" in root["entry/g1/g2"] assert "g2/f1" in root["entry/g1"] assert "g1/g2/f1" in root["entry"] assert root["entry/g1/g2/f1"].nxpath == "/entry/g1/g2/f1" assert "entry" in root