Coverage for python/gsfit/database_readers/freegsnke/setup_pressure_sensors.py: 32%
34 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-14 15:25 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-14 15:25 +0000
1import typing
2from typing import TYPE_CHECKING
4import numpy as np
5import numpy.typing as npt
6from freegsnke.equilibrium_update import Equilibrium as FreeGsnkeEquilibrium
7from gsfit_rs import Pressure
9if TYPE_CHECKING:
10 from . import DatabaseReader
13def setup_pressure_sensors(
14 self: "DatabaseReader",
15 pulseNo: int,
16 settings: dict[str, typing.Any],
17 time: npt.NDArray[np.float64],
18 freegsnke_eqs: list[FreeGsnkeEquilibrium],
19) -> Pressure:
20 """
21 This method initialises the Rust `Pressure` class using synthetic pressure sensors,
22 generated from the FreeGSNKE "truth" equilibrium.
24 :param pulseNo: Pulse number, used to read from the database
25 :param settings: Dictionary containing the JSON settings read from the `settings` directory
26 :param time: Measured time vector
27 :param freegsnke_eqs: List of FreeGSNKE equilibrium objects, one for each time-slice
29 The pressure sensors are only added when `sensor_weights_pressure.json["include"]` is `True`.
30 Synthetic sensors are placed along the outboard midplane (at the magnetic axis height),
31 from `synthetic.r_start` to `synthetic.r_end` [metre], measured relative to the magnetic axis
32 radius. The measured pressure at each sensor is read directly from the FreeGSNKE equilibrium's
33 `pressure(psi_n)` profile, so it is a "perfect" synthetic measurement (no noise added).
34 Sensors landing outside the last closed flux surface, where the pressure is (by definition)
35 below `synthetic.minimum_pressure` [pascal], are discarded.
37 **This method is specific to FreeGSNKE.**
39 See `python/gsfit/database_readers/interface.py` for more details on how a new database_reader should be implemented.
40 """
42 # Initialise the Pressure Rust class
43 pressure = Pressure()
45 pressure_settings = settings["sensor_weights_pressure.json"]
47 # Pressure sensors are opt-in
48 if not pressure_settings.get("include", False):
49 return pressure
51 synthetic_settings = pressure_settings["synthetic"]
52 sensor_r_start: float = synthetic_settings["r_start"]
53 sensor_r_end: float = synthetic_settings["r_end"]
54 n_sensors: int = synthetic_settings["n_sensors"]
55 minimum_pressure: float = synthetic_settings["minimum_pressure"]
57 sensor_name_prefix = pressure_settings["sensor_name_prefix"]
58 fit_settings_comment = pressure_settings["fit_settings"]["comment"]
59 fit_settings_weight = pressure_settings["fit_settings"]["weight"]
61 n_time: int = len(time)
63 # We assume the sensor geometry is not changing in time, so we use the first time-slice
64 mag_r: float = freegsnke_eqs[0].Rmagnetic()
65 mag_z: float = freegsnke_eqs[0].Zmagnetic()
66 sensors_geometry_r: npt.NDArray[np.float64] = mag_r + np.linspace(sensor_r_start, sensor_r_end, n_sensors)
67 sensors_geometry_z: npt.NDArray[np.float64] = np.full(n_sensors, mag_z)
69 # Get the "measured" pressure at each sensor, for each time-slice
70 pressure_measured = np.full((n_time, n_sensors), np.nan)
71 for i_time in range(n_time):
72 psi_n_sensors = freegsnke_eqs[i_time].psiNRZ(sensors_geometry_r, sensors_geometry_z)
73 pressure_measured[i_time, :] = freegsnke_eqs[i_time].pressure(psi_n_sensors)
75 for i_sensor in range(n_sensors):
76 measured = pressure_measured[:, i_sensor].copy()
78 # Ignore (set to NaN) any non-physical / below-threshold measurements, e.g. sensors
79 # which landed outside the last closed flux surface
80 measured[measured <= minimum_pressure] = np.nan
82 # Only add the sensor if it has at least one valid measurement
83 if np.any(~np.isnan(measured)):
84 pressure.add_sensor(
85 name=f"{sensor_name_prefix}{i_sensor + 1:02d}",
86 geometry_r=sensors_geometry_r[i_sensor],
87 geometry_z=sensors_geometry_z[i_sensor],
88 fit_settings_comment=fit_settings_comment,
89 fit_settings_expected_value=float(np.nanmax(measured)),
90 fit_settings_include=True,
91 fit_settings_weight=fit_settings_weight,
92 time=time,
93 measured=measured,
94 )
96 return pressure