Source code for ts_ids_components.particle_sizer.method

"""
Method components for particle sizer IDSs.

:py:class:`Method` holds the measurement conditions common to every particle
sizer technique (temperature, dispersant, particle optics, plate) alongside
two technique-specific settings blocks:

* :py:class:`DLSMethodSettings` -- Dynamic Light Scattering (also the parent
  technique for ELS and SLS, which share the same optical configuration).
* :py:class:`LaserDiffractionMethodSettings` -- Laser Diffraction.

A consuming IDS includes only the settings blocks relevant to the techniques
it supports.
"""

from enum import Enum
from typing import List

from ts_ids_core.annotations import (
    NullableNumber,
    NullableString,
    UUIDForeignKey,
    UUIDPrimaryKey,
)
from ts_ids_core.base.ids_element import IdsElement
from ts_ids_core.base.ids_field import IdsField
from ts_ids_core.schema import RawValueUnit

from ts_ids_components.particle_sizer.shared import (
    Particle,
    Plate,
    Solvent,
    Temperature,
)


[docs] class ParticleSizerTechnique(str, Enum): """ Standardized measurement technique for a particle sizer method. Each vendor reports the technique using a different raw value, which the task script should translate to one of these values rather than passing through verbatim. * :py:attr:`DYNAMIC_LIGHT_SCATTERING` -- measures Brownian-motion-driven intensity fluctuations to size sub-micron particles. * :py:attr:`ELECTROPHORETIC_LIGHT_SCATTERING` -- measures particle electrophoretic mobility to determine zeta potential. * :py:attr:`STATIC_LIGHT_SCATTERING` -- measures time-averaged scattered intensity to determine molar mass (DynaPro, simultaneous with DLS). * :py:attr:`LASER_DIFFRACTION` -- measures the angular scattering pattern of a laser to size particles from sub-micron to millimetre. """ DYNAMIC_LIGHT_SCATTERING = "dynamic light scattering" ELECTROPHORETIC_LIGHT_SCATTERING = "electrophoretic light scattering" STATIC_LIGHT_SCATTERING = "static light scattering" LASER_DIFFRACTION = "laser diffraction"
# --------------------------------------------------------------------------- # DLS method settings # ---------------------------------------------------------------------------
[docs] class InstrumentState(IdsElement): """Per-measurement DLS instrument state, one entry per acquisition.""" measurement_index: NullableNumber = IdsField( description="Zero- or one-based index of the measurement within the run." ) measurement_id: NullableString = IdsField( description="Vendor identifier for the measurement." ) laser_power: RawValueUnit = IdsField( description="Laser power used for the measurement." ) attenuation_level: RawValueUnit = IdsField( description="Attenuation level applied to the incident laser, set automatically to keep the count rate in range." ) acquisition_period: RawValueUnit = IdsField( description="Duration of a single acquisition." )
[docs] class AcquisitionQualityGate(IdsElement): """ A data quality gate/filter applied during DLS acquisition, used to accept or reject individual acquisitions before averaging. """ file_key: NullableNumber = IdsField( description="Vendor key identifying the gate in the raw file." ) label: NullableString = IdsField( description="Human-readable name of the quality gate." ) threshold: NullableString = IdsField( description="Threshold/condition applied by the gate, as reported by the instrument." ) enabled: NullableNumber = IdsField( description="Whether the gate is enabled (1) or disabled (0)." )
[docs] class SizeLimits(IdsElement): """Configured lower and upper size limits for DLS analysis.""" low: RawValueUnit = IdsField(description="Lower size limit for the analysis.") high: RawValueUnit = IdsField(description="Upper size limit for the analysis.")
[docs] class DLSMethodSettings(IdsElement): """ Dynamic Light Scattering method parameters. Also carries the optical configuration shared by the ELS and SLS techniques, which are measured on the same optical bench. """ cell_name: NullableString = IdsField( description="Name/type of the measurement cell or cuvette used." ) angle: RawValueUnit = IdsField( description="Scattering detection angle, e.g. 173 degrees for backscatter." ) wavelength: RawValueUnit = IdsField(description="Wavelength of the incident laser.") attenuator: RawValueUnit = IdsField( description="Attenuator setting applied to the incident laser." ) size_limits: SizeLimits = IdsField( description="Configured lower/upper size limits for the analysis." ) instrument_states: List[InstrumentState] = IdsField( description="Per-acquisition instrument state (laser power, attenuation, etc.)." ) acquisition_quality_gates: List[AcquisitionQualityGate] = IdsField( description="Data quality gates applied during acquisition filtering." )
# --------------------------------------------------------------------------- # Laser Diffraction method settings # ---------------------------------------------------------------------------
[docs] class ObscurationLimits(IdsElement): """Configured obscuration (light attenuation) high/low limits for a laser diffraction method.""" high_limit: RawValueUnit = IdsField(description="Upper obscuration limit.") low_limit: RawValueUnit = IdsField(description="Lower obscuration limit.")
[docs] class FeedRate(IdsElement): """Sample feed rate demand (configured) and achieved (measured) values.""" demand: RawValueUnit = IdsField(description="Configured/demanded feed rate.") achieved: RawValueUnit = IdsField(description="Actual/achieved feed rate.")
[docs] class SizeRange(IdsElement): """Configured lower and upper size range for laser diffraction analysis.""" low: RawValueUnit = IdsField(description="Lower bound of the analysis size range.") high: RawValueUnit = IdsField(description="Upper bound of the analysis size range.")
[docs] class MeasurementTime(IdsElement): """Background and sample measurement durations for a laser diffraction method.""" background: RawValueUnit = IdsField( description="Duration of the background (blank) measurement." ) sample: RawValueUnit = IdsField(description="Duration of the sample measurement.")
[docs] class DispersionUnit(IdsElement): """ Configuration of the dispersion unit (wet or dry) that suspends and delivers the sample to the laser diffraction measurement zone. """ name: NullableString = IdsField(description="Name/type of the dispersion unit.") stirrer_speed: RawValueUnit = IdsField( description="Stirrer speed of the wet dispersion unit." ) ultrasound_power: RawValueUnit = IdsField( description="Ultrasound power applied to disperse/de-agglomerate the sample." ) ultrasound_duration: RawValueUnit = IdsField( description="Duration for which ultrasound is applied." ) ultrasound_mode: NullableString = IdsField( description="Ultrasound application mode, e.g. 'continuous' or 'pre-measurement'." ) venturi_type: NullableString = IdsField( description="Venturi type for a dry dispersion unit." )
[docs] class LaserDiffractionMethodSettings(IdsElement): """Laser Diffraction method parameters (e.g. Mastersizer).""" sop_file: NullableString = IdsField( description="Name/path of the Standard Operating Procedure (SOP) file used." ) scattering_model: NullableString = IdsField( description="Scattering model used to invert the diffraction pattern, e.g. 'Mie' or 'Fraunhofer'." ) analysis_model: NullableString = IdsField( description="Analysis model applied, e.g. 'general purpose' or 'single narrow mode'." ) sensitivity: NullableString = IdsField( description="Analysis sensitivity setting, e.g. 'normal' or 'enhanced'." ) result_emulation: NullableString = IdsField( description="Result emulation setting used to reproduce results from an older instrument model." ) fine_powder_mode: NullableString = IdsField( description="Fine powder mode setting for dry dispersion of cohesive powders." ) size_range: SizeRange = IdsField( description="Configured lower/upper size range for the analysis." ) obscuration: ObscurationLimits = IdsField( description="Configured obscuration high/low limits." ) feed_rate: FeedRate = IdsField( description="Sample feed rate demand and achieved values." ) gauge_air_pressure_demand: RawValueUnit = IdsField( description="Configured gauge air pressure for a dry dispersion unit." ) hopper_gap: RawValueUnit = IdsField( description="Hopper gap setting controlling dry sample feed." ) dispersion_unit: DispersionUnit = IdsField( description="Configuration of the wet/dry dispersion unit." ) measurement_time: MeasurementTime = IdsField( description="Background and sample measurement durations." )
# --------------------------------------------------------------------------- # Top-level Method # ---------------------------------------------------------------------------
[docs] class Method(IdsElement): """ Measurement method and conditions common to every particle sizer technique. The technique-specific settings blocks are *not* included here. Following the same pattern as the :py:class:`System <ts_ids_core.schema.system.System>` and :py:class:`plate reader MeasurementSetting <ts_ids_components.plate_reader.methods.MeasurementSetting>` components, a vendor-specific IDS composes only the blocks its instrument supports by inheriting from this base plus the relevant nested mixin classes -- e.g. a DLS-only instrument uses ``class MyMethod(Method, Method.DynamicLightScattering)``, while an instrument supporting several techniques inherits from all the corresponding nested classes. """
[docs] class DynamicLightScattering(IdsElement): """ Adds the Dynamic Light Scattering method settings (which also carry the ELS/SLS optical configuration). Inherit from this to support DLS, ELS, or SLS. """ dynamic_light_scattering: DLSMethodSettings = IdsField( description="DLS-specific method parameters (also carries the ELS/SLS optical configuration)." )
[docs] class LaserDiffraction(IdsElement): """Adds the Laser Diffraction method settings. Inherit from this to support LD.""" laser_diffraction: LaserDiffractionMethodSettings = IdsField( description="Laser diffraction-specific method parameters." )
pk: UUIDPrimaryKey = IdsField( description="Primary key for this method, referenced by results via ``fk_method``." ) technique: NullableString = IdsField( description="Standardized measurement technique used.", json_schema_extra={ "example_values": [technique.value for technique in ParticleSizerTechnique] }, ) temperature: Temperature = IdsField( description="Target and actual temperature of the measurement." ) plate: Plate = IdsField( description="Plate information, for plate-reader DLS instruments." ) solvents: List[Solvent] = IdsField( description="Dispersant(s) the particles are suspended in." ) particle: Particle = IdsField( description="Optical properties of the analyte particle material." ) fk_run: UUIDForeignKey = IdsField( primary_key="/properties/runs/items/properties/pk", description="Foreign key to the run this method was used in.", )