GTEM Virtual Workflows ====================== The modern GTEM scripts in the ``script`` directory can be run with virtual device configurations without laboratory hardware. The current implementation focuses on one-port GTEM cells. Two-port cells will be handled separately. Normative Reference ------------------- The measurement flow and evaluation are based on the newer FDIS draft of IEC 61000-4-20. For the currently implemented GTEM workflows, the most relevant sections are: .. list-table:: :header-rows: 1 * - Section - Role in the code * - Annex A.3.2.3 - One-port waveguide correlation algorithm for emission measurements. * - Annex A.3.2.3.2 - Voltage measurements in three orthogonal EUT positions. * - Annex A.3.2.3.3 - Determination of the ``e0y`` field factor. * - Annex A.3.2.4 - Correlation from radiated power to maximum open-area field strength ``Emax``. * - Annex B - TEM mode verification and immunity test-level setup. The implementation uses the measured field distribution to derive a reference field and the associated forward power for later immunity measurements. This documentation only references the standard by section number. The standard remains authoritative for formulas and evaluation parameters. Available Scripts and Configurations ------------------------------------ .. list-table:: :header-rows: 1 * - Script - Purpose - Virtual configuration * - ``tem-e0y.py`` - Experimental determination of the GTEM ``e0y`` field factor. - ``conf/tem-gtem-e0y-virtual/conf.py`` * - ``tem-emission.py`` - Emission measurement and evaluation against an existing ``e0y`` history. - ``conf/tem-gtem-emission-virtual/conf.py`` * - ``tem-emission.py`` - Emission measurement and evaluation against an existing verification reference history. The ``e0y`` source is derived from ``reference_field / sqrt(forward_power)``. - ``conf/tem-gtem-emission-virtual-from-verification/conf.py`` * - ``tem-verification.py`` - TEM mode verification with derived verification reference. The measurement stores raw field-probe and power-meter data and evaluates a reference field and forward-power table. - ``conf/tem-gtem-verification-virtual/conf.py`` * - ``tem-immunity.py`` - Immunity measurement against an existing verification reference history. The current GTEM strategy levels on forward power derived from the reference data. - ``conf/tem-gtem-immunity-virtual/conf.py`` Each text script also has a Qt starter with the same name plus ``-qt`` before the file extension, for example ``tem-immunity-qt.py``. The Qt starters use the same configuration files and run the measurement in a worker thread while the UI remains responsive. History Pickles --------------- The TEM/GTEM pickle files are history containers. A follow-up measurement normally loads the output pickle from the preceding step through ``pickle_input_filename``, adds its own raw data and evaluation, and then writes a new complete ``TEMCell`` pickle. The typical sequence for a GTEM emission measurement is: .. code-block:: text e0y -> emission The emission pickle therefore contains both the ``e0y`` calibration history and the newly added emission measurement. This is important for traceability. GTEM Geometry ------------- All GTEM measurements in one history use one fixed geometry. The script configuration defines this geometry with the cell type designation, a height series and the associated ``delta_z`` spacing. The entries in ``heights`` are cell heights ``h_i``; they define the cell geometry first and do not have to be identical to later verification heights. ``delta_z`` is the spacing between adjacent height points. The absolute z position of the first height point is not assumed. For GTEM cells, the linear model ``h = k*z`` is used. The ``height_per_z`` factor is derived from adjacent height differences, approximately ``(h[i+1] - h[i]) / delta_z``. Only after that are calculated z positions derived from ``z = h / height_per_z``. For workflows that need the analytical GTEM ``e0y`` formula, the geometry also contains ``width_per_z`` and ``gap_per_z``. The characteristic impedance defaults to 50 Ohm and normally does not need to be configured explicitly. The geometry is stored in the measurement history. Newly measured ``e0y`` data carry the geometry into ``processedData_e0y``; later emission evaluation checks that these measured ``e0y`` data match the current GTEM geometry. Older pickle files without geometry metadata are still accepted as legacy data, but they cannot provide this consistency check. Emission e0y Data ----------------- Emission evaluation can use measured ``e0y`` data from a preceding ``tem-e0y.py`` run or the analytical GTEM formula. The virtual emission configuration uses measured ``e0y`` data by default. If ``use_e0y_GTEManalytical`` is set to ``True``, the EUT position must be known through ``eut_h`` or ``eut_z`` together with ``eut_x`` and ``eut_y``. The analytical path then derives the local GTEM width, height and gap from the stored geometry instead of taking those values from a separate ``EUTpos`` dictionary. Legacy ``EUTpos`` dictionaries with explicit cell dimensions remain accepted for compatibility. e0y Source Metadata ------------------- Processed ``e0y``-like data include a ``source`` entry that describes where the field factor came from. Isolated ``tem-e0y.py`` measurements store ``method = "measured_e0y"`` and the associated GTEM geometry. If ``e0y_h`` or ``e0y_z`` together with ``e0y_y`` is configured, the source is a point source with ``source_type = "point"`` and the derived ``h``, ``z``, ``x`` and ``y`` position. Without explicit position metadata, the source remains ``source_type = "unknown"``. For point sources with geometry metadata, ``Evaluate_e0y`` also stores ``point_summary``, ``frequency_summary`` and an informational ``e0y_comparison``. This compares the measured cell-y ``e0y = abs(E_y) / sqrt(P_fwd)`` with the analytical GTEM value at the same point. If the position or geometry is missing, ``e0y_comparison_status`` records why the analytical check was skipped. Verification results that are based on a configured uniform area store ``source_type = "uniform_area"`` with ``method = "verification"``, ``uniform_area``, ``uniform_area_plane`` and ``uniform_area_points``. This is a metadata layer for traceability and for later source selection or interpolation. It does not yet make an automatic decision about which ``e0y`` source should be used for an emission evaluation. The uniform area describes the x-y area in which the field distribution is verified. It has a fixed position in the GTEM cell, typically through a height ``h`` or the equivalent z position derived from the stored geometry. This position is stored as the verification plane in ``uniform_area_plane``. The individual measurement points in that plane are stored in ``uniform_area_points``. This allows a later measurement to report which planes are available, whether the EUT position lies inside the verified area, and whether interpolation between two adjacent planes is possible. The helper method ``TEMCell.summarize_e0y_sources()`` lists the available sources from ``processedData_e0y`` and ``processedData_Verification``. Each summary includes the source family, frequency range and ``geometry_matches``. ``geometry_matches`` is ``True`` or ``False`` when both geometries are known and ``None`` when the comparison is not possible. The method is intentionally read-only; it reports available sources but does not select or interpolate between them. For data-based ``e0y`` sources, the summary also compares the requested emission frequencies with the measured source range. Frequencies inside the range can be interpolated. Frequencies below or above the measured range would require extrapolation and therefore trigger a user decision before the selected source is used. This check is intentionally not applied to the analytical GTEM ``e0y`` formula because that model is frequency-independent; higher-mode effects are outside that analytical model rather than part of a limited frequency data set. For point-like measured ``e0y`` sources the emission evaluation can also compare the stored source position with the stored EUT position. The accepted distance is ``delta_r_max = q * c0 / f_max``, where ``q`` is ``e0y_position_wavelength_factor`` and defaults to ``0.5``. Thus, at a highest requested emission frequency of 1 GHz, the default limit is approximately 0.15 m. Larger deviations trigger a user decision before the selected point source is used because the measured ``e0y`` point may no longer represent the EUT position closely enough. For verification reference sources with ``source_type = "uniform_area"``, the same source summary reports whether the stored EUT ``x``/``y`` position lies inside the verified uniform area and whether the EUT height or z position matches the verification plane. If the EUT is outside the area or on a different plane, the source is marked as requiring a user decision before it should be used. Verification reference sources can also be selected directly as ``e0y`` sources for emission evaluation. In that case, ``e0y`` is derived from the processed reference data as ``reference_field / sqrt(forward_power)``. Only frequencies where both processed values are available are considered part of the usable source range. The emission configuration parameter ``e0y_description`` must name one of the listed data-based sources explicitly. It may refer either to an isolated measured ``e0y`` data set from ``processedData_e0y`` or to a verification / reference data set from ``processedData_Verification``. Automatic source selection is intentionally not enabled yet; using ``None`` or ``"auto"`` reports the available source names and asks the user to choose one explicitly. Emission Prescreening for Quasi-Peak Remeasurements --------------------------------------------------- GTEM emission evaluation can optionally store peak-prescreening data for later remeasurement with the detector required by the selected limit. Configure an ``emission_limit`` in the ``measure_parameters`` to enable this step. If the entry is missing or ``None``, no detector prescreening is performed. A typical limit is configured through ``mpylab.limits``, for example: .. code-block:: python "emission_limit": { "module": "radiated_emission.en_55011", "group": "1", "classification": "B", "detector": "QP", "port": "AC (<= 20 kVA)", "distance": "10 m", }, "prescreen_margin_db": 6.0, "prescreen_position_count": 3, "prescan_detector": "PK", The limit curve returns electric-field limits in ``dBµV/m``. For each frequency, the evaluator derives an equivalent single-position voltage limit under the assumption that all EUT positions have equal voltages. The largest measured peak voltage is compared with this screening voltage. If it is within ``prescreen_margin_db`` below the limit or above it, the frequency is marked as a remeasurement candidate for the detector defined by the limit. This detector is often ``QP``, but can also be ``AV`` or ``PK`` depending on the selected limit. The decision is made immediately during ``Measure_Emission`` after each peak measurement and is stored in the raw-data pickle. After the peak prescan for the current EUT position is complete, marked frequencies are remeasured immediately with the detector defined by the limit before the next EUT position is selected. Results are stored below ``rawData_Emission[description]["Prescreen"]``. Important entries are ``field_limit``, ``voltage_limit``, ``measured_peak_voltage``, ``margin_db``, ``remeasure_required``, ``prescan_detector``, ``remeasure_detector``, and ``position_count_assumption``. The sorted list of candidates is also stored as ``rawData_Emission[description]["RemeasureRequiredFrequencies"]``. Measured voltages are stored below a detector layer, for example ``rawData_Emission[description]["voltage"]["PK"]`` for the fast peak prescan and later ``...["voltage"]["QP"]`` or ``...["voltage"]["AV"]`` for remeasurements. ``Evaluate_Emission`` remains responsible for the final correlation; it prefers values with the detector required by the limit and falls back to the prescan detector where no remeasurement is available yet. For the final limit comparison, configure the same limit in the ``evaluation_parameters`` as well. The evaluator then stores ``processedData_Emission[description]["LimitComparison"]`` with one entry per frequency and port. Each entry contains the calculated field strength ``Emax``, the limit, ``margin_db``, ``passed``, ``detector_required``, ``detector_used``, and ``detector_fallback``. ``detector_fallback`` is ``True`` when no remeasurement with the detector required by the limit is available yet and the prescan detector had to be used. The default output of ``OutputProcessedData_Emission`` writes these results as a tab-separated table. Important columns are ``freq_Hz``, ``Emax_value``, ``limit_value``, ``margin_dB``, ``passed``, ``detector_required``, ``detector_used``, and ``detector_fallback`` so the file can be used directly in pexplorer or spreadsheet tools. When an output filename is used, two additional tab-separated detail files are written next to the compact table. ``prescreen-...dat`` contains the inverted voltage limit, measured peak voltage, margin and remeasurement decision per frequency, port and EUT position. ``e0y-source-...dat`` records the ``e0y`` source used for the final correlation and, if available, for the prescreening step. This makes the selected analytical, measured or verification-derived ``e0y`` source traceable without opening the pickle file. For analytical ``e0y``, the EUT position must be known through ``eut_h`` or ``eut_z`` together with ``eut_x`` and ``eut_y``. When measured or verification derived ``e0y`` data are used, the same position and frequency checks as in the regular emission evaluation apply. The typical sequence for a GTEM immunity measurement is: .. code-block:: text verification -> immunity The verification reference pickle contains the TEM mode verification raw data and the processed ``reference_field`` and ``forward_power`` tables. Because the interpretation of the field-uniformity statistics is still under technical discussion, the constant-forward-power evaluation can process the primary field component in three ways: mean and standard deviation in dB, mean and standard deviation in linear V/m, and the legacy 75 % point-coverage method from the older standard. The configuration ``field_uniformity_scale = "all"`` stores all variants in ``field_uniformity_by_scale`` and ``reference_field_by_scale``; the active ``selected_field_uniformity_scale`` feeds ``reference_field`` for later leveling. This makes it possible to compare the current draft interpretation with the legacy method in one pickle. The flattened ``reference_field_comparison`` table is written by the processed-data output and contains the selected value plus the ``db``, ``linear``, and ``coverage`` alternatives for each frequency. The evaluation also stores TEM-mode dominance via the 75 % quantile of the secondary-to-primary field ratio, ``primary_field_sigma_db``, ``primary_field_sigma_linear``, and ``tem_mode_q75``. For GTEM data evaluated on the cell-y component, the evaluation additionally stores an informational analytical check in ``e0y_comparison``. For each verification point it compares the measured normalized field ``abs(E_y) / sqrt(P_fwd)`` with the analytical GTEM ``e0y`` from the configured geometry at the same x-y position and verification-plane z / h position. The check stores the measured value, the analytical value, the ratio, the relative deviation, and the deviation in dB. It is intended for inspection only and does not change the reference field, forward power, or pass/fail decision. The immunity measurement loads this pickle, uses the reference data for forward-power leveling, adds the EUT immunity data, and writes a new complete history pickle. For field-probe based verification data, the raw pickle keeps both coordinate systems. ``value`` is stored in cell-axis order after applying the active ``probe_axis_map``; ``value_probe`` keeps the original probe-axis reading. The raw data also contain ``probe_axis_maps`` and ``field_probe_values_are_cell_mapped`` so that later inspection can verify which orientation was applied. The text ``*.dat`` files are intended for quick inspection and simple frequency-based checks. The pickle remains the authoritative, structured history container. Verification Pickle Data Structure ---------------------------------- The TEM-mode verification pickle contains the complete measurement history: the active geometry, raw measurement data, processed verification results, and reference metadata for later immunity runs. Field and power values are stored as ``scuq`` ``Quantity`` objects. Important keys are: ``tem.geometry`` The active GTEM geometry of the ``TEMCell`` instance. It contains values such as ``height_per_z``, ``width_per_z``, ``gap_per_z``, and ``characteristic_impedance``. ``tem.rawData_Verification["cal"]`` Raw TEM-mode verification data for the description ``"cal"``. ``tem.rawData_Verification["cal"]["geometry"]`` The geometry stored with the raw verification measurement. ``tem.rawData_Verification["cal"]["efield"]`` The raw frequency-indexed measurement data. The structure is ``efield[freq][port][point_index] -> list[entry]``. Entries contain field probe values, forward and backward power, point metadata, and leveling metadata. ``tem.rawData_Verification["cal"]["uniform_area"]`` Name of the verification plane. ``tem.rawData_Verification["cal"]["uniform_area_plane"]`` Complete verification plane with h / z position and all verification points. ``tem.rawData_Verification["cal"]["probe_axis_maps"]`` Field-probe orientation metadata used during the measurement. ``tem.rawData_Verification["cal"]["target_efield"]`` Configured target field strength of the verification measurement when the run used constant-field-strength leveling. This value is a measurement setpoint and is not automatically identical to the processed ``reference_field``. ``tem.rawData_Verification["cal"]["target_fwd_power"]`` Configured target forward power of the verification measurement when the run used constant-forward-power leveling. ``tem.rawData_Verification["cal"]["verification_target_kind"]`` Compact, machine-readable description of the measurement target: ``"field"``, ``"forward_power"``, or ``"sg_level"``. Multiple verification runs of the same plane can therefore coexist under different descriptions in one pickle while still being filterable by target type. ``tem.rawData_Verification["cal"]["verification_target_value"]`` Target value matching ``verification_target_kind``. For field strength and forward power this is a ``Quantity`` object; for ``"sg_level"`` it is the initial signal-generator level in dBm. ``tem.rawData_Verification["cal"]["verification_target_label"]`` Human-readable short label for the target, for example ``"5 V/m"`` or ``"5 W"``. ``tem.rawData_Verification["cal"]["verification_drive_mode"]`` Drive mode used to reach the target, for example ``"constant_field_strength"``, ``"constant_forward_power"``, or ``"constant_sg_level"``. ``tem.processedData_Verification["cal"]`` Processed verification data. The compact ``verification_target_*`` metadata from the raw data are also stored here so that evaluation and source selection routines can work directly on processed data sets. ``tem.processedData_Verification["cal"]["reference_field"]`` Frequency-indexed reference field used by later leveling: ``reference_field[freq] -> Quantity(V/m)``. ``tem.processedData_Verification["cal"]["forward_power"]`` Compatibility key for the frequency-indexed forward power belonging to the reference field: ``forward_power[freq] -> Quantity(W)``. New code should prefer the more explicit ``effective_reference_forward_power`` key. ``tem.processedData_Verification["cal"]["measured_forward_power_samples"]`` Measured forward-power samples per frequency and verification point. In the ``constant_forward_power`` method these values should ideally be equal; deviations describe the practical stability of the applied forward power. ``tem.processedData_Verification["cal"]["measured_forward_power_mean"]`` Arithmetic mean of the measured forward-power samples. This mean is the implementation estimate of the single ``Pfwd`` required by the ``constant_forward_power`` method. ``tem.processedData_Verification["cal"]["measured_forward_power_sigma_db"]`` Standard deviation of the measured forward-power samples in dB. This is a diagnostic value for forward-power stability. ``tem.processedData_Verification["cal"]["effective_reference_forward_power"]`` Forward power to which ``reference_field`` actually refers. In the current ``constant_forward_power`` implementation this is the arithmetic mean of the measured forward-power samples. ``tem.processedData_Verification["cal"]["field_per_sqrt_power"]`` Frequency-indexed field factor ``reference_field / sqrt(effective_reference_forward_power)``. This is the preferred ``e0y`` source for emission evaluation from verification data. ``tem.processedData_Verification["cal"]["target_field"]`` Target field strength from the measurement configuration, if known. ``tem.processedData_Verification["cal"]["target_forward_power"]`` Forward power scaled to ``target_field``: ``effective_reference_forward_power * (target_field / reference_field)^2``. This is useful for later immunity runs when verification was performed at a setpoint such as 5 V/m, but the processed ``reference_field`` differs slightly and varies with frequency. ``tem.processedData_Verification["cal"]["reference_field_by_scale"]`` Alternative reference-field evaluations per frequency. The subkeys are ``"db"``, ``"linear"``, and ``"coverage"``. ``tem.processedData_Verification["cal"]["point_summary"]`` Point-indexed processed values: ``point_summary[point_label][freq]``. Each entry contains the point, ``primary_field``, ``secondary_fields``, ``pfwd``, and ``pbwd``. ``tem.processedData_Verification["cal"]["points"]`` Frequency-indexed point data: ``points[freq][point_label] -> list[entry]``. ``tem.processedData_Verification["cal"]["verification"]`` Complete per-frequency verification result, including field-uniformity values, TEM-mode criteria, and the reference-field comparison. ``tem.processedData_Verification["cal"]["field_uniformity_passed"]`` Field-uniformity pass/fail result per frequency. ``tem.processedData_Verification["cal"]["tem_mode_passed"]`` TEM-mode pass/fail result per frequency. ``tem.processedData_Verification["cal"]["tem_mode_in_exception_band"]`` Per-frequency marker for frequencies that fail the normal TEM-mode limit but still lie inside the normative exception band. The overall summary still checks whether the number of such frequencies stays within the allowed fraction. ``tem.processedData_Verification["cal"]["summary"]`` Overall verification summary, including ``overall_passed``, ``field_uniformity_passed``, ``tem_mode_passed``, ``tem_mode_in_exception_band_count``, and exception counts. ``tem.processedData_Verification["cal"]["e0y_comparison"]`` Informational comparison of measured and analytical ``e0y``: ``e0y_comparison[freq][point_label]``. ``tem.processedData_Verification["cal"]["e0y_comparison_summary"]`` Per-frequency summary of the e0y comparison, including ``ratio_min``, ``ratio_max``, ``ratio_mean``, and ``delta_db_mean``. ``tem.processedData_Verification["cal"]["reference_dataset"]`` Metadata for the reference dataset created from this verification. Later immunity measurements use this metadata together with ``reference_field`` and ``forward_power``. ``tem.verification_datasets["cal"]`` Metadata for the raw verification measurement. ``tem.reference_datasets["cal"]`` Metadata for the processed reference dataset used by later leveling and immunity measurements. Verification Reports -------------------- An evaluated verification pickle can be turned into a self-contained report package without connecting to hardware: .. code-block:: console python tem-verification-report.py path/to/tem-verification.p --description cal --output verification-report-cal --formats pdf html svg png The command loads the pickle with the compatibility loader and reads ``processedData_Verification[description]``. The report directory contains: ``verification-report-cal.pdf`` A multi-page PDF with summary information and plots. ``index.html`` A static HTML report that links the generated figures and tables. ``figures/*.svg`` Vector plots for reference field, forward power, field uniformity, TEM-mode criterion, TEM-mode failed-point fraction, analytical e0y comparison, and selected point maps. If the same pickle also contains evaluated ``processedData_e0y`` data, the report additionally writes ``measured-e0y-comparison`` showing the measured point e0y data sets against the analytical GTEM value. The ``tem-mode-q75`` plot shows the 75 % descriptor of ``max(E_secondary) / E_primary``. The ``tem-mode-failed-points`` plot shows the percentage of valid points where ``max(E_secondary) / E_primary > 0.5``; blue and red guide lines mark 5 % and 25 %. The point maps show the lowest frequency, the highest frequency, and the frequency with the largest ``tem_mode_q75``. PNG copies are written when ``png`` is included in ``--formats``. ``tables/*.tsv`` Machine-readable tables for summary data, reference data, exceptions, e0y comparison, measured e0y data sets, and point values. ``summary.tsv`` also contains the compact ``verification_target_*`` metadata. ``reference-data.tsv`` contains, among other fields, ``effective_reference_forward_power``, ``field_per_sqrt_power``, ``target_field``, ``target_forward_power``, ``tem_mode_failed_point_percent``, and the corresponding point counters. ``measured-e0y.tsv`` is populated when evaluated ``processedData_e0y`` entries with analytical comparison data are present in the same pickle. The PDF and HTML reports are intended for quick review and archiving. The TSV files are better suited for additional scripts, notebooks, or spreadsheet-based checks. When the command is run again with the same ``--output`` directory, files with the same generated names are overwritten. The directory is not cleaned first; remove the old report directory manually when an exact file inventory is required. The preferred API names are ``Evaluate_Verification``, ``OutputRawData_Verification``, and ``OutputProcessedData_Verification``. They describe the workflow as TEM-mode verification whose result is stored as verification reference data for later leveling steps. Hardware Template for e0y Measurements -------------------------------------- For the first real run of ``tem-e0y.py``, a template is available at ``conf/tem-gtem-e0y-template/conf.py``. It writes all outputs to its own ``output`` directory, enables ``preflight_only = True``, and initially uses one frequency only with a conservative ``initial_sg_power_dbm``. The preflight initializes the measurement graph and devices, sets the start level with RF off, executes RF-off/quit, and skips the measurement loop, evaluation, and pickle output. Before a hardware test, adapt the ``TODO`` entries in the ``*-real-template.ini`` files, the GTEM geometry, the e0y point (``e0y_h`` or ``e0y_z``, plus ``e0y_x`` and ``e0y_y``), and the field-probe list ``names["fp"]``. The additional runbook ``conf/tem-gtem-e0y-template/HARDWARE_TEST.md`` describes the preflight, the first small-scope RF-on run, and the subsequent inspection of ``processedData_e0y["e0y"]``. No ``evaluation_parameters`` block is required for this script. ``tem-e0y.py`` calls ``Evaluate_e0y(description=...)`` directly. With a processed-output filename configured, the script writes a compact processed file, a point table, and an analytical e0y comparison table. Hardware Template for Emission Measurements ------------------------------------------- For the first real run of ``tem-emission.py``, a template is available at ``conf/tem-gtem-emission-template/conf.py``. It writes all outputs to its own ``output`` directory, enables ``preflight_only = True``, and initially uses one frequency only. The preflight initializes the measurement graph and receiver, checks the configured e0y/limit setup, executes RF-off/quit, and skips the measurement loop, evaluation, and pickle output. Before a hardware test, adapt the ``TODO`` entries in ``receiver-real-template.ini``, the GTEM geometry, the EUT position, the path loss from the GTEM port to the receiver, and ``EMISSION_LIMIT``. The first preflight uses analytical GTEM ``e0y``. For traceable final results, set ``REFERENCE_PICKLE`` to an e0y or verification pickle and set ``use_e0y_GTEManalytical`` to ``None`` in both measurement and evaluation parameters. The additional runbook ``conf/tem-gtem-emission-template/HARDWARE_TEST.md`` describes the preflight, the first small-scope emission run, and the subsequent inspection of ``rawData_Emission``, ``RemeasureRequiredFrequencies``, and ``processedData_Emission[description]["LimitComparison"]``. Hardware Template for TEM-Mode Verification ------------------------------------------- For the first real run of ``tem-verification.py``, a template is available at ``conf/tem-gtem-verification-template/conf.py``. It writes all outputs to its own ``output`` directory, enables ``preflight_only = True``, and initially uses one frequency only with a conservative ``initial_sg_power_dbm``. The preflight initializes the measurement graph and devices, sets the start level with RF off, executes RF-off/quit, and skips the measurement loop, evaluation, and pickle output. Before a hardware test, adapt the ``TODO`` entries in the ``*-real-template.ini`` files, the GTEM geometry, the uniform area, and the field-probe list ``names["fp"]``. The additional runbook ``conf/tem-gtem-verification-template/HARDWARE_TEST.md`` describes the preflight, the first small-scope RF-on run, and the subsequent inspection of ``processedData_Verification["verification"]``. The field-probe orientation should be configured on the field-probe graph node. For simple signed axis permutations, use ``probe_axis_map``. For example, ``probe_axis_map="cell_x:-probe_y,cell_y:+probe_x,cell_z:+probe_z"`` means that the primary cell-y field is read from the probe-x channel. After the run, inspect one raw field-probe entry and check that ``value`` contains the mapped cell-axis vector while ``value_probe`` still contains the original probe-axis vector. For arbitrary probe rotations, use ``probe_rotation_matrix`` instead. The matrix transforms probe-axis readings into cell-axis readings: .. code-block:: text E_cell = R_cell_from_probe * E_probe For example, a 90 degree rotation around the cell/probe z-axis can be written as ``probe_rotation_matrix="0,-1,0;1,0,0;0,0,1"``. The matrix must be a proper orthonormal rotation matrix with determinant ``+1``. The older ``probe_axis_map`` syntax remains useful for exact axis swaps and sign changes; internally it is treated as a special rotation-matrix case. As a human-readable alternative, the same rotation can be configured as fixed cell-axis angles: .. code-block:: python probe_rotation_angles_deg = { "about_cell_z": 90.0, "about_cell_x": 0.0, "about_cell_y": 0.0, } The convention starts with probe and cell axes aligned. The probe is then rotated around the fixed cell z-axis, then around the fixed cell x-axis, and finally around the fixed cell y-axis. Internally these angles are converted to the same ``R_cell_from_probe`` matrix used by ``probe_rotation_matrix``. Important: in this path, ``initial_sg_power_dbm`` is the safety-relevant conservative start value. ``target_efield`` is not a safety limit in the constant-forward-power measurement path. Leveling Strategies ------------------- The implemented GTEM immunity strategy is ``forward_power_from_reference``. It derives the required forward power at the GTEM input from ``reference_field`` and ``forward_power`` in the immunity reference data, then uses :class:`mpylab.tools.mgraph.Leveler` to adjust the signal-generator level until the forward-power meter observes that target. The alternative strategy ``field_probe_monitor`` levels directly against a field probe at a monitor position. From the requested EUT field and the ``e0y`` values at the EUT and monitor positions, the code first derives the monitor-field target. The signal generator is then adjusted iteratively until the probe measures that monitor field. ``e0y_source = "analytical_geometry"`` uses the analytical GTEM geometry; ``e0y_source = "verification_reference"`` uses stored verification reference data. ``probe_axis_map`` maps simple signed probe-axis permutations to the cell axes, for example ``"cell_y": "+probe_y"``. For arbitrary rotations, ``probe_rotation_matrix`` or ``probe_rotation_angles_deg`` can be used with the same probe-to-cell convention as described above. The sign can be configured explicitly, although it is often practically irrelevant for probes that report magnitudes. For multiple monitor probes that are activated in the DOT file, for example via frequency-dependent ``condition`` attributes, the orientation must match the currently active probe. The orientation can be read from the leveling configuration, the DOT node, or the field-probe INI. Conflicting definitions are rejected so that a wrong axis orientation cannot silently affect evaluation or leveling. For real hardware tests, ``start_level`` should be set explicitly in the leveling configuration. It is the first signal-generator level used by the control loop and should be conservative. If ``start_level`` is omitted, the current generator level can be read via ``actor.GetLevel()`` as a convenience path, but that is less explicit for traceability. Before a hardware test, ``tem-immunity.py`` can be started with ``preflight_only = True`` in the configuration. In this mode, the measurement graph and devices are initialized, the leveling configuration including ``field_probe_monitor`` is validated, and RF-off/quit is executed afterwards. The actual measurement sequence, evaluation, and pickle output are skipped. For field-probe based paths, the preflight also prints the effective probe orientation source, the ``R_cell_from_probe`` matrix, and the resulting ``cell_y`` expression, for example ``cell_y = +0.707*probe_x +0.707*probe_y``. This is the quickest check that the cell-y component used for evaluation or leveling is built from the intended probe channels. The leveling results are stored in the raw immunity data, including ``leveling_strategy``, ``leveling_target_monitor_field``, ``leveling_actual_monitor_field``, ``leveling_actor_level``, and ``leveling_samples``. This keeps the actual control process traceable in the pickle. First Hardware Test with Field-Probe Monitor -------------------------------------------- For the first real run with ``field_probe_monitor``, use a staged procedure: As a starting point, a template is available at ``conf/tem-gtem-immunity-field-probe-template/conf.py``. It writes all outputs to its own ``output`` directory, enables ``preflight_only = True``, and uses conservative start values. Before a hardware test, adapt the ``TODO`` entries in the ``*-real-template.ini`` files, the GTEM geometry, the positions, and the path to the verification pickle. 1. Set ``preflight_only = True`` and start the script. The run should only initialize devices, validate the configuration, and then execute RF-off/quit. 2. Set ``preflight_only = False``, but choose an intentionally small ``start_level``. The start level should be well below the expected operating level. 3. Use a small test field for the first leveling test, for example ``field = 0.1`` or another value that is safe for the setup. 4. After the run, inspect the log and pickle. The most important entries are ``leveling_target_monitor_field``, ``leveling_actual_monitor_field``, ``leveling_actor_level``, and ``leveling_samples``. 5. Increase the test level step by step only after target and actual monitor fields look plausible. EUT Position for Immunity Measurements -------------------------------------- For ``tem-immunity.py``, the equipment-under-test position can be configured in ``measure_parameters`` with ``eut_h`` or, alternatively, with ``eut_z``. ``eut_h`` is the height in the GTEM cell and is usually the easier quantity to measure in the laboratory; ``eut_z`` is the longitudinal coordinate derived from the configured geometry. Only one of the two values may be set. Position entries ``x`` and ``y`` refer to the cell coordinate system. Here, ``y`` is the absolute height above the lower GTEM plate or bottom plane; ``y = 0.25`` therefore means 25 cm above the bottom. Before the measurement starts, the immunity routine reports the available verification planes. If an EUT position is configured, the report also contains the target position and the height difference ``delta_h`` to each plane. The selected plane is stored in the raw-data entry under ``reference_selection`` together with ``target_h``, ``target_z``, and ``delta_h``. The virtual configuration uses ``eut_h = 0.5`` as an example. If the EUT height lies between two available planes, the dialog offers an additional interpolation choice between those planes. The implementation does not linearly interpolate the final ``forward_power`` values over height. Instead, it first derives the measured field factor ``K = reference_field / sqrt(forward_power)`` for each frequency. For an ideally scaling GTEM cell, ``K*h`` is approximately height-independent; this quantity is interpolated between the adjacent planes and then converted back to the target height. The resulting field factor is used to calculate the forward power for the requested test level. Interpolation is offered only when both planes contain common ``reference_field`` and ``forward_power`` values for the requested measurement frequencies. For an interpolated selection, the pickle stores ``mode = "interpolated"``, ``lower_reference``, ``upper_reference``, and ``fraction`` in ``reference_selection``. Immunity Target Power and AM Headroom ------------------------------------- Verification references can contain ``immunity_reference`` curves generated from ``required_immunity_efields``. During ``tem-immunity.py``, ``immunity_target_efield`` selects the required immunity test field strength from those curves. Exact target levels are used directly. Intermediate target levels are interpolated over ``E**2``. Target levels above the largest verified level are rejected. For each selected frequency, the raw and processed immunity data store the selected ``immunity_reference_power_selection``. It contains two different forward-power values: ``forward_power_for_required_immunity_efield`` The forward power used for the normal immunity test field. ``forward_power_for_am_test_efield`` The forward power for the AM-headroom field ``required_immunity_efield * am_headroom_factor``. With the default ``am_headroom_factor = 1.8`` this corresponds to the 80 % AM reserve check. The optional ``headroom_check`` parameter controls whether the forward-power leveling first approaches ``forward_power_for_am_test_efield`` and then returns to ``forward_power_for_required_immunity_efield`` for the actual test. The check is disabled by default. When enabled, the resulting fields ``leveling_headroom_check_*`` are stored in the raw data and summarized in ``processedData_Immunity[description]["leveling_summary"]``. The field-probe monitor template intentionally keeps ``immunity_target_efield`` and ``headroom_check`` disabled while the first hardware bring-up uses a small live monitor field. Enable them only when the selected verification pickle contains suitable ``immunity_reference`` curves and the RF path has already been tested conservatively. Virtual GTEM Run ---------------- From the ``script`` directory, the hardware-independent workflow can be run as: .. code-block:: console python tem-e0y.py conf/tem-gtem-e0y-virtual/conf.py python tem-emission.py conf/tem-gtem-emission-virtual/conf.py Alternatively, after a virtual verification reference, emission can use the verification reference data directly as its ``e0y`` source: .. code-block:: console python tem-verification.py conf/tem-gtem-verification-virtual/conf.py python tem-emission.py conf/tem-gtem-emission-virtual-from-verification/conf.py For a virtual GTEM immunity run: .. code-block:: console python tem-verification.py conf/tem-gtem-verification-virtual/conf.py python tem-immunity.py conf/tem-gtem-immunity-virtual/conf.py The live field-probe strategy can be tested without hardware using a second virtual configuration: .. code-block:: console python tem-verification.py conf/tem-gtem-verification-virtual/conf.py python tem-immunity.py conf/tem-gtem-immunity-virtual/conf-field-probe-monitor.py The same runs can be started through the Qt UI: .. code-block:: console python tem-e0y-qt.py conf/tem-gtem-e0y-virtual/conf.py python tem-emission-qt.py conf/tem-gtem-emission-virtual/conf.py python tem-verification-qt.py conf/tem-gtem-verification-virtual/conf.py python tem-immunity-qt.py conf/tem-gtem-immunity-virtual/conf.py The Qt stop button requests the same user-interrupt path as the text UI. It is therefore suitable for development and operator testing, but it does not replace the RF-off handling in the measurement routines. The first measurement writes its pickle below ``conf/tem-gtem-e0y-virtual/output``. The virtual emission configuration uses that pickle as input and writes its own results below ``conf/tem-gtem-emission-virtual/output``. For e0y, the processed output is split into a compact file and detail tables. ``out_points_tem-e0y-virtual-gtem.dat`` contains one row per frequency and measurement point with field, e0y, forward-power, and backward-power columns. ``out_e0y-comparison_tem-e0y-virtual-gtem.dat`` contains the measured versus analytical e0y check when the e0y point and GTEM geometry are known. The alternative virtual emission-from-verification configuration uses the pickle from ``conf/tem-gtem-verification-virtual/output`` and writes its own results below ``conf/tem-gtem-emission-virtual-from-verification/output``. The virtual verification reference writes its pickle below ``conf/tem-gtem-verification-virtual/output``. The virtual immunity configuration uses that pickle as input and writes its own results below ``conf/tem-gtem-immunity-virtual/output``. The file ``out_processed_tem-verification-verification.dat`` also contains the ``reference_field_comparison`` table. For each frequency, it shows the currently selected reference-field value for leveling together with the ``db``, ``linear``, and ``coverage`` alternatives. For a quick check, search the output file for that key: .. code-block:: console grep -n "reference_field_comparison" conf/tem-gtem-verification-virtual/output/out_processed_tem-verification-verification.dat The companion file ``out_e0y-comparison_tem-verification-verification.dat`` contains the point-wise analytical ``e0y`` check with one row per frequency and verification point. It is useful for detecting geometry, position, orientation, or higher-mode effects without changing the verification result itself. The processed text output follows the deterministic order of the processed pickle keys and is useful for quick reviews. More deeply nested data such as per-point field readings are easier to inspect from the pickle, for example with ``pexplorer``. The virtual configurations use only virtual device drivers from ``mpylab.device`` and synthetic path corrections. They are suitable for development, debugging, and regression tests without laboratory hardware. Tests ----- The GTEM workflow is covered by ``test/test_tem_scripts.py``. The tests run the virtual chains ``e0y -> emission`` and ``verification -> immunity`` with temporary output files and verify that the resulting pickles preserve the previous ``TEMCell`` history. Run the tests from the repository root with: .. code-block:: console PYTHONPATH=src:../scuq/src python -m pytest test/test_tem_scripts.py