diff --git a/applications/NXxas_new.nxdl.xml b/applications/NXxas_new.nxdl.xml new file mode 100644 index 0000000000..ccb72a4549 --- /dev/null +++ b/applications/NXxas_new.nxdl.xml @@ -0,0 +1,170 @@ + + + + + + + The symbol(s) listed here will be used below to coordinate datasets with the same shape. + + + Number of energy data points + + + Number of electronic transitions + + + + This is an application definition for X-ray absorption spectroscopy. + + + + Official NeXus NXDL schema to which this file conforms. TODO: replace NXxas + + + + + + + Transmission + + + Total fluorescence yield (TFY) + + + Partial fluorescence yield (PFY) + + + + Excited element + + + Absorption edge + + + Specify if the data commes from a calculation + + + TODO + + + + + + TODO + + + + + + TODO + + + + + + + Descriptive name of the sample + + + + + Description on how :ref:`energy </NXxas_new/ENTRY/energy-field>` + and :ref:`intensity </NXxas_new/ENTRY/intensity-field>` were obtained + from the raw data. + + + + + + + + + + + + + + + + + + + + + spacing between crystal planes of the reflection + + + Type or material of monochromating substance (Si, Ge, Multilayer). + + + Miller indices (hkl) values of nominal reflection + + + + + + + + + + + + + + + + + + + + + + + XAS intensity versus energy plot + + + + + + Table like data structure common in the XAS domain. + + + + + + + + + + + + + + + + + + + diff --git a/base_classes/NXedge.nxdl.xml b/base_classes/NXedge.nxdl.xml new file mode 100644 index 0000000000..6f9a752cab --- /dev/null +++ b/base_classes/NXedge.nxdl.xml @@ -0,0 +1,58 @@ + + + + + Absorption edge + + + Name of the edge + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/base_classes/NXelement.nxdl.xml b/base_classes/NXelement.nxdl.xml new file mode 100644 index 0000000000..19237a8d29 --- /dev/null +++ b/base_classes/NXelement.nxdl.xml @@ -0,0 +1,171 @@ + + + + + Definition of a chemical element. + + + For each symbol, the atomic number, common English name, and standard atomic weight are also given. + + + Z=1, name="hydrogen", standard_atomic_weight=1.0078 + Z=2, name="helium", standard_atomic_weight=4.0026 + Z=3, name="lithium", standard_atomic_weight=6.94 + Z=4, name="beryllium", standard_atomic_weight=9.0122 + Z=5, name="boron", standard_atomic_weight=10.81 + Z=6, name="carbon", standard_atomic_weight=12.011 + Z=7, name="nitrogen", standard_atomic_weight=14.007 + Z=8, name="oxygen", standard_atomic_weight=15.999 + Z=9, name="fluorine", standard_atomic_weight=18.9984 + Z=10, name="neon", standard_atomic_weight=20.1797 + Z=11, name="sodium", standard_atomic_weight=22.9898 + Z=12, name="magnesium", standard_atomic_weight=24.305 + Z=13, name="aluminum", standard_atomic_weight=26.9815 + Z=14, name="silicon", standard_atomic_weight=28.085 + Z=15, name="phosphorus", standard_atomic_weight=30.9738 + Z=16, name="sulfur", standard_atomic_weight=32.06 + Z=17, name="chlorine", standard_atomic_weight=35.453 + Z=18, name="argon", standard_atomic_weight=39.948 + Z=19, name="potassium", standard_atomic_weight=39.0983 + Z=20, name="calcium", standard_atomic_weight=40.078 + Z=21, name="scandium", standard_atomic_weight=44.9559 + Z=22, name="titanium", standard_atomic_weight=47.867 + Z=23, name="vanadium", standard_atomic_weight=50.9415 + Z=24, name="chromium", standard_atomic_weight=51.996 + Z=25, name="manganese", standard_atomic_weight=54.938 + Z=26, name="iron", standard_atomic_weight=55.845 + Z=27, name="cobalt", standard_atomic_weight=58.9332 + Z=28, name="nickel", standard_atomic_weight=58.6934 + Z=29, name="copper", standard_atomic_weight=63.546 + Z=30, name="zinc", standard_atomic_weight=65.38 + Z=31, name="gallium", standard_atomic_weight=69.72 + Z=32, name="germanium", standard_atomic_weight=72.63 + Z=33, name="arsenic", standard_atomic_weight=74.9216 + Z=34, name="selenium", standard_atomic_weight=78.971 + Z=35, name="bromine", standard_atomic_weight=79.904 + Z=36, name="krypton", standard_atomic_weight=83.798 + Z=37, name="rubidium", standard_atomic_weight=85.4678 + Z=38, name="strontium", standard_atomic_weight=87.62 + Z=39, name="yttrium", standard_atomic_weight=88.9058 + Z=40, name="zirconium", standard_atomic_weight=91.224 + Z=41, name="niobium", standard_atomic_weight=92.9064 + Z=42, name="molybdenum", standard_atomic_weight=95.95 + Z=43, name="technetium", standard_atomic_weight=97.907 + Z=44, name="ruthenium", standard_atomic_weight=101.07 + Z=45, name="rhodium", standard_atomic_weight=102.906 + Z=46, name="palladium", standard_atomic_weight=106.42 + Z=47, name="silver", standard_atomic_weight=107.868 + Z=48, name="cadmium", standard_atomic_weight=112.414 + Z=49, name="indium", standard_atomic_weight=114.818 + Z=50, name="tin", standard_atomic_weight=118.71 + Z=51, name="antimony", standard_atomic_weight=121.76 + Z=52, name="tellurium", standard_atomic_weight=127.6 + Z=53, name="iodine", standard_atomic_weight=126.905 + Z=54, name="xenon", standard_atomic_weight=131.293 + Z=55, name="cesium", standard_atomic_weight=132.905 + Z=56, name="barium", standard_atomic_weight=137.327 + Z=57, name="lanthanum", standard_atomic_weight=138.905 + Z=58, name="cerium", standard_atomic_weight=140.116 + Z=59, name="praseodymium", standard_atomic_weight=140.908 + Z=60, name="neodymium", standard_atomic_weight=144.242 + Z=61, name="promethium", standard_atomic_weight=145.0 + Z=62, name="samarium", standard_atomic_weight=150.36 + Z=63, name="europium", standard_atomic_weight=151.96 + Z=64, name="gadolinium", standard_atomic_weight=157.25 + Z=65, name="terbium", standard_atomic_weight=158.925 + Z=66, name="dysprosium", standard_atomic_weight=162.5 + Z=67, name="holmium", standard_atomic_weight=164.93 + Z=68, name="erbium", standard_atomic_weight=167.259 + Z=69, name="thulium", standard_atomic_weight=168.934 + Z=70, name="ytterbium", standard_atomic_weight=173.045 + Z=71, name="lutetium", standard_atomic_weight=174.967 + Z=72, name="hafnium", standard_atomic_weight=178.49 + Z=73, name="tantalum", standard_atomic_weight=180.948 + Z=74, name="tungsten", standard_atomic_weight=183.84 + Z=75, name="rhenium", standard_atomic_weight=186.207 + Z=76, name="osmium", standard_atomic_weight=190.23 + Z=77, name="iridium", standard_atomic_weight=192.217 + Z=78, name="platinum", standard_atomic_weight=195.084 + Z=79, name="gold", standard_atomic_weight=196.967 + Z=80, name="mercury", standard_atomic_weight=200.592 + Z=81, name="thallium", standard_atomic_weight=204.383 + Z=82, name="lead", standard_atomic_weight=207.2 + Z=83, name="bismuth", standard_atomic_weight=208.98 + Z=84, name="polonium", standard_atomic_weight=209.0 + Z=85, name="astatine", standard_atomic_weight=210.0 + Z=86, name="radon", standard_atomic_weight=222.0 + Z=87, name="francium", standard_atomic_weight=223.0 + Z=88, name="radium", standard_atomic_weight=226.0 + Z=89, name="actinium", standard_atomic_weight=227.0 + Z=90, name="thorium", standard_atomic_weight=232.038 + Z=91, name="protactinium", standard_atomic_weight=231.036 + Z=92, name="uranium", standard_atomic_weight=238.029 + Z=93, name="neptunium", standard_atomic_weight=237.048 + Z=94, name="plutonium", standard_atomic_weight=239.052 + Z=95, name="americium", standard_atomic_weight=243.0 + Z=96, name="curium", standard_atomic_weight=247.0 + Z=97, name="berkelium", standard_atomic_weight=247.0 + Z=98, name="californium", standard_atomic_weight=251.0 + Z=99, name="einsteinium", standard_atomic_weight=252 + Z=100, name="fermium", standard_atomic_weight=257 + Z=101, name="mendelevium", standard_atomic_weight=258 + Z=102, name="nobelium", standard_atomic_weight=259 + Z=103, name="lawrencium", standard_atomic_weight=266 + Z=104, name="rutherfordium", standard_atomic_weight=267 + Z=105, name="dubnium", standard_atomic_weight=268 + Z=106, name="seaborgium", standard_atomic_weight=269 + Z=107, name="bohrium", standard_atomic_weight=270 + Z=108, name="hassium", standard_atomic_weight=269 + Z=109, name="meitnerium", standard_atomic_weight=278 + Z=110, name="darmstadtium", standard_atomic_weight=281 + Z=111, name="roentgenium", standard_atomic_weight=282 + Z=112, name="copernicium", standard_atomic_weight=285 + Z=113, name="nihonium", standard_atomic_weight=286 + Z=114, name="flerovium", standard_atomic_weight=289 + Z=115, name="moscovium", standard_atomic_weight=290 + Z=116, name="livermorium", standard_atomic_weight=293 + Z=117, name="tennessine", standard_atomic_weight=294 + Z=118, name="oganesson", standard_atomic_weight=294 + + + + The charge number *Z* of the atomic nucleus. + + + + *Relative atomic mass* of the element in *amu*. It can be but is not restricted to the + *standard atomic weight* (using the natural abundance of isotopes). + + + + The charge of the atom after ionic approximation of its heteronuclear bonds. + + diff --git a/base_classes/NXemission_lines.nxdl.xml b/base_classes/NXemission_lines.nxdl.xml new file mode 100644 index 0000000000..395ecb2ed3 --- /dev/null +++ b/base_classes/NXemission_lines.nxdl.xml @@ -0,0 +1,46 @@ + + + + + Emission lines + + + The emission lines are writen using the IUPAC notation, i.e. an + initial and final edge seprated by a hyphen. + + TODO: Extend the enumeration to include all possible emission lines. + + + + + + + + + + + + + diff --git a/base_classes/NXpfy.nxdl.xml b/base_classes/NXpfy.nxdl.xml new file mode 100644 index 0000000000..ae432776da --- /dev/null +++ b/base_classes/NXpfy.nxdl.xml @@ -0,0 +1,28 @@ + + + + + Partial fluorescence yield (PFY) mode + diff --git a/base_classes/NXtfy.nxdl.xml b/base_classes/NXtfy.nxdl.xml new file mode 100644 index 0000000000..ec41a7701e --- /dev/null +++ b/base_classes/NXtfy.nxdl.xml @@ -0,0 +1,28 @@ + + + + + Total fluorescence yield (TFY) mode + diff --git a/base_classes/NXtrans.nxdl.xml b/base_classes/NXtrans.nxdl.xml new file mode 100644 index 0000000000..85ed12e25f --- /dev/null +++ b/base_classes/NXtrans.nxdl.xml @@ -0,0 +1,28 @@ + + + + + Transmission mode + diff --git a/base_classes/NXxas_mode.nxdl.xml b/base_classes/NXxas_mode.nxdl.xml new file mode 100644 index 0000000000..12d1fd63bb --- /dev/null +++ b/base_classes/NXxas_mode.nxdl.xml @@ -0,0 +1,141 @@ + + + + + XAS measurement mode + + + X-ray absorption spectroscopy (XAS) is a technique that measures the absorption coefficient :math:`\mu(E)` of a material as a function of energy. + + The name of the XAS mode indicates the type of process being monitored to obtain the spectrum. Below is a description of the available modes, with emphasis on the expected values for the `intensity` and `monitor` fields. + + 1. Transmission + + The absorption coefficient is obtained by measuring the intensity of the incident :math:`I_0` and transmitted beam :math:`I`. + + .. math:: + \mu(E) = -\ln(I/I_0) + + 2. Total fluorescence yield (TFY) + + The absorption coefficient is obtained by measuring the intensity of the emitted fluorescence :math:`I_f` and the incident beam :math:`I_0`. + + .. math:: + \mu(E) \propto I_f/I_0 + + 3. Partial fluorescence yield (PFY) + + 4. Inverse partial fluorescence yield (IPFY) + + 5. High-energy resolution fluorescence detection (HERFD) + + 6. Total electron yield (TEY) + + 7. Partial electron yield (PEY) + + 8. Electron energy loss (EELS) + + 9. X-ray Raman Scattering (XRS) + + 10. Diffraction Anomalous Fine Structure (DAFS) + + 11. X-ray Excited Optical Luminescence (XEOL) + + 12. Grazing Angle Reflection Extended X-ray Absorption Fine Structure (ReflEXAFS) + + 13. Other + + + + + Transmission + + + + + Total Fluorescence Yield + + + + + Partial Fluorescence Yield + + + + + Inverse Partial Fluorescence Yield + + + + + High Energy Resolution Fluorescence Detected + + + + + Total Electron Yield + + + + + Partial Electron Yield + + + + + Electron Energy Loss + + + + + X-ray Raman Scattering + + + + + Diffraction Anomalous Fine Structure + + + + + X-ray Excited Optical Luminescence + + + + + Grazing Angle Reflection Extended X-ray Absorption Fine Structure + + + + + Other + + + + + + + + diff --git a/dev_tools/docs/nxdl.py b/dev_tools/docs/nxdl.py index ebffd22080..e1974ecd11 100644 --- a/dev_tools/docs/nxdl.py +++ b/dev_tools/docs/nxdl.py @@ -364,7 +364,7 @@ def _get_required_or_optional_text(self, node): :returns: formatted text """ tag = node.tag.split("}")[-1] - if tag in ("field", "group"): + if tag in ("field", "group", "choice"): optional_default = not self._use_application_defaults optional = node.get("optional", optional_default) in (True, "true", "1", 1) recommended = node.get("recommended", None) in (True, "true", "1", 1) @@ -624,91 +624,144 @@ def _print_full_tree(self, ns, parent, name, indent, parent_path): :param indent: to keep track of indentation level :param parent_path: NX class path of parent nodes """ - for node in parent.xpath("nx:field", namespaces=ns): - name = node.get("name") - formatted_name = get_rst_formatted_name(node) - index_name = name - dims = self._analyze_dimensions(ns, node) - - optional_text = self._get_required_or_optional_text(node) - self._print(f"{indent}{self._hyperlink_target(parent_path, name, 'field')}") - self._print(f"{indent}.. index:: {index_name} (field)\n") - self._print( - f"{indent}{formatted_name}: " - f"{optional_text}" - f"{self._format_type(node)}" - f"{dims}" - f"{self._format_units(node)}" - f" {self.get_first_parent_ref(f'{parent_path}/{name}', 'field')}" - "\n" - ) + # Process children in document order to preserve XML ordering. + for node in parent.xpath("nx:field|nx:group|nx:choice|nx:link", namespaces=ns): + tag = node.tag.split("}")[-1] + + if tag == "field": + name = node.get("name") + formatted_name = get_rst_formatted_name(node) + index_name = name + dims = self._analyze_dimensions(ns, node) + + optional_text = self._get_required_or_optional_text(node) + self._print( + f"{indent}{self._hyperlink_target(parent_path, name, 'field')}" + ) + self._print(f"{indent}.. index:: {index_name} (field)\n") + self._print( + f"{indent}{formatted_name}: " + f"{optional_text}" + f"{self._format_type(node)}" + f"{dims}" + f"{self._format_units(node)}" + f" {self.get_first_parent_ref(f'{parent_path}/{name}', 'field')}" + "\n" + ) - self._print_if_deprecated(ns, node, indent + self._INDENTATION_UNIT) - self._print_doc_enum(indent, ns, node) + self._print_if_deprecated(ns, node, indent + self._INDENTATION_UNIT) + self._print_doc_enum(indent, ns, node) + + for subnode in node.xpath("nx:attribute", namespaces=ns): + optional = self._get_required_or_optional_text(subnode) + self._print_attribute( + ns, + "field", + subnode, + optional, + indent + self._INDENTATION_UNIT, + parent_path + "/" + name, + ) - for subnode in node.xpath("nx:attribute", namespaces=ns): - optional = self._get_required_or_optional_text(subnode) - self._print_attribute( - ns, - "field", - subnode, - optional, - indent + self._INDENTATION_UNIT, - parent_path + "/" + name, + elif tag == "group": + name = node.get("name", "") + formatted_name = get_rst_formatted_name(node) + typ = node.get("type", "untyped (this is an error; please report)") + + optional_text = self._get_required_or_optional_text(node) + if typ.startswith("NX"): + if name == "": + name = typ.lstrip("NX").upper() + typ = f":ref:`{typ}`" + hTarget = self._hyperlink_target(parent_path, name, "group") + # target = hTarget.replace(".. _", "").replace(":\n", "") + # TODO: https://github.com/nexusformat/definitions/issues/1057 + self._print(f"{indent}{hTarget}") + self._print( + f"{indent}{formatted_name}: {optional_text}{typ} " + f"{self.get_first_parent_ref(f'{parent_path}/{name}', 'group')}\n" ) - for node in parent.xpath("nx:group", namespaces=ns): - name = node.get("name", "") - formatted_name = get_rst_formatted_name(node) - typ = node.get("type", "untyped (this is an error; please report)") - - optional_text = self._get_required_or_optional_text(node) - if typ.startswith("NX"): - if name == "": - name = typ.lstrip("NX").upper() - typ = f":ref:`{typ}`" - hTarget = self._hyperlink_target(parent_path, name, "group") - # target = hTarget.replace(".. _", "").replace(":\n", "") - # TODO: https://github.com/nexusformat/definitions/issues/1057 - self._print(f"{indent}{hTarget}") - self._print( - f"{indent}{formatted_name}: {optional_text}{typ} {self.get_first_parent_ref(f'{parent_path}/{name}', 'group')}\n" - ) - - self._print_if_deprecated(ns, node, indent + self._INDENTATION_UNIT) - self._print_doc_enum(indent, ns, node) + self._print_if_deprecated(ns, node, indent + self._INDENTATION_UNIT) + self._print_doc_enum(indent, ns, node) + + for subnode in node.xpath("nx:attribute", namespaces=ns): + optional = self._get_required_or_optional_text(subnode) + self._print_attribute( + ns, + "group", + subnode, + optional, + indent + self._INDENTATION_UNIT, + parent_path + "/" + name, + ) - for subnode in node.xpath("nx:attribute", namespaces=ns): - optional = self._get_required_or_optional_text(subnode) - self._print_attribute( + nodename = "%s/%s" % (name, node.get("type")) + self._print_full_tree( ns, - "group", - subnode, - optional, + node, + nodename, indent + self._INDENTATION_UNIT, parent_path + "/" + name, ) - nodename = "%s/%s" % (name, node.get("type")) - self._print_full_tree( - ns, - node, - nodename, - indent + self._INDENTATION_UNIT, - parent_path + "/" + name, - ) + elif tag == "choice": + name = node.get("name", "") + hTarget = self._hyperlink_target(parent_path, name, "choice") + self._print(f"{indent}{hTarget}") + optional_text = self._get_required_or_optional_text(node).strip("() ") + self._print( + f"{indent}**{name}**: ({optional_text}) " + "Only one of the following groups may be present:\n" + ) + self._print_doc_enum(indent, ns, node) - for node in parent.xpath("nx:link", namespaces=ns): - name = node.get("name") - formatted_name = get_rst_formatted_name(node) - self._print(f"{indent}{self._hyperlink_target(parent_path, name, 'link')}") - self._print( - f"{indent}{formatted_name}: " - ":ref:`link` " - f"(suggested target: ``{node.get('target')}``)" - "\n" - ) - self._print_doc_enum(indent, ns, node) + # Print each group option within the choice. + for subnode in node.xpath("nx:group", namespaces=ns): + subname = subnode.get("name", "") + typ = subnode.get( + "type", "untyped (this is an error; please report)" + ) + if typ.startswith("NX"): + if subname == "": + subname = typ.lstrip("NX").upper() + typ_ref = f":ref:`{typ}`" + else: + typ_ref = typ + sub_indent = indent + self._INDENTATION_UNIT + subTarget = self._hyperlink_target( + parent_path + "/" + name, subname, "group" + ) + self._print(f"{sub_indent}{subTarget}") + self._print(f"{sub_indent}**{subname}**: {typ_ref}\n") + self._print_doc_enum(sub_indent, ns, subnode) + + # Recursively print any content within this group option. + nodename = "%s/%s" % (subname, subnode.get("type")) + self._print_full_tree( + ns, + subnode, + nodename, + sub_indent + self._INDENTATION_UNIT, + parent_path + "/" + name + "/" + subname, + ) + + elif tag == "link": + name = node.get("name") + formatted_name = get_rst_formatted_name(node) + self._print( + f"{indent}{self._hyperlink_target(parent_path, name, 'link')}" + ) + self._print( + f"{indent}{formatted_name}: " + ":ref:`link` " + f"(suggested target: ``{node.get('target')}``)" + "\n" + ) + self._print_doc_enum(indent, ns, node) + + else: + raise ValueError(f"Unknown node type: {tag}") def _print(self, *args, end="\n"): # TODO: change instances of \t to proper indentation