Coverage for python/gsfit/database_readers/st40_mdsplus/setup_isoflux_sensors.py: 0%
15 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 gsfit_rs import Isoflux
7from shapely.geometry import LineString
8from st40_database import GetData
10if TYPE_CHECKING:
11 from . import DatabaseReader
14def setup_isoflux_sensors(
15 self: "DatabaseReader",
16 pulseNo: int,
17 settings: dict[str, typing.Any],
18 times_to_reconstruct: npt.NDArray[np.float64],
19) -> Isoflux:
20 """
21 This method initialises the Rust `Isoflux` 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
26 **This method is specific to ST40's experimental MDSplus database.**
28 See `python/gsfit/database_readers/interface.py` for more details on how a new database_reader should be implemented.
29 """
31 # Initialise the Isoflux Rust class
32 isoflux = Isoflux()
34 isoflux_settings = settings["sensor_weights_isoflux.json"]
36 if len(isoflux_settings) == 0:
37 return isoflux
39 code_name = settings["GSFIT_code_settings.json"]["database_reader"]["st40_mdsplus"]["isoflux_code_name"]
40 run_name = settings["GSFIT_code_settings.json"]["database_reader"]["st40_mdsplus"]["workflow"][code_name]["run_name"]
42 # TODO: need to check that this is working!
43 # for isoflux_name in isoflux_settings.keys():
44 # # We need a try/except here because there is sometimes no TS data
45 # try:
46 # results = GetData(pulseNo, f"{code_name}#{run_name}")
48 # time = typing.cast(npt.NDArray[np.float32], results.get("TIME")).astype(np.float64)
49 # n_time = len(time)
51 # r = typing.cast(npt.NDArray[np.float32], results.get("R_MID_PROFILES.R")).astype(np.float64)
52 # te = typing.cast(npt.NDArray[np.float32], results.get("R_MID_PROFILES.TE")).astype(np.float64)
54 # location_1_r = np.full(n_time, np.nan)
55 # location_1_z = np.full(n_time, np.nan)
56 # location_2_r = np.full(n_time, np.nan)
57 # location_2_z = np.full(n_time, np.nan)
59 # for i_time in range(0, n_time):
60 # # Create LineString objects for the two lines
61 # te_profile_line = LineString(np.column_stack((r[i_time, :], te[i_time, :])))
63 # # Read in a LFS coordinate we want to use as the constant
64 # location_1_r_now = isoflux_settings[isoflux_name]["location_1"]["r"]
65 # location_1_z_now = 0.0 # Assumed for TS
67 # # Interpolate the Te profile to find Te at the LFS
68 # index_sorted = np.argsort(r[i_time, :])
69 # te_interpolated = np.interp(location_1_r_now, r[i_time, index_sorted], te[i_time, index_sorted])
71 # r_target_line = np.array([location_1_r_now, 200.0])
72 # te_target_line = np.array([te_interpolated, te_interpolated])
73 # line_to_interpolate = LineString(np.column_stack((r_target_line, te_target_line)))
75 # # Find the intersection
76 # intersections = te_profile_line.intersection(line_to_interpolate)
78 # # Convert `intersections` to list
79 # geoms = []
80 # if intersections.geom_type == "MultiPoint":
81 # geoms = [geom for geom in intersections.geoms] # TODO: causes mypy error??
82 # # if intersections.geom_type == 'Point' # there is only one intersection, so we haven't found both the LFS and HFS
83 # # if intersections.geom_type == 'MultiLineString': # this only happens when the entire line is 0.0
85 # # Loop over all intersections
86 # location_2_r_now = np.nan
87 # location_2_z_now = np.nan
88 # if len(geoms) > 0:
89 # for geom in geoms:
90 # # Look for HFS intersection
91 # if geom.x > location_1_r_now:
92 # location_2_r_now = geom.x
93 # location_2_z_now = 0.0
95 # # Store the isoflux coordinates
96 # if not np.isnan(location_2_r_now):
97 # location_1_r[i_time] = location_1_r_now
98 # location_1_z[i_time] = location_1_z_now
99 # location_2_r[i_time] = location_2_r_now
100 # location_2_z[i_time] = location_2_z_now
102 # isoflux.add_sensor(
103 # name=isoflux_name,
104 # fit_settings_comment="",
105 # fit_settings_include=True,
106 # fit_settings_weight=1.0e3,
107 # time=time,
108 # location_1_r=location_1_r,
109 # location_1_z=location_1_z,
110 # location_2_r=location_2_r,
111 # location_2_z=location_2_z,
112 # times_to_reconstruct=times_to_reconstruct,
113 # )
114 # except Exception as e:
115 # print(f"Error reading {isoflux_name}; exception={e}")
117 return isoflux