nexusLIMS.schemas.units#
Pint unit registry and utilities for NexusLIMS metadata.
This module provides a centralized Pint unit registry for handling physical quantities with units in NexusLIMS metadata. It defines preferred units for different measurement types and provides utilities for normalizing quantities to these preferred units.
The module supports three-tiered unit serialization:
Tier 1 (Internal): Pint Quantity objects with QUDT/EMG mappings
Tier 2 (XML): Clean name/value/unit separation using XSD unit attribute
Tier 3 (Future): Optional QUDT/EMG URIs for semantic web integration
Examples:
Create and normalize quantities:
>>> from nexusLIMS.schemas.units import ureg, normalize_quantity
>>> voltage = ureg.Quantity(10000, "volt")
>>> normalized = normalize_quantity("acceleration_voltage", voltage)
>>> print(normalized)
10.0 kilovolt
Parse from strings:
>>> from nexusLIMS.schemas.units import parse_quantity
>>> voltage = parse_quantity("acceleration_voltage", "10 kV")
>>> print(voltage)
10.0 kilovolt
Serialize for XML:
>>> from nexusLIMS.schemas.units import quantity_to_xml_parts
>>> name, value, unit = quantity_to_xml_parts("acceleration_voltage", voltage)
>>> print(f"<meta name='{name}' unit='{unit}'>{value}</meta>")
<meta name='Voltage' unit='kV'>10.0</meta>
Module Contents#
Functions#
Normalize a quantity to its preferred unit for the given field. |
|
Parse a value into a Pint Quantity and normalize to preferred units. |
|
Convert a field name and quantity to XML serialization parts. |
|
Get the QUDT URI for a Pint Quantity’s unit. |
|
Serialize a Pint Quantity to a JSON-compatible dictionary. |
|
Deserialize a dictionary back to a Pint Quantity. |
Data#
API#
- nexusLIMS.schemas.units.logger#
‘getLogger(…)’
- nexusLIMS.schemas.units.ureg#
‘UnitRegistry(…)’
- nexusLIMS.schemas.units.QUDT_UNIT_TTL_PATH#
- nexusLIMS.schemas.units.QUDT_VERSION#
‘3.1.9’
- nexusLIMS.schemas.units.QUDT_UNIT#
‘Namespace(…)’
- nexusLIMS.schemas.units.PREFERRED_UNITS#
- nexusLIMS.schemas.units.normalize_quantity(field_name: str, quantity: Any) Any[source]#
Normalize a quantity to its preferred unit for the given field.
Takes a Pint Quantity and converts it to the canonical unit defined in PREFERRED_UNITS for that field. If no preferred unit is defined, returns the quantity unchanged. Non-Quantity values are passed through.
- Parameters:
field_name (str) – The metadata field name (e.g., “acceleration_voltage”, “working_distance”)
quantity (Any) –
The quantity to normalize. Can be:
Pint Quantity object (will be converted)
String (returned unchanged - use parse_quantity first)
Numeric value (returned unchanged)
None (returned unchanged)
- Returns:
The normalized quantity in preferred units, or the original value if not a Quantity or no preferred unit is defined
- Return type:
Any
Examples:
>>> voltage = ureg.Quantity(10000, "volt") >>> normalized = normalize_quantity("acceleration_voltage", voltage) >>> print(normalized) 10.0 kilovolt
>>> current = ureg.Quantity(0.1, "nanoampere") >>> normalized = normalize_quantity("beam_current", current) >>> print(normalized) 100.0 picoampere
>>> # Non-Quantity values pass through >>> normalize_quantity("unknown_field", "some string") 'some string'
>>> # Fields without preferred units return unchanged >>> qty = ureg.Quantity(5.0, "furlong") >>> normalize_quantity("custom_field", qty) == qty True
- nexusLIMS.schemas.units.parse_quantity(field_name: str, value: Any) Any[source]#
Parse a value into a Pint Quantity and normalize to preferred units.
Accepts multiple input types:
Pint Quantity: Normalized to preferred units
String: Parsed as quantity (e.g., “10 kV”, “5.2 mm”)
Numeric: Assumed to be in preferred units for field
None: Passed through unchanged
- Parameters:
field_name (str) – The metadata field name (e.g., “acceleration_voltage”)
value (Any) – The value to parse. Can be Quantity, string, numeric, or None
- Returns:
Pint Quantity in preferred units, or original value if unparseable
- Return type:
Any
Examples:
>>> qty = parse_quantity("acceleration_voltage", "10 kV") >>> print(qty) 10.0 kilovolt
>>> qty = parse_quantity("working_distance", 5.2) # Assumes mm >>> print(qty) 5.2 millimeter
>>> qty = parse_quantity("beam_current", ureg.Quantity(0.1, "nA")) >>> print(qty) 100.0 picoampere
>>> parse_quantity("operator", None) is None True
- nexusLIMS.schemas.units.quantity_to_xml_parts(field_name: str, quantity: Any) tuple[str, str, str | None][source]#
Convert a field name and quantity to XML serialization parts.
Extracts the display name, numeric value, and unit string for XML serialization. This enables clean XML output like:
<meta name="Voltage" unit="kV">10.0</meta>- Parameters:
field_name (str) – The internal field name (e.g., “acceleration_voltage”)
quantity (Any) – The quantity value (Pint Quantity, string, or numeric)
- Returns:
A 3-tuple of (display_name, value_string, unit_string)
display_name: Human-readable field name for XML
value_string: Numeric value as string
unit_string: Unit abbreviation, or None if dimensionless/non-quantity
- Return type:
Examples:
>>> qty = ureg.Quantity(10.0, "kilovolt") >>> name, value, unit = quantity_to_xml_parts("acceleration_voltage", qty) >>> print(f"<meta name='{name}' unit='{unit}'>{value}</meta>") <meta name='Voltage' unit='kV'>10.0</meta>
>>> qty = ureg.Quantity(5000, "dimensionless") >>> name, value, unit = quantity_to_xml_parts("magnification", qty) >>> print(f"<meta name='{name}'>{value}</meta>") # No unit attr <meta name='Magnification'>5000</meta>
Notes:
For non-Quantity values, the value is converted to string and unit is None. Display name mapping is handled by separate EM Glossary utilities.
- nexusLIMS.schemas.units.get_qudt_uri(quantity: Any) str | None[source]#
Get the QUDT URI for a Pint Quantity’s unit.
Returns the QUDT (Quantities, Units, Dimensions and Data Types) ontology URI for the quantity’s unit. This enables Tier 3 semantic web integration.
The mapping is loaded dynamically from the QUDT unit vocabulary file (qudt_unit.ttl) using RDFLib.
- Parameters:
quantity (Any) – A Pint Quantity object
- Returns:
QUDT URI string, or None if not a Quantity or URI not found
- Return type:
str or None
Examples:
>>> qty = ureg.Quantity(10, "kilovolt") >>> get_qudt_uri(qty) 'http://qudt.org/vocab/unit/KiloV'
>>> qty = ureg.Quantity(5.2, "millimeter") >>> get_qudt_uri(qty) 'http://qudt.org/vocab/unit/MilliM'
>>> get_qudt_uri("not a quantity") # Returns None
- nexusLIMS.schemas.units.serialize_quantity(quantity: Any) dict[str, Any][source]#
Serialize a Pint Quantity to a JSON-compatible dictionary.
Converts a Quantity to a dict with ‘value’ and ‘units’ keys. Used for internal storage or JSON export. For XML serialization, use
quantity_to_xml_parts()instead.- Parameters:
quantity (Any) – A Pint Quantity object, or other value to serialize
- Returns:
Dictionary with ‘value’ and ‘units’ keys if Quantity, or {‘value’: quantity} for non-Quantity values
- Return type:
Examples:
>>> qty = ureg.Quantity(10, "kilovolt") >>> serialize_quantity(qty) {'value': 10.0, 'units': 'kilovolt'}
>>> serialize_quantity("some string") {'value': 'some string'}
- nexusLIMS.schemas.units.deserialize_quantity(data: dict[str, Any]) Any[source]#
Deserialize a dictionary back to a Pint Quantity.
Reverses the operation of
serialize_quantity(). Takes a dict with ‘value’ and ‘units’ keys and reconstructs the Quantity.- Parameters:
data (dict[str, Any]) – Dictionary with ‘value’ and ‘units’ keys, or just ‘value’ key
- Returns:
Pint Quantity if dict has value/units, otherwise the ‘value’ field
- Return type:
Any
Examples:
>>> data = {'value': 10.0, 'units': 'kilovolt'} >>> qty = deserialize_quantity(data) >>> print(qty) 10.0 kilovolt
>>> data = {'value': 'some string'} >>> deserialize_quantity(data) 'some string'