Coverage for python/gsfit/database_readers/freegsnke/setup_bp_probes.py: 86%
37 statements
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-07 13:12 +0000
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-07 13:12 +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 BpProbes
9if TYPE_CHECKING:
10 from . import DatabaseReader
13def setup_bp_probes(
14 self: "DatabaseReader",
15 pulseNo: int,
16 settings: dict[str, typing.Any],
17 time: npt.NDArray[np.float64],
18 freegsnke_eqs: list[FreeGsnkeEquilibrium],
19) -> BpProbes:
20 """
21 This method initialises the Rust `BpProbes` class.
23 :param pulseNo: Pulse number, used to read from the database
24 :param settings: Dictionary containing the JSON settings read from the `settings` directory
25 :param time: Measured time vector
26 :param freegsnke_eqs: List of FreeGSNKE equilibrium objects, one for each time-slice
28 **This method is specific to FreeGSNKE.**
30 See `python/gsfit/database_readers/interface.py` for more details on how a new database_reader should be implemented.
31 """
33 # Initialise the BpProbes Rust class
34 bp_probes = BpProbes()
36 # We assume that the static data is not changing in time
37 freegsnke_tokamak = freegsnke_eqs[0].tokamak
39 # Get lengths
40 n_time = len(time)
41 n_sensors = len(freegsnke_tokamak.probes.pickups)
43 # Loop over time and calculate the pickup values
44 pickups_vals = np.full((n_time, n_sensors), np.nan)
45 for i_time in range(n_time):
46 pickups_vals[i_time, :] = freegsnke_tokamak.probes.calculate_pickup_value(freegsnke_eqs[i_time])
48 # Loop over sensors and add them to the BpProbes class
49 for i_sensor, sensor in enumerate(freegsnke_tokamak.probes.pickups):
50 # Only use sensors in the poloidal plane
51 if sensor["orientation"] == "PARALLEL":
52 # Get the sensor name
53 sensor_name = sensor["name"]
55 # Only add sesnors which are included in the settings file
56 if sensor_name in settings["sensor_weights_bp_probe.json"]:
57 fit_settings_comment = settings["sensor_weights_bp_probe.json"][sensor_name]["fit_settings"]["comment"]
58 fit_settings_expected_value = settings["sensor_weights_bp_probe.json"][sensor_name]["fit_settings"]["expected_value"]
59 fit_settings_include = settings["sensor_weights_bp_probe.json"][sensor_name]["fit_settings"]["include"]
60 fit_settings_weight = settings["sensor_weights_bp_probe.json"][sensor_name]["fit_settings"]["weight"]
61 else:
62 fit_settings_comment = ""
63 fit_settings_expected_value = np.nan
64 fit_settings_include = False
65 fit_settings_weight = np.nan
67 # Get the sensor position
68 r = sensor["position"][0]
69 z = sensor["position"][2]
71 orientation_vector = sensor["orientation_vector"]
72 orientation_r = orientation_vector[0]
73 orientation_z = orientation_vector[2]
74 if orientation_r == 0.0 and orientation_z == 0.0:
75 raise ValueError(f"Sensor {sensor_name} has zero orientation vector. Perhaps it's pointing in the toroidal direction?")
76 angle = np.arctan2(orientation_z, orientation_r)
78 # Get the sensor data, all times
79 measured = pickups_vals[:, i_sensor]
81 # Add the sensor to the BpProbes class
82 bp_probes.add_sensor(
83 name=sensor_name,
84 geometry_angle_pol=angle,
85 geometry_r=r,
86 geometry_z=z,
87 fit_settings_comment=fit_settings_comment,
88 fit_settings_expected_value=fit_settings_expected_value,
89 fit_settings_include=fit_settings_include,
90 fit_settings_weight=fit_settings_weight,
91 time=time,
92 measured=measured,
93 )
95 return bp_probes