Immunity results and EUT assessment =================================== An immunity result contains more than a final pass/fail value. mpylab keeps the applied disturbance, EUT observations, operator interventions, retries, and assessment against the selected performance criterion separate and traceable. Primary data and interchange format ----------------------------------- The final measurement-class pickle remains the complete measurement history. It contains raw data, configuration, reference data, autosave information, and evaluation. The structured JSON export from :mod:`mpylab.env.immunity_result` is a portable subset for interchange and external tools. It replaces neither the pickle nor the modular report. The three layers are: ``EUT event`` One manual or automatic observation during an exposure phase. ``Performance criterion`` Assessment of an event sequence against criterion A, B, or C. ``Immunity document`` Optional JSON-compatible export of measurement points, disturbances, and assessments. Disturbance-neutral records --------------------------- A record must not hard-code the disturbance as an electric field. The ``disturbance`` mapping therefore uses a descriptive ``quantity_kind`` and freely named measured components: .. code-block:: python field_record = { "frequency_hz": 80e6, "disturbance": { "quantity_kind": "electric_field_strength", "target": target_field, "measured_components": {"cell_y": measured_field}, }, "eut_events": events, "assessment": assessment, } conducted_record = { "frequency_hz": 10e6, "disturbance": { "quantity_kind": "injected_current", "target": target_current, "measured_components": {"monitor": measured_current}, }, } Other useful identifiers include ``applied_voltage`` or ``bulk_current``. ``quantity_kind`` is deliberately not a closed enumeration. Applications should nevertheless use stable, explicit names so that evaluation and report tools can recognize compatible datasets. SCUQ quantities remain intact inside the measurement history. JSON export represents them through ``value``, ``uncertainty``, and ``unit``. Complex numbers are split into ``real`` and ``imag``; NumPy scalars and arrays become normal JSON values and lists. EUT event contract ------------------ The shared monitoring API lives in :mod:`mpylab.env.eut`. New applications import events, monitors, and virtual test helpers from this package. The former ``mpylab.env.eut_monitor`` and ``mpylab.env.random_eut_monitor`` modules remain available as compatibility layers for existing scripts and pickle files. :func:`mpylab.env.eut.make_eut_event` creates a validated, pickle-friendly event. Important fields are: ``status`` ``passed``, ``degraded``, ``failed``, or ``not_evaluated``. ``event_type`` ``status`` for an EUT observation or ``monitor_diagnostic`` for a failure of the monitoring system itself. ``phase`` ``pre_exposure``, ``during_exposure``, ``post_exposure``, or ``recovery``. ``functional_state`` ``normal``, ``degraded``, ``failed``, or ``not_evaluated`` during the phase being observed. ``after_exposure_state`` and ``recovery`` State after removing the disturbance and method of recovery. ``recovery`` may be ``not_required``, ``automatic``, ``operator``, ``reset``, ``failed``, or ``not_evaluated``. ``operating_mode_changed`` and ``stored_data_lost`` Optional Boolean observations relevant to assessment. ``action`` Recommendation to the measurement kernel: ``continue``, ``retry``, or ``stop``. ``safety_action`` ``none`` or ``rf_off``. The field expresses a safety requirement but does not itself issue a hardware command. ``reason``, ``details``, ``timestamp``, and ``source`` Rationale, supplementary data, timestamp, and origin of the observation. The measurement class remains responsible for RF-off and for the workflow action actually applied. A monitor does not access the ``MGraph`` directly. The task-oriented :doc:`EUT monitoring guide <../framework/eut-monitoring>` covers both existing measurement classes and development of custom monitors. Manual and automatic monitoring ------------------------------- Manual intervention is always present. ``ManualEUTMonitor`` accepts keyboard or GUI events. ``CompositeEUTMonitor`` supplements this mandatory component with any number of automatic monitors such as camera, communication, or process-data monitoring. ``EUTMonitoringSession`` provides the shared, RF-neutral lifecycle around this monitor combination. It starts and stops exposures, forwards phase changes, validates events, and separates monitor diagnostics from EUT status events. RF-off actions, retries, and measurement-flow decisions deliberately remain in the measurement kernel or worker. ``EUTMonitor.poll_event`` should not block. Wrap a monitor with a bounded blocking call in ``ThreadedEUTMonitor``. A failure of an automatic monitor is reported as ``monitor_diagnostic`` while manual fallback remains available. ``VirtualEUTMonitor`` and ``RandomEUTMonitor`` provide reproducible hardware-independent tests. Random events are test data only and do not demonstrate real EUT performance. Performance criteria A, B, and C -------------------------------- :func:`mpylab.env.eut.evaluate_performance_criterion` assesses the structured events: Criterion A No impairment is permitted during or after exposure. A diagnostic retry does not erase an impairment that was actually observed. Criterion B Temporary degradation is permitted, but temporary loss of function is not. After exposure, the state must be ``normal`` and recovery must be automatic. Criterion C Temporary loss of function is permitted. Afterwards, the state must be ``normal``; automatic recovery, operator intervention, or reset is valid. An observed operating-mode change or loss of stored data fails the current common assessment. When criterion B or C lacks the required post-exposure state or recovery information, the assessment remains ``not_evaluated`` rather than making an assumption. An earlier ``not_evaluated`` attempt may be superseded by a later fully evaluated attempt. For criterion A, a retry does not retroactively hide an impairment that was actually observed. Creating a JSON document ------------------------ .. code-block:: python from mpylab.env.immunity_result import ( build_immunity_document, write_immunity_document, ) document = build_immunity_document( application="my-immunity-application", eut_description="Example EUT", performance_criterion="A", created_at="2026-07-16T12:00:00+02:00", records=records, ) output = write_immunity_document("result.json", document) The document contains: * ``schema = "mpylab-immunity-result"`` and ``schema_version``; * ``measurement_type = "immunity"``; * application, creation time, and EUT description; * the selected performance criterion; * the application-specific ``records`` list. ``load_immunity_document`` validates the schema name, version, and presence of a record list. The concrete measurement class or evaluation must still validate domain completeness. JSON is written with ``allow_nan=False``, so non-finite numbers are not silently serialized. Reports and API --------------- The :doc:`modular TEM report ` reads EUT assessment from the complete pickle history and creates tables and summaries. It does not re-evaluate the measurement. * :doc:`../framework/ui-workers` covers manual intervention and threading of automatic monitors. * :doc:`history-files` explains the complete measurement history. * :doc:`../../api/measurement` documents the curated Python API.