Create susceptibility charts

In this notebook we showcase how we can compute the multipactor thresholds measured during several tests and represent it on a susceptibility chart.

Load data

[1]:
from functools import partial

from multipac_testbench import AveragedThresholdSet, TestCampaign, ThresholdSet
from multipac_testbench.data import config_path
from multipac_testbench.data.multipactor_tests import tests
from multipac_testbench.instruments import CurrentProbe, FieldProbe, ForwardPower
from multipac_testbench.util.multipactor_detectors import quantity_is_above_threshold

freqs = (120.0, 120.0, 120.0, 120.0, 120.0, 140.0, 140.0, 140.0, 140.0, 160.0, 160.0, 160.0, 160.0)
swrs = (5.0, 4.0, 3.0, 2.0, 1.0, 4.0, 3.0, 2.0, 1.0, 1.0, 2.0, 3.0, 4.0)

test_campaign =  TestCampaign.from_filepaths(
    tests,
    freqs,
    swrs,
    config_path,
    is_raw=True
)
[INFO    ] [loader.py           ] Applied trigger_policy = 'keep_all' on /home/placais/Documents/simulation/python/multipac_testbench/src/multipac_testbench/data/multipactor_tests/2025.06.20_120MHz-SWR5-6.csv
[WARNING ] [physics.py          ] 1 points were removed in R calculation, where reflected power was higher than forward power.
[INFO    ] [loader.py           ] Applied trigger_policy = 'keep_all' on /home/placais/Documents/simulation/python/multipac_testbench/src/multipac_testbench/data/multipactor_tests/2025.06.20_120MHz-SWR4-7.csv
[WARNING ] [physics.py          ] 3 points were removed in R calculation, where reflected power was higher than forward power.
[INFO    ] [loader.py           ] Applied trigger_policy = 'keep_all' on /home/placais/Documents/simulation/python/multipac_testbench/src/multipac_testbench/data/multipactor_tests/2025.06.20_120MHz-SWR3-8.csv
[WARNING ] [physics.py          ] 4 points were removed in R calculation, where reflected power was higher than forward power.
[INFO    ] [loader.py           ] Applied trigger_policy = 'keep_all' on /home/placais/Documents/simulation/python/multipac_testbench/src/multipac_testbench/data/multipactor_tests/2025.06.20_120MHz-SWR2-9.csv
[INFO    ] [loader.py           ] Applied trigger_policy = 'keep_all' on /home/placais/Documents/simulation/python/multipac_testbench/src/multipac_testbench/data/multipactor_tests/2025.06.20_120MHz-SWR1-10.csv
[INFO    ] [loader.py           ] Applied trigger_policy = 'keep_all' on /home/placais/Documents/simulation/python/multipac_testbench/src/multipac_testbench/data/multipactor_tests/2025.06.20_140MHz-SWR4-11.csv
[ERROR   ] [factory.py          ] column_header = 'NI9205_E1' not present in provided file. Skipping associated instrument.
[INFO    ] [loader.py           ] Applied trigger_policy = 'keep_all' on /home/placais/Documents/simulation/python/multipac_testbench/src/multipac_testbench/data/multipactor_tests/2025.06.20_140MHz-SWR3-12.csv
[ERROR   ] [factory.py          ] column_header = 'NI9205_E1' not present in provided file. Skipping associated instrument.
[INFO    ] [loader.py           ] Applied trigger_policy = 'keep_all' on /home/placais/Documents/simulation/python/multipac_testbench/src/multipac_testbench/data/multipactor_tests/2025.06.20_140MHz-SWR2-13.csv
[ERROR   ] [factory.py          ] column_header = 'NI9205_E1' not present in provided file. Skipping associated instrument.
[INFO    ] [loader.py           ] Applied trigger_policy = 'keep_all' on /home/placais/Documents/simulation/python/multipac_testbench/src/multipac_testbench/data/multipactor_tests/2025.06.20_140MHz-SWR1-14.csv
[ERROR   ] [factory.py          ] column_header = 'NI9205_E1' not present in provided file. Skipping associated instrument.
[INFO    ] [loader.py           ] Applied trigger_policy = 'keep_all' on /home/placais/Documents/simulation/python/multipac_testbench/src/multipac_testbench/data/multipactor_tests/2025.06.20_160MHz-SWR1-15.csv
[ERROR   ] [factory.py          ] column_header = 'NI9205_E1' not present in provided file. Skipping associated instrument.
[INFO    ] [loader.py           ] Applied trigger_policy = 'keep_all' on /home/placais/Documents/simulation/python/multipac_testbench/src/multipac_testbench/data/multipactor_tests/2025.06.20_160MHz-SWR2-16.csv
[ERROR   ] [factory.py          ] column_header = 'NI9205_E1' not present in provided file. Skipping associated instrument.
[INFO    ] [loader.py           ] Applied trigger_policy = 'keep_all' on /home/placais/Documents/simulation/python/multipac_testbench/src/multipac_testbench/data/multipactor_tests/2025.06.20_160MHz-SWR3-17.csv
[ERROR   ] [factory.py          ] column_header = 'NI9205_E1' not present in provided file. Skipping associated instrument.
[INFO    ] [loader.py           ] Applied trigger_policy = 'keep_all' on /home/placais/Documents/simulation/python/multipac_testbench/src/multipac_testbench/data/multipactor_tests/2025.06.20_160MHz-SWR4-18.csv
[WARNING ] [physics.py          ] 2 points were removed in R calculation, where reflected power was higher than forward power.
[ERROR   ] [factory.py          ] column_header = 'NI9205_E1' not present in provided file. Skipping associated instrument.
/home/placais/Documents/simulation/python/multipac_testbench/src/multipac_testbench/util/physics.py:28: RuntimeWarning: invalid value encountered in sqrt
  reflection_coefficient = np.abs(np.sqrt(reflected_power / forward_power))
/home/placais/Documents/simulation/python/multipac_testbench/src/multipac_testbench/util/physics.py:28: RuntimeWarning: invalid value encountered in sqrt
  reflection_coefficient = np.abs(np.sqrt(reflected_power / forward_power))
/home/placais/Documents/simulation/python/multipac_testbench/src/multipac_testbench/util/physics.py:28: RuntimeWarning: invalid value encountered in sqrt
  reflection_coefficient = np.abs(np.sqrt(reflected_power / forward_power))
/home/placais/Documents/simulation/python/multipac_testbench/src/multipac_testbench/util/physics.py:28: RuntimeWarning: invalid value encountered in sqrt
  reflection_coefficient = np.abs(np.sqrt(reflected_power / forward_power))
/home/placais/Documents/simulation/python/multipac_testbench/src/multipac_testbench/util/physics.py:28: RuntimeWarning: invalid value encountered in sqrt
  reflection_coefficient = np.abs(np.sqrt(reflected_power / forward_power))
/home/placais/Documents/simulation/python/multipac_testbench/src/multipac_testbench/util/physics.py:28: RuntimeWarning: invalid value encountered in sqrt
  reflection_coefficient = np.abs(np.sqrt(reflected_power / forward_power))

Determine thresholds

[2]:
current_multipactor_criterions = {'threshold': 12., 'minimum_number_of_points': 1}
current_multipac_detector = partial(quantity_is_above_threshold, **current_multipactor_criterions)

thresholds = test_campaign.determine_thresholds(
    current_multipac_detector,
    CurrentProbe,
    threshold_predicate=lambda t: t.sample_index > 300,
)

merged = test_campaign.determine_thresholds(
    current_multipac_detector,
    CurrentProbe,
    threshold_predicate=lambda t: t.sample_index > 300,
    threshold_reducer="any",
)
averaged = {test: AveragedThresholdSet.from_threshold_set(threshold_set) for test, threshold_set in merged.items()}

[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold_set.py    ] Multiple instruments detected at the same position 0.611:
- NI9205_MP4l
- NI9205_MP8l
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold_set.py    ] Multiple instruments detected at the same position 0.611:
- NI9205_MP4l
- NI9205_MP8l
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold_set.py    ] Multiple instruments detected at the same position 0.611:
- NI9205_MP4l
- NI9205_MP8l
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold_set.py    ] Multiple instruments detected at the same position 0.611:
- NI9205_MP4l
- NI9205_MP8l
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold_set.py    ] Multiple instruments detected at the same position 0.611:
- NI9205_MP4l
- NI9205_MP8l
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold_set.py    ] Multiple instruments detected at the same position 0.611:
- NI9205_MP4l
- NI9205_MP8l
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold_set.py    ] Multiple instruments detected at the same position 0.611:
- NI9205_MP4l
- NI9205_MP8l
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold_set.py    ] Multiple instruments detected at the same position 0.611:
- NI9205_MP4l
- NI9205_MP8l
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold_set.py    ] Multiple instruments detected at the same position 0.611:
- NI9205_MP4l
- NI9205_MP8l
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.
[WARNING ] [threshold.py        ] User should manually trim exceedent powers in order to avoid flat minima at the end of the test.

Represent susceptibility plot

You can use ForwardPower or FieldProbe as y-data (technically, any instrument would work).

You can color the points according to the value of the SWR at the moment of detection of multipactor, or keep classic colors associated with each instrument.

[3]:
_ = test_campaign.susceptibility_chart(merged, ForwardPower, figsize=(8, 8), xlim=(1e2, 1e3), ylim=(1e1, 1e4))
[WARNING ] [plot.py             ] Dropped 1 rows with NaN in $SWR$ column.
../../_images/manual_notebooks_plot_susceptibility_8_1.png
[4]:
axes, df = test_campaign.susceptibility_chart(thresholds, FieldProbe, figsize=(8, 8), xlim=(1e2, 1e3), ylim=(8e1, 2e3), color_according_to_swr=False)
axes.legend(loc='upper left', bbox_to_anchor=(1.05, 1.05))
[4]:
<matplotlib.legend.Legend at 0x7f02bf436710>
../../_images/manual_notebooks_plot_susceptibility_9_1.png