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:

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

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:

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:

"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:

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:

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:

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:

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 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:

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:

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:

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:

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:

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:

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:

PYTHONPATH=src:../scuq/src python -m pytest test/test_tem_scripts.py