From 2d7856e8f9d457df11b974b65d18c2d7bccf68ee Mon Sep 17 00:00:00 2001 From: Jussi Hakosalo Date: Sun, 24 Mar 2024 20:38:34 +0000 Subject: [PATCH 01/11] feat: config for st40 reader, not working yet --- indica/readers/st40conf.py | 233 +++++++++++++++++++++++++++++++++++ indica/readers/st40reader.py | 4 + 2 files changed, 237 insertions(+) create mode 100644 indica/readers/st40conf.py diff --git a/indica/readers/st40conf.py b/indica/readers/st40conf.py new file mode 100644 index 00000000..2c810a02 --- /dev/null +++ b/indica/readers/st40conf.py @@ -0,0 +1,233 @@ +MACHINE_DIMS = ((0.15, 0.85), (-0.75, 0.75)) +INSTRUMENT_METHODS = { + "efit": "get_equilibrium", + "xrcs": "get_helike_spectroscopy", + "princeton": "get_charge_exchange", + "lines": "get_diode_filters", + "nirh1": "get_interferometry", + "nirh1_bin": "get_interferometry", + "smmh1": "get_interferometry", + "smmh": "get_interferometry", + "astra": "get_astra", + "sxr_spd": "get_radiation", + "sxr_diode_1": "get_diode_filters", + "sxr_diode_2": "get_diode_filters", + "sxr_diode_3": "get_diode_filters", + "sxr_diode_4": "get_diode_filters", + "sxr_mid1": "get_radiation", + "sxr_mid2": "get_radiation", + "sxr_mid3": "get_radiation", + "sxr_mid4": "get_radiation", + "sxrc_xy1": "get_radiation", + "sxrc_xy2": "get_radiation", + "blom_xy1": "get_radiation", + "cxff_pi": "get_charge_exchange", + "cxff_tws_c": "get_charge_exchange", + "cxqf_tws_c": "get_charge_exchange", + "pi": "get_spectrometer", + "tws_c": "get_spectrometer", + "ts": "get_thomson_scattering", +} +# TODO: this will not be necessary once the MDS+ standardisation is complete +UIDS_MDS = { + "xrcs": "sxr", + "princeton": "spectrom", + "nirh1": "interferom", + "nirh1_bin": "interferom", + "smmh1": "interferom", + "sxr_diode_1": "sxr", + "sxr_diode_2": "sxr", + "sxr_diode_3": "sxr", + "sxr_diode_4": "sxr", +} +QUANTITIES_MDS = { + "efit": { + "f": ".profiles.psi_norm:f", + "faxs": ".global:faxs", + "fbnd": ".global:fbnd", + "ftor": ".profiles.psi_norm:ftor", + "rmji": ".profiles.psi_norm:rmji", + "rmjo": ".profiles.psi_norm:rmjo", + "psi": ".psi2d:psi", + "vjac": ".profiles.psi_norm:vjac", + "ajac": ".profiles.psi_norm:ajac", + "rmag": ".global:rmag", + "rgeo": ".global:rgeo", + "rbnd": ".p_boundary:rbnd", + "zmag": ".global:zmag", + "zbnd": ".p_boundary:zbnd", + "ipla": ".constraints.ip:cvalue", + "wp": ".virial:wp", + "df": ".constraints.df:cvalue", + }, + "xrcs": { + "int_k": ".te_kw:int_k", + "int_w": ".te_kw:int_w", + "int_z": ".te_kw:int_z", + "int_q": ".te_kw:int_q", + "int_r": ".te_kw:int_r", + "int_a": ".te_kw:int_a", + "int_n3": ".te_n3w:int_n3", + "int_tot": ".te_n3w:int_tot", + "te_kw": ".te_kw:te", + "te_n3w": ".te_n3w:te", + "ti_w": ".ti_w:ti", + "ti_z": ".ti_z:ti", + "ampl_w": ".ti_w:amplitude", + "spectra": ":intensity", + }, + "nirh1": { + "ne": ".line_int:ne", + }, + "nirh1_bin": { + "ne": ".line_int:ne", + }, + "smmh1": { + "ne": ".line_int:ne", + }, + "smmh": { + "ne": ".global:ne_int", + }, + "lines": { + "brightness": ":emission", + }, + "sxr_spd": { + "brightness": ".profiles:emission", + }, + "sxr_mid1": { + "brightness": ".profiles:emission", + }, + "sxr_mid2": { + "brightness": ".profiles:emission", + }, + "sxr_mid3": { + "brightness": ".profiles:emission", + }, + "sxr_mid4": { + "brightness": ".profiles:emission", + }, + "diode_arrays": { + "brightness": ".middle_head.filter_4:", + "location": ".middle_head.geometry:location", + "direction": ".middle_head.geometry:direction", + }, + "sxrc_xy1": { + "brightness": ".profiles:emission", + }, + "sxrc_xy2": { + "brightness": ".profiles:emission", + }, + "blom_xy1": { + "brightness": ".profiles:emission", + }, + "sxr_diode_1": { + "brightness": ".filter_001:signal", + }, + "sxr_diode_2": { + "brightness": ".filter_002:signal", + }, + "sxr_diode_3": { + "brightness": ".filter_003:signal", + }, + "sxr_diode_4": { + "brightness": ".filter_004:signal", + }, + "cxff_pi": { + "int": ".profiles:int", + "ti": ".profiles:ti", + "vtor": ".profiles:vtor", + "spectra": ":spectra", + "fit": ":full_fit", + }, + "cxff_tws_c": { + "int": ".profiles:int", + "ti": ".profiles:ti", + "vtor": ".profiles:vtor", + "spectra": ":spectra", + "fit": ":full_fit", + }, + "pi": { + "spectra": ":emission", + }, + "tws_c": { + "spectra": ":emission", + }, + "ts": { + "ne": ".profiles:ne", + "te": ".profiles:te", + "pe": ".profiles:pe", + "chi2": ".profiles:chi2", + }, + "astra": { + "f": ".profiles.psi_norm:fpol", + "faxs": ".global:faxs", + "fbnd": ".global:fbnd", + "ftor": ".profiles.psi_norm:ftor", # Wb + # "rmji": ".profiles.psi_norm:rmji", + # "rmjo": ".profiles.psi_norm:rmjo", + "psi_1d": ".profiles.psi_norm:psi", + "psi": ".psi2d:psi", + # "vjac": ".profiles.psi_norm:vjac", + # "ajac": ".profiles.psi_norm:ajac", + "volume": ".profiles.psi_norm:volume", + "area": ".profiles.psi_norm:areat", + "rmag": ".global:rmag", + "rgeo": ".global:rgeo", + "zmag": ".global:zmag", + "zgeo": ".global:zgeo", + "rbnd": ".p_boundary:rbnd", + "zbnd": ".p_boundary:zbnd", + "wp": ".global:wth", + "ipla": ".global:ipl", + "upl": ".global:upl", + "wth": ".global:wth", + "wtherm": ".global:wtherm", + "wfast": ".global:wfast", + "df": ".global.df", + "elon": ".profiles.astra:elon", # Elongation profile + "j_bs": ".profiles.astra:j_bs", # Bootstrap current density,MA/m2 + "j_nbi": ".profiles.astra:j_nbi", # NB driven current density,MA/m2 + "j_oh": ".profiles.astra:j_oh", # Ohmic current density,MA/m2 + "j_rf": ".profiles.astra:j_rf", # EC driven current density,MA/m2 + "j_tot": ".profiles.astra:j_tot", # Total current density,MA/m2 + "ne": ".profiles.astra:ne", # Electron density, 10^19 m^-3 + "ni": ".profiles.astra:ni", # Main ion density, 10^19 m^-3 + "nf": ".profiles.astra:nf", # Main ion density, 10^19 m^-3 + "n_d": ".profiles.astra:n_d", # Deuterium density,10E19/m3 + "n_t": ".profiles.astra:n_t", # Tritium density ,10E19/m3 + "omega_tor": ".profiles.astra:omega_tor", # Toroidal rot. freq., 1/s + "qe": ".profiles.astra:qe", # electron power flux, MW + "qi": ".profiles.astra:qi", # ion power flux, MW + "qn": ".profiles.astra:qn", # total electron flux, 10^19/s + "qnbe": ".profiles.astra:qnbe", # Beam power density to electrons, MW/m3 + "qnbi": ".profiles.astra:qnbi", # Beam power density to ions, MW/m3 + "q_oh": ".profiles.astra:q_oh", # Ohmic heating power profile, MW/m3 + "q_rf": ".profiles.astra:q_rf", # RF power density to electron,MW/m3 + "rho": ".profiles.astra:rho", # ASTRA rho-toroidal + "rmid": ".profiles.astra:rmid", # Centre of flux surfaces, m + "rminor": ".profiles.astra:rminor", # minor radius, m + "sbm": ".profiles.astra:sbm", # Particle source from beam, 10^19/m^3/s + "spel": ".profiles.astra:spel", # Particle source from pellets, 10^19/m^3/s + "stot": ".profiles.astra:stot", # Total electron source,10^19/s/m3 + "swall": ".profiles.astra:swall", # Wall neutrals source, 10^19/m^3/s + "te": ".profiles.astra:te", # Electron temperature, keV + "ti": ".profiles.astra:ti", # Ion temperature, keV + "tri": ".profiles.astra:tri", # Triangularity (up/down symmetrized) profile + "t_d": ".profiles.astra:t_d", # Deuterium temperature,keV + "t_t": ".profiles.astra:t_t", # Tritium temperature,keV + "zeff": ".profiles.astra:zeff", # Effective ion charge + "areat": ".profiles.psi_norm:areat", # Toroidal cross section,m2 + "p": ".profiles.psi_norm:p", # PRESSURE(PSI_NORM) + "pblon": ".profiles.astra:pblon", # PRESSURE(PSI_NORM) + "pbper": ".profiles.astra:pbper", # PRESSURE(PSI_NORM) + "pnb": ".global:pnb", # Injected NBI power, W + "pabs": ".global:pabs", # Absorber NBI power, W + "p_oh": ".global:p_oh", # Absorber NBI power, W + "q": ".profiles.psi_norm:q", # Q_PROFILE(PSI_NORM) + "sigmapar": ".profiles.psi_norm:sigmapar", # Paral. conduct.,1/(Ohm*m) + "nn": ".profiles.astra:nn", # Thermal neutral density, 10^19/m^3 + "niz1": ".profiles.astra:niz1", # Impurity density, 10^19/m^3 + "niz2": ".profiles.astra:niz2", # Impurity density, 10^19/m^3 + "niz3": ".profiles.astra:niz3", # Impurity density, 10^19/m^3 + }, +} diff --git a/indica/readers/st40reader.py b/indica/readers/st40reader.py index aa782692..6e402cee 100644 --- a/indica/readers/st40reader.py +++ b/indica/readers/st40reader.py @@ -10,6 +10,10 @@ from typing import Set from typing import Tuple + + +#from st40conf import MACHINE_DIMS, INSTRUMENT_METHODS, UIDS_MDS, QUANTITIES_MDS + from MDSplus import Connection from MDSplus.mdsExceptions import TreeNNF from MDSplus.mdsExceptions import TreeNODATA From 617729e31603df2a6edcab94e93f26a2990dfa51 Mon Sep 17 00:00:00 2001 From: Jussi Hakosalo Date: Sun, 24 Mar 2024 21:12:02 +0000 Subject: [PATCH 02/11] feat: an approach to the reader separation --- indica/readers/mds_functions.py | 132 +++++++++++++ indica/readers/st40reader.py | 326 +------------------------------- 2 files changed, 137 insertions(+), 321 deletions(-) create mode 100644 indica/readers/mds_functions.py diff --git a/indica/readers/mds_functions.py b/indica/readers/mds_functions.py new file mode 100644 index 00000000..a4870f7b --- /dev/null +++ b/indica/readers/mds_functions.py @@ -0,0 +1,132 @@ +from MDSplus import Connection +from MDSplus.mdsExceptions import TreeNNF +from MDSplus.mdsExceptions import TreeNODATA + +from .abstractreader import DataReader +from .. import session + + +from copy import deepcopy +from typing import Any +from typing import Dict +from typing import List +from typing import Set +from typing import Tuple + +from ..numpy_typing import RevisionLike + +import numpy as np + + + +class MDSError(Exception): + """An exception which occurs when trying to read MDS+ data which would + not be caught by the lower-level MDSplus library. An example would be + failing to find any valid channels for an instrument when each channel + is a separate DTYPE. + + """ + + +class MDSWarning(UserWarning): + """A warning that occurs while trying to read MDS+ data. Typically + related to caching in some way. + + """ + +class MDSReader(DataReader): + + def __init__( + self, + pulse: int, + tstart: float, + tend: float, + server: str = "smaug", + tree: str = "ST40", + default_error: float = 0.05, + max_freq: float = 1e6, + session: session.Session = session.global_session, + ): + self.tree: str = tree + self.conn: Connection = Connection(server) + self.conn.openTree(self.tree, self.pulse) + + + + + def get_mds_path_dims(self, mds_path: str, dim: int): + """Gets the dimensions' path given an mds_path""" + + dims_path = f"dim_of({mds_path},{dim})" + return dims_path + + + def _get_signal( + self, uid: str, instrument: str, quantity: str, revision: RevisionLike + ) -> Tuple[np.array, str]: + """Gets the signal for the given INSTRUMENT, at the + given revision.""" + path, path_check = self.get_mds_path(uid, instrument, quantity, revision) + if quantity.lower() == ":best_run": + data = str(self.conn.get(path)) + else: + data = np.array(self.conn.get(path)) + # data = np.array(self.conn.get(path_check)) + + return data, path + + def _get_signal_dims( + self, + mds_path: str, + ndims: int, + ) -> Tuple[List[np.array], List[str]]: + """Gets the dimensions of a signal given the path to the signal + and the number of dimensions""" + + dimensions = [] + paths = [] + for dim in range(ndims): + path = f"dim_of({mds_path},{dim})" + dim_tmp = self.conn.get(self.mdsCheck(path)).data() + + paths.append(path) + dimensions.append(np.array(dim_tmp)) + return dimensions, paths + + + def _get_signal_units( + self, + mds_path: str, + ) -> str: + """Gets the units of a signal given the path to the signal + and the number of dimensions""" + + path = f"units_of({mds_path})" + unit = self.conn.get(path).data() + + return unit + + def get_mds_path( + self, uid: str, instrument: str, quantity: str, revision: RevisionLike + ) -> Tuple[str, str]: + """Return the path in the MDS+ database to for the given INSTRUMENT/CODE + + uid: currently redundant --> set to empty string "" + instrument: e.g. "efit" + quantity: e.g. ".global:cr0" # minor radius + revision: if 0 --> looks for "best", else "run##" + """ + revision_name = self.get_revision_name(revision) + mds_path = "" + if len(uid) > 0: + mds_path += f".{uid}".upper() + if len(instrument) > 0 and instrument.upper() != self.tree.upper(): + mds_path += f".{instrument}".upper() + mds_path += f"{revision_name}{quantity}".upper() + return mds_path, self.mdsCheck(mds_path) + + def get_mds_path_dims(self, mds_path: str, dim: int): + """Gets the dimensions' path given an mds_path""" + + dims_path = f"dim_of({mds_path},{dim})" + return dims_path \ No newline at end of file diff --git a/indica/readers/st40reader.py b/indica/readers/st40reader.py index 6e402cee..d98b8e9b 100644 --- a/indica/readers/st40reader.py +++ b/indica/readers/st40reader.py @@ -12,7 +12,7 @@ -#from st40conf import MACHINE_DIMS, INSTRUMENT_METHODS, UIDS_MDS, QUANTITIES_MDS +from st40conf import MACHINE_DIMS, INSTRUMENT_METHODS, UIDS_MDS, QUANTITIES_MDS from MDSplus import Connection from MDSplus.mdsExceptions import TreeNNF @@ -24,22 +24,6 @@ from ..numpy_typing import RevisionLike -class MDSError(Exception): - """An exception which occurs when trying to read MDS+ data which would - not be caught by the lower-level MDSplus library. An example would be - failing to find any valid channels for an instrument when each channel - is a separate DTYPE. - - """ - - -class MDSWarning(UserWarning): - """A warning that occurs while trying to read MDS+ data. Typically - related to caching in some way. - - """ - - class ST40Reader(DataReader): """Class to read ST40 MDS+ data using MDSplus. @@ -74,240 +58,7 @@ class ST40Reader(DataReader): """ - MACHINE_DIMS = ((0.15, 0.85), (-0.75, 0.75)) - INSTRUMENT_METHODS = { - "efit": "get_equilibrium", - "xrcs": "get_helike_spectroscopy", - "princeton": "get_charge_exchange", - "lines": "get_diode_filters", - "nirh1": "get_interferometry", - "nirh1_bin": "get_interferometry", - "smmh1": "get_interferometry", - "smmh": "get_interferometry", - "astra": "get_astra", - "sxr_spd": "get_radiation", - "sxr_diode_1": "get_diode_filters", - "sxr_diode_2": "get_diode_filters", - "sxr_diode_3": "get_diode_filters", - "sxr_diode_4": "get_diode_filters", - "sxr_mid1": "get_radiation", - "sxr_mid2": "get_radiation", - "sxr_mid3": "get_radiation", - "sxr_mid4": "get_radiation", - "sxrc_xy1": "get_radiation", - "sxrc_xy2": "get_radiation", - "blom_xy1": "get_radiation", - "cxff_pi": "get_charge_exchange", - "cxff_tws_c": "get_charge_exchange", - "cxqf_tws_c": "get_charge_exchange", - "pi": "get_spectrometer", - "tws_c": "get_spectrometer", - "ts": "get_thomson_scattering", - } - # TODO: this will not be necessary once the MDS+ standardisation is complete - UIDS_MDS = { - "xrcs": "sxr", - "princeton": "spectrom", - "nirh1": "interferom", - "nirh1_bin": "interferom", - "smmh1": "interferom", - "sxr_diode_1": "sxr", - "sxr_diode_2": "sxr", - "sxr_diode_3": "sxr", - "sxr_diode_4": "sxr", - } - QUANTITIES_MDS = { - "efit": { - "f": ".profiles.psi_norm:f", - "faxs": ".global:faxs", - "fbnd": ".global:fbnd", - "ftor": ".profiles.psi_norm:ftor", - "rmji": ".profiles.psi_norm:rmji", - "rmjo": ".profiles.psi_norm:rmjo", - "psi": ".psi2d:psi", - "vjac": ".profiles.psi_norm:vjac", - "ajac": ".profiles.psi_norm:ajac", - "rmag": ".global:rmag", - "rgeo": ".global:rgeo", - "rbnd": ".p_boundary:rbnd", - "zmag": ".global:zmag", - "zbnd": ".p_boundary:zbnd", - "ipla": ".constraints.ip:cvalue", - "wp": ".virial:wp", - "df": ".constraints.df:cvalue", - }, - "xrcs": { - "int_k": ".te_kw:int_k", - "int_w": ".te_kw:int_w", - "int_z": ".te_kw:int_z", - "int_q": ".te_kw:int_q", - "int_r": ".te_kw:int_r", - "int_a": ".te_kw:int_a", - "int_n3": ".te_n3w:int_n3", - "int_tot": ".te_n3w:int_tot", - "te_kw": ".te_kw:te", - "te_n3w": ".te_n3w:te", - "ti_w": ".ti_w:ti", - "ti_z": ".ti_z:ti", - "ampl_w": ".ti_w:amplitude", - "spectra": ":intensity", - }, - "nirh1": { - "ne": ".line_int:ne", - }, - "nirh1_bin": { - "ne": ".line_int:ne", - }, - "smmh1": { - "ne": ".line_int:ne", - }, - "smmh": { - "ne": ".global:ne_int", - }, - "lines": { - "brightness": ":emission", - }, - "sxr_spd": { - "brightness": ".profiles:emission", - }, - "sxr_mid1": { - "brightness": ".profiles:emission", - }, - "sxr_mid2": { - "brightness": ".profiles:emission", - }, - "sxr_mid3": { - "brightness": ".profiles:emission", - }, - "sxr_mid4": { - "brightness": ".profiles:emission", - }, - "diode_arrays": { - "brightness": ".middle_head.filter_4:", - "location": ".middle_head.geometry:location", - "direction": ".middle_head.geometry:direction", - }, - "sxrc_xy1": { - "brightness": ".profiles:emission", - }, - "sxrc_xy2": { - "brightness": ".profiles:emission", - }, - "blom_xy1": { - "brightness": ".profiles:emission", - }, - "sxr_diode_1": { - "brightness": ".filter_001:signal", - }, - "sxr_diode_2": { - "brightness": ".filter_002:signal", - }, - "sxr_diode_3": { - "brightness": ".filter_003:signal", - }, - "sxr_diode_4": { - "brightness": ".filter_004:signal", - }, - "cxff_pi": { - "int": ".profiles:int", - "ti": ".profiles:ti", - "vtor": ".profiles:vtor", - "spectra": ":spectra", - "fit": ":full_fit", - }, - "cxff_tws_c": { - "int": ".profiles:int", - "ti": ".profiles:ti", - "vtor": ".profiles:vtor", - "spectra": ":spectra", - "fit": ":full_fit", - }, - "pi": { - "spectra": ":emission", - }, - "tws_c": { - "spectra": ":emission", - }, - "ts": { - "ne": ".profiles:ne", - "te": ".profiles:te", - "pe": ".profiles:pe", - "chi2": ".profiles:chi2", - }, - "astra": { - "f": ".profiles.psi_norm:fpol", - "faxs": ".global:faxs", - "fbnd": ".global:fbnd", - "ftor": ".profiles.psi_norm:ftor", # Wb - # "rmji": ".profiles.psi_norm:rmji", - # "rmjo": ".profiles.psi_norm:rmjo", - "psi_1d": ".profiles.psi_norm:psi", - "psi": ".psi2d:psi", - # "vjac": ".profiles.psi_norm:vjac", - # "ajac": ".profiles.psi_norm:ajac", - "volume": ".profiles.psi_norm:volume", - "area": ".profiles.psi_norm:areat", - "rmag": ".global:rmag", - "rgeo": ".global:rgeo", - "zmag": ".global:zmag", - "zgeo": ".global:zgeo", - "rbnd": ".p_boundary:rbnd", - "zbnd": ".p_boundary:zbnd", - "wp": ".global:wth", - "ipla": ".global:ipl", - "upl": ".global:upl", - "wth": ".global:wth", - "wtherm": ".global:wtherm", - "wfast": ".global:wfast", - "df": ".global.df", - "elon": ".profiles.astra:elon", # Elongation profile - "j_bs": ".profiles.astra:j_bs", # Bootstrap current density,MA/m2 - "j_nbi": ".profiles.astra:j_nbi", # NB driven current density,MA/m2 - "j_oh": ".profiles.astra:j_oh", # Ohmic current density,MA/m2 - "j_rf": ".profiles.astra:j_rf", # EC driven current density,MA/m2 - "j_tot": ".profiles.astra:j_tot", # Total current density,MA/m2 - "ne": ".profiles.astra:ne", # Electron density, 10^19 m^-3 - "ni": ".profiles.astra:ni", # Main ion density, 10^19 m^-3 - "nf": ".profiles.astra:nf", # Main ion density, 10^19 m^-3 - "n_d": ".profiles.astra:n_d", # Deuterium density,10E19/m3 - "n_t": ".profiles.astra:n_t", # Tritium density ,10E19/m3 - "omega_tor": ".profiles.astra:omega_tor", # Toroidal rot. freq., 1/s - "qe": ".profiles.astra:qe", # electron power flux, MW - "qi": ".profiles.astra:qi", # ion power flux, MW - "qn": ".profiles.astra:qn", # total electron flux, 10^19/s - "qnbe": ".profiles.astra:qnbe", # Beam power density to electrons, MW/m3 - "qnbi": ".profiles.astra:qnbi", # Beam power density to ions, MW/m3 - "q_oh": ".profiles.astra:q_oh", # Ohmic heating power profile, MW/m3 - "q_rf": ".profiles.astra:q_rf", # RF power density to electron,MW/m3 - "rho": ".profiles.astra:rho", # ASTRA rho-toroidal - "rmid": ".profiles.astra:rmid", # Centre of flux surfaces, m - "rminor": ".profiles.astra:rminor", # minor radius, m - "sbm": ".profiles.astra:sbm", # Particle source from beam, 10^19/m^3/s - "spel": ".profiles.astra:spel", # Particle source from pellets, 10^19/m^3/s - "stot": ".profiles.astra:stot", # Total electron source,10^19/s/m3 - "swall": ".profiles.astra:swall", # Wall neutrals source, 10^19/m^3/s - "te": ".profiles.astra:te", # Electron temperature, keV - "ti": ".profiles.astra:ti", # Ion temperature, keV - "tri": ".profiles.astra:tri", # Triangularity (up/down symmetrized) profile - "t_d": ".profiles.astra:t_d", # Deuterium temperature,keV - "t_t": ".profiles.astra:t_t", # Tritium temperature,keV - "zeff": ".profiles.astra:zeff", # Effective ion charge - "areat": ".profiles.psi_norm:areat", # Toroidal cross section,m2 - "p": ".profiles.psi_norm:p", # PRESSURE(PSI_NORM) - "pblon": ".profiles.astra:pblon", # PRESSURE(PSI_NORM) - "pbper": ".profiles.astra:pbper", # PRESSURE(PSI_NORM) - "pnb": ".global:pnb", # Injected NBI power, W - "pabs": ".global:pabs", # Absorber NBI power, W - "p_oh": ".global:p_oh", # Absorber NBI power, W - "q": ".profiles.psi_norm:q", # Q_PROFILE(PSI_NORM) - "sigmapar": ".profiles.psi_norm:sigmapar", # Paral. conduct.,1/(Ohm*m) - "nn": ".profiles.astra:nn", # Thermal neutral density, 10^19/m^3 - "niz1": ".profiles.astra:niz1", # Impurity density, 10^19/m^3 - "niz2": ".profiles.astra:niz2", # Impurity density, 10^19/m^3 - "niz3": ".profiles.astra:niz3", # Impurity density, 10^19/m^3 - }, - } - + def __init__( self, pulse: int, @@ -331,35 +82,10 @@ def __init__( default_error=default_error, ) self.pulse: int = pulse - self.tree: str = tree - self.conn: Connection = Connection(server) - self.conn.openTree(self.tree, self.pulse) - self._default_error = default_error - - def get_mds_path( - self, uid: str, instrument: str, quantity: str, revision: RevisionLike - ) -> Tuple[str, str]: - """Return the path in the MDS+ database to for the given INSTRUMENT/CODE - uid: currently redundant --> set to empty string "" - instrument: e.g. "efit" - quantity: e.g. ".global:cr0" # minor radius - revision: if 0 --> looks for "best", else "run##" - """ - revision_name = self.get_revision_name(revision) - mds_path = "" - if len(uid) > 0: - mds_path += f".{uid}".upper() - if len(instrument) > 0 and instrument.upper() != self.tree.upper(): - mds_path += f".{instrument}".upper() - mds_path += f"{revision_name}{quantity}".upper() - return mds_path, self.mdsCheck(mds_path) + self._default_error = default_error - def get_mds_path_dims(self, mds_path: str, dim: int): - """Gets the dimensions' path given an mds_path""" - dims_path = f"dim_of({mds_path},{dim})" - return dims_path def _get_data( self, uid: str, instrument: str, quantity: str, revision: RevisionLike @@ -371,51 +97,9 @@ def _get_data( unit = self._get_signal_units(_path) return data, dims, unit, _path + - def _get_signal( - self, uid: str, instrument: str, quantity: str, revision: RevisionLike - ) -> Tuple[np.array, str]: - """Gets the signal for the given INSTRUMENT, at the - given revision.""" - path, path_check = self.get_mds_path(uid, instrument, quantity, revision) - if quantity.lower() == ":best_run": - data = str(self.conn.get(path)) - else: - data = np.array(self.conn.get(path)) - # data = np.array(self.conn.get(path_check)) - - return data, path - - def _get_signal_dims( - self, - mds_path: str, - ndims: int, - ) -> Tuple[List[np.array], List[str]]: - """Gets the dimensions of a signal given the path to the signal - and the number of dimensions""" - - dimensions = [] - paths = [] - for dim in range(ndims): - path = f"dim_of({mds_path},{dim})" - dim_tmp = self.conn.get(self.mdsCheck(path)).data() - - paths.append(path) - dimensions.append(np.array(dim_tmp)) - return dimensions, paths - - def _get_signal_units( - self, - mds_path: str, - ) -> str: - """Gets the units of a signal given the path to the signal - and the number of dimensions""" - - path = f"units_of({mds_path})" - unit = self.conn.get(path).data() - - return unit - + def _get_revision( self, uid: str, instrument: str, revision: RevisionLike ) -> RevisionLike: From 649e3d9893368e1cb706f739a5e021fd5b5a6f70 Mon Sep 17 00:00:00 2001 From: Jussi Hakosalo Date: Thu, 4 Apr 2024 00:55:15 +0100 Subject: [PATCH 03/11] feat: split mds and st40reader, split config to a separate class. Connection error atm --- indica/readers/__init__.py | 19 +- .../readers/{mds_functions.py => mdsutils.py} | 41 +++-- indica/readers/st40conf.py | 18 +- indica/readers/st40reader.py | 168 +++++++++--------- 4 files changed, 144 insertions(+), 102 deletions(-) rename indica/readers/{mds_functions.py => mdsutils.py} (81%) diff --git a/indica/readers/__init__.py b/indica/readers/__init__.py index 5f427343..6574b5a7 100644 --- a/indica/readers/__init__.py +++ b/indica/readers/__init__.py @@ -17,9 +17,26 @@ except ImportError: pass +try: + from .st40conf import ST40Conf + __all__ +=["ST40Conf"] +except ImportError as e: + print(e) + pass + +try: + from .mdsutils import MDSUtils + __all__+=["MDSUtils"] +except ImportError as e: + print(e) + pass + + + try: from .st40reader import ST40Reader __all__ += ["ST40Reader"] -except ImportError: +except ImportError as e: + print(e) pass diff --git a/indica/readers/mds_functions.py b/indica/readers/mdsutils.py similarity index 81% rename from indica/readers/mds_functions.py rename to indica/readers/mdsutils.py index a4870f7b..82c216a7 100644 --- a/indica/readers/mds_functions.py +++ b/indica/readers/mdsutils.py @@ -13,6 +13,8 @@ from typing import Set from typing import Tuple +from indica.abstractio import BaseIO + from ..numpy_typing import RevisionLike import numpy as np @@ -34,26 +36,31 @@ class MDSWarning(UserWarning): """ -class MDSReader(DataReader): +#this will be baseio class instead. what is defauly pulse? +class MDSUtils(BaseIO): def __init__( self, - pulse: int, - tstart: float, - tend: float, + pulse, server: str = "smaug", tree: str = "ST40", - default_error: float = 0.05, - max_freq: float = 1e6, - session: session.Session = session.global_session, ): self.tree: str = tree + self.pulse: int = pulse self.conn: Connection = Connection(server) self.conn.openTree(self.tree, self.pulse) + + def close(self) -> None: + del self.conn + + @property + def requires_authentication(self) -> bool: + return False + def get_mds_path_dims(self, mds_path: str, dim: int): """Gets the dimensions' path given an mds_path""" @@ -61,7 +68,7 @@ def get_mds_path_dims(self, mds_path: str, dim: int): return dims_path - def _get_signal( + def get_signal( self, uid: str, instrument: str, quantity: str, revision: RevisionLike ) -> Tuple[np.array, str]: """Gets the signal for the given INSTRUMENT, at the @@ -75,7 +82,7 @@ def _get_signal( return data, path - def _get_signal_dims( + def get_signal_dims( self, mds_path: str, ndims: int, @@ -94,7 +101,7 @@ def _get_signal_dims( return dimensions, paths - def _get_signal_units( + def get_signal_units( self, mds_path: str, ) -> str: @@ -129,4 +136,16 @@ def get_mds_path_dims(self, mds_path: str, dim: int): """Gets the dimensions' path given an mds_path""" dims_path = f"dim_of({mds_path},{dim})" - return dims_path \ No newline at end of file + return dims_path + + def mdsCheck(self, mds_path): + """Return FAILED if node doesn't exist or other error + Return FAILED if: lenght(data)==1 and data==nan""" + + mds_path_test = ( + f"_dummy = IF_ERROR (IF ((SIZE ({mds_path})==1), " + + f'IF ({mds_path}+1>{mds_path}, {mds_path}, "FAILED"),' + + f' {mds_path}), "FAILED")' + ) + + return mds_path_test \ No newline at end of file diff --git a/indica/readers/st40conf.py b/indica/readers/st40conf.py index 2c810a02..fea2984c 100644 --- a/indica/readers/st40conf.py +++ b/indica/readers/st40conf.py @@ -1,5 +1,9 @@ -MACHINE_DIMS = ((0.15, 0.85), (-0.75, 0.75)) -INSTRUMENT_METHODS = { +class ST40Conf: + def __init__(self): + + + self.MACHINE_DIMS = ((0.15, 0.85), (-0.75, 0.75)) + self.INSTRUMENT_METHODS = { "efit": "get_equilibrium", "xrcs": "get_helike_spectroscopy", "princeton": "get_charge_exchange", @@ -27,9 +31,9 @@ "pi": "get_spectrometer", "tws_c": "get_spectrometer", "ts": "get_thomson_scattering", -} -# TODO: this will not be necessary once the MDS+ standardisation is complete -UIDS_MDS = { + } + + self.UIDS_MDS = { "xrcs": "sxr", "princeton": "spectrom", "nirh1": "interferom", @@ -40,7 +44,7 @@ "sxr_diode_3": "sxr", "sxr_diode_4": "sxr", } -QUANTITIES_MDS = { + self.QUANTITIES_MDS = { "efit": { "f": ".profiles.psi_norm:f", "faxs": ".global:faxs", @@ -229,5 +233,5 @@ "niz1": ".profiles.astra:niz1", # Impurity density, 10^19/m^3 "niz2": ".profiles.astra:niz2", # Impurity density, 10^19/m^3 "niz3": ".profiles.astra:niz3", # Impurity density, 10^19/m^3 - }, + } } diff --git a/indica/readers/st40reader.py b/indica/readers/st40reader.py index d98b8e9b..1bcda75d 100644 --- a/indica/readers/st40reader.py +++ b/indica/readers/st40reader.py @@ -12,7 +12,9 @@ -from st40conf import MACHINE_DIMS, INSTRUMENT_METHODS, UIDS_MDS, QUANTITIES_MDS +from .st40conf import ST40Conf + +from .mdsutils import MDSUtils from MDSplus import Connection from MDSplus.mdsExceptions import TreeNNF @@ -84,6 +86,16 @@ def __init__( self.pulse: int = pulse self._default_error = default_error + self.mdsutils=MDSUtils(server,tree,pulse) + + + #ST40 configurations. ACtually should modify the code not to set as self.. + self.st40conf = ST40Conf() + self.MACHINE_DIMS=self.st40conf.MACHINE_DIMS + self.INSTRUMENT_METHODS=self.st40conf.INSTRUMENT_METHODS + self.UIDS_MDS=self.st40conf.UIDS_MDS + self.QUANTITIES_MDS=self.st40conf.QUANTITIES_MDS + @@ -92,9 +104,9 @@ def _get_data( ) -> Tuple[np.array, List[np.array], str, str]: """Gets the signal and its coordinates for the given INSTRUMENT, at the given revision.""" - data, _path = self._get_signal(uid, instrument, quantity, revision) - dims, _ = self._get_signal_dims(_path, len(data.shape)) - unit = self._get_signal_units(_path) + data, _path = self.mdsutils.get_signal(uid, instrument, quantity, revision) + dims, _ = self.mdsutils.get_signal_dims(_path, len(data.shape)) + unit = self.mdsutils.get_signal_units(_path) return data, dims, unit, _path @@ -110,7 +122,7 @@ def _get_revision( return revision if revision == 0: - run_name, _ = self._get_signal(uid, instrument, ":best_run", revision) + run_name, _ = self.mdsutils.get_signal(uid, instrument, ":best_run", revision) return run_name return revision @@ -130,22 +142,22 @@ def _get_equilibrium( results: Dict[str, Any] = {} results["revision"] = self._get_revision(uid, instrument, revision) revision = results["revision"] - times, _ = self._get_signal(uid, instrument, ":time", revision) + times, _ = self.mdsutils.get_signal(uid, instrument, ":time", revision) results["times"] = times - results["psin"], results["psin_records"] = self._get_signal( + results["psin"], results["psin_records"] = self.mdsutils.get_signal( uid, instrument, ".profiles.psi_norm:xpsn", revision ) - results["psi_r"], results["psi_r_records"] = self._get_signal( + results["psi_r"], results["psi_r_records"] = self.mdsutils.get_signal( uid, instrument, ".psi2d:rgrid", revision ) - results["psi_z"], results["psi_z_records"] = self._get_signal( + results["psi_z"], results["psi_z_records"] = self.mdsutils.get_signal( uid, instrument, ".psi2d:zgrid", revision ) for q in quantities: if q not in self.QUANTITIES_MDS[instrument].keys(): continue try: - qval, q_path = self._get_signal( + qval, q_path = self.mdsutils.get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q], revision ) except TreeNNF: @@ -187,30 +199,30 @@ def _get_astra( revision = results["revision"] # Read time and radial dimensions - results["boundary_index"], _ = self._get_signal( + results["boundary_index"], _ = self.mdsutils.get_signal( uid, instrument, ".p_boundary:index", revision ) - results["psi"], _ = self._get_signal( + results["psi"], _ = self.mdsutils.get_signal( uid, instrument, ".profiles.psi_norm:psi", revision ) - results["psin"], psin_path = self._get_signal( + results["psin"], psin_path = self.mdsutils.get_signal( uid, instrument, ".profiles.psi_norm:xpsn", revision ) - results["ftor"], _ = self._get_signal( + results["ftor"], _ = self.mdsutils.get_signal( uid, instrument, ".profiles.psi_norm:ftor", revision ) - results["rho"], rho_path = self._get_signal( + results["rho"], rho_path = self.mdsutils.get_signal( uid, instrument, ".profiles.astra:rho", revision ) - results["psi_r"], _ = self._get_signal( + results["psi_r"], _ = self.mdsutils.get_signal( uid, instrument, ".psi2d:rgrid", revision ) - results["psi_z"], _ = self._get_signal( + results["psi_z"], _ = self.mdsutils.get_signal( uid, instrument, ".psi2d:zgrid", revision ) - results["times"], t_path = self._get_signal(uid, instrument, ":time", revision) + results["times"], t_path = self.mdsutils.get_signal(uid, instrument, ":time", revision) for q in quantities: - qval, q_path = self._get_signal( + qval, q_path = self.mdsutils.get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q], revision ) @@ -244,27 +256,27 @@ def _get_radiation( results["revision"] = self._get_revision(uid, instrument, revision) revision = results["revision"] - location, location_path = self._get_signal( + location, location_path = self.mdsutils.get_signal( uid, instrument, ".geometry:location", revision ) - direction, direction_path = self._get_signal( + direction, direction_path = self.mdsutils.get_signal( uid, instrument, ".geometry:direction", revision ) quantity = "brightness" - times, times_path = self._get_signal( + times, times_path = self.mdsutils.get_signal( uid, instrument, ":time", revision, ) - qval, qval_record = self._get_signal( + qval, qval_record = self.mdsutils.get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][quantity], revision, ) - qerr, qerr_record = self._get_signal( + qerr, qerr_record = self.mdsutils.get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][quantity] + "_err", @@ -302,18 +314,18 @@ def _get_helike_spectroscopy( results["revision"] = self._get_revision(uid, instrument, revision) revision = results["revision"] - location, location_path = self._get_signal( + location, location_path = self.mdsutils.get_signal( uid, instrument, ".geometry:location", revision ) - direction, direction_path = self._get_signal( + direction, direction_path = self.mdsutils.get_signal( uid, instrument, ".geometry:direction", revision ) if len(np.shape(location)) == 1: location = np.array([location]) direction = np.array([direction]) - results["times"], _ = self._get_signal(uid, instrument, ":time", revision) - wavelength, _ = self._get_signal(uid, instrument, ":wavelength", revision) + results["times"], _ = self.mdsutils.get_signal(uid, instrument, ":time", revision) + wavelength, _ = self.mdsutils.get_signal(uid, instrument, ":wavelength", revision) # TODO: change once wavelength in MDS+ has been fixed to nanometers! wavelength /= 10.0 if self.pulse >= 10307: @@ -322,14 +334,14 @@ def _get_helike_spectroscopy( results["wavelength"] = wavelength for q in quantities: - qval, q_path = self._get_signal( + qval, q_path = self.mdsutils.get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q], revision ) results[q + "_records"] = q_path results[q] = qval try: - qval_err, q_path_err = self._get_signal( + qval_err, q_path_err = self.mdsutils.get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q] + "_err", @@ -367,24 +379,24 @@ def _get_charge_exchange( results["revision"] = self._get_revision(uid, instrument, revision) revision = results["revision"] - texp, texp_path = self._get_signal(uid, instrument, ":exposure", revision) - times, _ = self._get_signal(uid, instrument, ":time", revision) + texp, texp_path = self.mdsutils.get_signal(uid, instrument, ":exposure", revision) + times, _ = self.mdsutils.get_signal(uid, instrument, ":time", revision) try: - wavelength, _ = self._get_signal(uid, instrument, ":wavelen", revision) + wavelength, _ = self.mdsutils.get_signal(uid, instrument, ":wavelen", revision) except TreeNODATA: wavelength = None - x, x_path = self._get_signal(uid, instrument, ":x", revision) - y, y_path = self._get_signal(uid, instrument, ":y", revision) - z, z_path = self._get_signal(uid, instrument, ":z", revision) - R, R_path = self._get_signal(uid, instrument, ":R", revision) + x, x_path = self.mdsutils.get_signal(uid, instrument, ":x", revision) + y, y_path = self.mdsutils.get_signal(uid, instrument, ":y", revision) + z, z_path = self.mdsutils.get_signal(uid, instrument, ":z", revision) + R, R_path = self.mdsutils.get_signal(uid, instrument, ":R", revision) # TODO: temporary fix until geometry sorted (especially pulse if statement..) try: - location, location_path = self._get_signal( + location, location_path = self.mdsutils.get_signal( uid, instrument, ".geometry:location", revision ) - direction, direction_path = self._get_signal( + direction, direction_path = self.mdsutils.get_signal( uid, instrument, ".geometry:direction", revision ) if len(np.shape(location)) == 1: @@ -404,7 +416,7 @@ def _get_charge_exchange( for q in quantities: try: - qval, q_path = self._get_signal( + qval, q_path = self.mdsutils.get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q], @@ -414,7 +426,7 @@ def _get_charge_exchange( continue try: - qval_err, q_path_err = self._get_signal( + qval_err, q_path_err = self.mdsutils.get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q] + "_err", @@ -423,7 +435,7 @@ def _get_charge_exchange( except TreeNNF: qval_err = np.full_like(qval, 0.0) - dimensions, _ = self._get_signal_dims(q_path, len(qval.shape)) + dimensions, _ = self.mdsutils.get_signal_dims(q_path, len(qval.shape)) results[q + "_records"] = q_path results[q] = qval results[f"{q}_error"] = qval_err @@ -463,13 +475,13 @@ def _get_spectrometer( results["revision"] = self._get_revision(uid, instrument, revision) revision = results["revision"] - times, _ = self._get_signal(uid, instrument, ":time", revision) - wavelength, _ = self._get_signal(uid, instrument, ":wavelen", revision) + times, _ = self.mdsutils.get_signal(uid, instrument, ":time", revision) + wavelength, _ = self.mdsutils.get_signal(uid, instrument, ":wavelen", revision) - location, location_path = self._get_signal( + location, location_path = self.mdsutils.get_signal( uid, instrument, ".geometry:location", revision ) - direction, direction_path = self._get_signal( + direction, direction_path = self.mdsutils.get_signal( uid, instrument, ".geometry:direction", revision ) if len(np.shape(location)) == 1: @@ -477,7 +489,7 @@ def _get_spectrometer( direction = np.array([direction]) for q in quantities: - qval, q_path = self._get_signal( + qval, q_path = self.mdsutils.get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q], @@ -485,7 +497,7 @@ def _get_spectrometer( ) try: - qval_err, q_path_err = self._get_signal( + qval_err, q_path_err = self.mdsutils.get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q] + "_err", @@ -494,7 +506,7 @@ def _get_spectrometer( except TreeNNF: qval_err = np.full_like(qval, 0.0) - dimensions, _ = self._get_signal_dims(q_path, len(qval.shape)) + dimensions, _ = self.mdsutils.get_signal_dims(q_path, len(qval.shape)) results[q + "_records"] = q_path results[q] = qval @@ -523,10 +535,10 @@ def _get_diode_filters( if len(uid) == 0 and instrument in self.UIDS_MDS: uid = self.UIDS_MDS[instrument] - location, location_path = self._get_signal( + location, location_path = self.mdsutils.get_signal( uid, instrument, ".geometry:location", revision ) - direction, position_path = self._get_signal( + direction, position_path = self.mdsutils.get_signal( uid, instrument, ".geometry:direction", revision ) if len(np.shape(location)) == 1: @@ -546,11 +558,11 @@ def _get_diode_filters( revision = results["revision"] quantity = "brightness" - qval, q_path = self._get_signal( + qval, q_path = self.mdsutils.get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][quantity], revision ) - times, _ = self._get_signal(uid, instrument, ":time", revision) - _labels, _ = self._get_signal(uid, instrument, ":label", revision) + times, _ = self.mdsutils.get_signal(uid, instrument, ":time", revision) + _labels, _ = self.mdsutils.get_signal(uid, instrument, ":label", revision) if type(_labels[0]) == np.bytes_: labels = np.array([label.decode("UTF-8") for label in _labels]) else: @@ -561,7 +573,7 @@ def _get_diode_filters( results[quantity + "_records"] = q_path results[quantity] = qval try: - qval_err, q_path_err = self._get_signal( + qval_err, q_path_err = self.mdsutils.get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][quantity] + "_ERR", @@ -598,18 +610,18 @@ def _get_interferometry( results["revision"] = self._get_revision(uid, instrument, revision) revision = results["revision"] - location, location_path = self._get_signal( + location, location_path = self.mdsutils.get_signal( uid, instrument, ".geometry:location", revision ) - direction, direction_path = self._get_signal( + direction, direction_path = self.mdsutils.get_signal( uid, instrument, ".geometry:direction", revision ) if instrument == "smmh": - location_r, _ = self._get_signal( + location_r, _ = self.mdsutils.get_signal( uid, instrument, ".geometry:location_r", revision ) - direction_r, _ = self._get_signal( + direction_r, _ = self.mdsutils.get_signal( uid, instrument, ".geometry:direction_r", revision ) location = (location + location_r) / 2.0 @@ -619,10 +631,10 @@ def _get_interferometry( location = np.array([location]) direction = np.array([direction]) - times, _ = self._get_signal(uid, instrument, ":time", revision) + times, _ = self.mdsutils.get_signal(uid, instrument, ":time", revision) for q in quantities: - qval, q_path = self._get_signal( + qval, q_path = self.mdsutils.get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q], revision ) @@ -632,7 +644,7 @@ def _get_interferometry( results[q] = qval try: - qval_err, q_path_err = self._get_signal( + qval_err, q_path_err = self.mdsutils.get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q] + "_err", @@ -645,7 +657,7 @@ def _get_interferometry( results[q + "_error" + "_records"] = q_path_err try: - qval_syserr, q_path_syserr = self._get_signal( + qval_syserr, q_path_syserr = self.mdsutils.get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q] + "_syserr", @@ -686,31 +698,31 @@ def _get_thomson_scattering( results["revision"] = self._get_revision(uid, instrument, revision) revision = results["revision"] - times, times_path = self._get_signal(uid, instrument, ":time", revision) + times, times_path = self.mdsutils.get_signal(uid, instrument, ":time", revision) print("\n Hardcoded correction to TS coordinates to be fixed in MDS+ \n") - # location, location_path = self._get_signal( + # location, location_path = self.mdsutils.get_signal( # uid, instrument, ".geometry:location", revision # ) - # direction, direction_path = self._get_signal( + # direction, direction_path = self.mdsutils.get_signal( # uid, instrument, ".geometry:direction", revision # ) - x, x_path = self._get_signal(uid, instrument, ":x", revision) - y, y_path = self._get_signal(uid, instrument, ":y", revision) - z, z_path = self._get_signal(uid, instrument, ":z", revision) - R, R_path = self._get_signal(uid, instrument, ":R", revision) + x, x_path = self.mdsutils.get_signal(uid, instrument, ":x", revision) + y, y_path = self.mdsutils.get_signal(uid, instrument, ":y", revision) + z, z_path = self.mdsutils.get_signal(uid, instrument, ":z", revision) + R, R_path = self.mdsutils.get_signal(uid, instrument, ":R", revision) z = R * 0.0 x = deepcopy(R) y = 0 for q in quantities: - qval, q_path = self._get_signal( + qval, q_path = self.mdsutils.get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q], revision, ) try: - qval_err, q_path_err = self._get_signal( + qval_err, q_path_err = self.mdsutils.get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q] + "_err", @@ -719,7 +731,7 @@ def _get_thomson_scattering( except TreeNNF: qval_err = np.full_like(qval, 0.0) - dimensions, _ = self._get_signal_dims(q_path, len(qval.shape)) + dimensions, _ = self.mdsutils.get_signal_dims(q_path, len(qval.shape)) results[q + "_records"] = q_path results[q] = qval @@ -760,17 +772,7 @@ def requires_authentication(self): # return False - def mdsCheck(self, mds_path): - """Return FAILED if node doesn't exist or other error - Return FAILED if: lenght(data)==1 and data==nan""" - - mds_path_test = ( - f"_dummy = IF_ERROR (IF ((SIZE ({mds_path})==1), " - + f'IF ({mds_path}+1>{mds_path}, {mds_path}, "FAILED"),' - + f' {mds_path}), "FAILED")' - ) - return mds_path_test def get_revision_name(self, revision) -> str: """Return string defining RUN## or BEST if revision = 0""" From b5bec58ca7789feca2af4bda330aea7d447b33f0 Mon Sep 17 00:00:00 2001 From: Jussi Hakosalo Date: Wed, 10 Apr 2024 02:39:24 +0100 Subject: [PATCH 04/11] feat: removed duplicate method --- indica/readers/mdsutils.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/indica/readers/mdsutils.py b/indica/readers/mdsutils.py index 82c216a7..6ef5aa39 100644 --- a/indica/readers/mdsutils.py +++ b/indica/readers/mdsutils.py @@ -61,13 +61,6 @@ def close(self) -> None: def requires_authentication(self) -> bool: return False - def get_mds_path_dims(self, mds_path: str, dim: int): - """Gets the dimensions' path given an mds_path""" - - dims_path = f"dim_of({mds_path},{dim})" - return dims_path - - def get_signal( self, uid: str, instrument: str, quantity: str, revision: RevisionLike ) -> Tuple[np.array, str]: From 597629cc2a0dba06a8cb5e746de28a5ba28310c5 Mon Sep 17 00:00:00 2001 From: Jussi Hakosalo Date: Wed, 10 Apr 2024 02:54:54 +0100 Subject: [PATCH 05/11] feat: pre-commit --- indica/readers/__init__.py | 7 +- indica/readers/mdsutils.py | 58 ++--- indica/readers/st40conf.py | 455 +++++++++++++++++------------------ indica/readers/st40reader.py | 84 +++---- 4 files changed, 292 insertions(+), 312 deletions(-) diff --git a/indica/readers/__init__.py b/indica/readers/__init__.py index 6574b5a7..bf0886f8 100644 --- a/indica/readers/__init__.py +++ b/indica/readers/__init__.py @@ -19,20 +19,21 @@ try: from .st40conf import ST40Conf - __all__ +=["ST40Conf"] + + __all__ += ["ST40Conf"] except ImportError as e: print(e) pass try: from .mdsutils import MDSUtils - __all__+=["MDSUtils"] + + __all__ += ["MDSUtils"] except ImportError as e: print(e) pass - try: from .st40reader import ST40Reader diff --git a/indica/readers/mdsutils.py b/indica/readers/mdsutils.py index 6ef5aa39..6ec87f11 100644 --- a/indica/readers/mdsutils.py +++ b/indica/readers/mdsutils.py @@ -1,24 +1,11 @@ -from MDSplus import Connection -from MDSplus.mdsExceptions import TreeNNF -from MDSplus.mdsExceptions import TreeNODATA - -from .abstractreader import DataReader -from .. import session - - -from copy import deepcopy -from typing import Any -from typing import Dict from typing import List -from typing import Set from typing import Tuple -from indica.abstractio import BaseIO - -from ..numpy_typing import RevisionLike - +from MDSplus import Connection import numpy as np +from indica.abstractio import BaseIO +from ..numpy_typing import RevisionLike class MDSError(Exception): @@ -36,24 +23,20 @@ class MDSWarning(UserWarning): """ -#this will be baseio class instead. what is defauly pulse? -class MDSUtils(BaseIO): - + +# this will be baseio class instead. what is defauly pulse? +class MDSUtils(BaseIO): def __init__( self, pulse, server: str = "smaug", tree: str = "ST40", - ): + ): self.tree: str = tree self.pulse: int = pulse self.conn: Connection = Connection(server) self.conn.openTree(self.tree, self.pulse) - - - - def close(self) -> None: del self.conn @@ -61,6 +44,24 @@ def close(self) -> None: def requires_authentication(self) -> bool: return False + def get_revision_name(self, revision) -> str: + """Return string defining RUN## or BEST if revision = 0""" + + if type(revision) == int: + rev_str = "" + if revision < -1: + rev_str = "" + elif revision == -1: + rev_str = ".best" + elif revision < 9: + rev_str = f".run-1{int(revision)}" + elif revision > 8: + rev_str = f".run{int(revision)}" + else: + rev_str = f".{revision}" + + return rev_str + def get_signal( self, uid: str, instrument: str, quantity: str, revision: RevisionLike ) -> Tuple[np.array, str]: @@ -74,7 +75,7 @@ def get_signal( # data = np.array(self.conn.get(path_check)) return data, path - + def get_signal_dims( self, mds_path: str, @@ -92,7 +93,6 @@ def get_signal_dims( paths.append(path) dimensions.append(np.array(dim_tmp)) return dimensions, paths - def get_signal_units( self, @@ -105,7 +105,7 @@ def get_signal_units( unit = self.conn.get(path).data() return unit - + def get_mds_path( self, uid: str, instrument: str, quantity: str, revision: RevisionLike ) -> Tuple[str, str]: @@ -130,7 +130,7 @@ def get_mds_path_dims(self, mds_path: str, dim: int): dims_path = f"dim_of({mds_path},{dim})" return dims_path - + def mdsCheck(self, mds_path): """Return FAILED if node doesn't exist or other error Return FAILED if: lenght(data)==1 and data==nan""" @@ -141,4 +141,4 @@ def mdsCheck(self, mds_path): + f' {mds_path}), "FAILED")' ) - return mds_path_test \ No newline at end of file + return mds_path_test diff --git a/indica/readers/st40conf.py b/indica/readers/st40conf.py index fea2984c..81f1f7e5 100644 --- a/indica/readers/st40conf.py +++ b/indica/readers/st40conf.py @@ -1,237 +1,236 @@ class ST40Conf: def __init__(self): - self.MACHINE_DIMS = ((0.15, 0.85), (-0.75, 0.75)) self.INSTRUMENT_METHODS = { - "efit": "get_equilibrium", - "xrcs": "get_helike_spectroscopy", - "princeton": "get_charge_exchange", - "lines": "get_diode_filters", - "nirh1": "get_interferometry", - "nirh1_bin": "get_interferometry", - "smmh1": "get_interferometry", - "smmh": "get_interferometry", - "astra": "get_astra", - "sxr_spd": "get_radiation", - "sxr_diode_1": "get_diode_filters", - "sxr_diode_2": "get_diode_filters", - "sxr_diode_3": "get_diode_filters", - "sxr_diode_4": "get_diode_filters", - "sxr_mid1": "get_radiation", - "sxr_mid2": "get_radiation", - "sxr_mid3": "get_radiation", - "sxr_mid4": "get_radiation", - "sxrc_xy1": "get_radiation", - "sxrc_xy2": "get_radiation", - "blom_xy1": "get_radiation", - "cxff_pi": "get_charge_exchange", - "cxff_tws_c": "get_charge_exchange", - "cxqf_tws_c": "get_charge_exchange", - "pi": "get_spectrometer", - "tws_c": "get_spectrometer", - "ts": "get_thomson_scattering", + "efit": "get_equilibrium", + "xrcs": "get_helike_spectroscopy", + "princeton": "get_charge_exchange", + "lines": "get_diode_filters", + "nirh1": "get_interferometry", + "nirh1_bin": "get_interferometry", + "smmh1": "get_interferometry", + "smmh": "get_interferometry", + "astra": "get_astra", + "sxr_spd": "get_radiation", + "sxr_diode_1": "get_diode_filters", + "sxr_diode_2": "get_diode_filters", + "sxr_diode_3": "get_diode_filters", + "sxr_diode_4": "get_diode_filters", + "sxr_mid1": "get_radiation", + "sxr_mid2": "get_radiation", + "sxr_mid3": "get_radiation", + "sxr_mid4": "get_radiation", + "sxrc_xy1": "get_radiation", + "sxrc_xy2": "get_radiation", + "blom_xy1": "get_radiation", + "cxff_pi": "get_charge_exchange", + "cxff_tws_c": "get_charge_exchange", + "cxqf_tws_c": "get_charge_exchange", + "pi": "get_spectrometer", + "tws_c": "get_spectrometer", + "ts": "get_thomson_scattering", } self.UIDS_MDS = { - "xrcs": "sxr", - "princeton": "spectrom", - "nirh1": "interferom", - "nirh1_bin": "interferom", - "smmh1": "interferom", - "sxr_diode_1": "sxr", - "sxr_diode_2": "sxr", - "sxr_diode_3": "sxr", - "sxr_diode_4": "sxr", -} + "xrcs": "sxr", + "princeton": "spectrom", + "nirh1": "interferom", + "nirh1_bin": "interferom", + "smmh1": "interferom", + "sxr_diode_1": "sxr", + "sxr_diode_2": "sxr", + "sxr_diode_3": "sxr", + "sxr_diode_4": "sxr", + } self.QUANTITIES_MDS = { - "efit": { - "f": ".profiles.psi_norm:f", - "faxs": ".global:faxs", - "fbnd": ".global:fbnd", - "ftor": ".profiles.psi_norm:ftor", - "rmji": ".profiles.psi_norm:rmji", - "rmjo": ".profiles.psi_norm:rmjo", - "psi": ".psi2d:psi", - "vjac": ".profiles.psi_norm:vjac", - "ajac": ".profiles.psi_norm:ajac", - "rmag": ".global:rmag", - "rgeo": ".global:rgeo", - "rbnd": ".p_boundary:rbnd", - "zmag": ".global:zmag", - "zbnd": ".p_boundary:zbnd", - "ipla": ".constraints.ip:cvalue", - "wp": ".virial:wp", - "df": ".constraints.df:cvalue", - }, - "xrcs": { - "int_k": ".te_kw:int_k", - "int_w": ".te_kw:int_w", - "int_z": ".te_kw:int_z", - "int_q": ".te_kw:int_q", - "int_r": ".te_kw:int_r", - "int_a": ".te_kw:int_a", - "int_n3": ".te_n3w:int_n3", - "int_tot": ".te_n3w:int_tot", - "te_kw": ".te_kw:te", - "te_n3w": ".te_n3w:te", - "ti_w": ".ti_w:ti", - "ti_z": ".ti_z:ti", - "ampl_w": ".ti_w:amplitude", - "spectra": ":intensity", - }, - "nirh1": { - "ne": ".line_int:ne", - }, - "nirh1_bin": { - "ne": ".line_int:ne", - }, - "smmh1": { - "ne": ".line_int:ne", - }, - "smmh": { - "ne": ".global:ne_int", - }, - "lines": { - "brightness": ":emission", - }, - "sxr_spd": { - "brightness": ".profiles:emission", - }, - "sxr_mid1": { - "brightness": ".profiles:emission", - }, - "sxr_mid2": { - "brightness": ".profiles:emission", - }, - "sxr_mid3": { - "brightness": ".profiles:emission", - }, - "sxr_mid4": { - "brightness": ".profiles:emission", - }, - "diode_arrays": { - "brightness": ".middle_head.filter_4:", - "location": ".middle_head.geometry:location", - "direction": ".middle_head.geometry:direction", - }, - "sxrc_xy1": { - "brightness": ".profiles:emission", - }, - "sxrc_xy2": { - "brightness": ".profiles:emission", - }, - "blom_xy1": { - "brightness": ".profiles:emission", - }, - "sxr_diode_1": { - "brightness": ".filter_001:signal", - }, - "sxr_diode_2": { - "brightness": ".filter_002:signal", - }, - "sxr_diode_3": { - "brightness": ".filter_003:signal", - }, - "sxr_diode_4": { - "brightness": ".filter_004:signal", - }, - "cxff_pi": { - "int": ".profiles:int", - "ti": ".profiles:ti", - "vtor": ".profiles:vtor", - "spectra": ":spectra", - "fit": ":full_fit", - }, - "cxff_tws_c": { - "int": ".profiles:int", - "ti": ".profiles:ti", - "vtor": ".profiles:vtor", - "spectra": ":spectra", - "fit": ":full_fit", - }, - "pi": { - "spectra": ":emission", - }, - "tws_c": { - "spectra": ":emission", - }, - "ts": { - "ne": ".profiles:ne", - "te": ".profiles:te", - "pe": ".profiles:pe", - "chi2": ".profiles:chi2", - }, - "astra": { - "f": ".profiles.psi_norm:fpol", - "faxs": ".global:faxs", - "fbnd": ".global:fbnd", - "ftor": ".profiles.psi_norm:ftor", # Wb - # "rmji": ".profiles.psi_norm:rmji", - # "rmjo": ".profiles.psi_norm:rmjo", - "psi_1d": ".profiles.psi_norm:psi", - "psi": ".psi2d:psi", - # "vjac": ".profiles.psi_norm:vjac", - # "ajac": ".profiles.psi_norm:ajac", - "volume": ".profiles.psi_norm:volume", - "area": ".profiles.psi_norm:areat", - "rmag": ".global:rmag", - "rgeo": ".global:rgeo", - "zmag": ".global:zmag", - "zgeo": ".global:zgeo", - "rbnd": ".p_boundary:rbnd", - "zbnd": ".p_boundary:zbnd", - "wp": ".global:wth", - "ipla": ".global:ipl", - "upl": ".global:upl", - "wth": ".global:wth", - "wtherm": ".global:wtherm", - "wfast": ".global:wfast", - "df": ".global.df", - "elon": ".profiles.astra:elon", # Elongation profile - "j_bs": ".profiles.astra:j_bs", # Bootstrap current density,MA/m2 - "j_nbi": ".profiles.astra:j_nbi", # NB driven current density,MA/m2 - "j_oh": ".profiles.astra:j_oh", # Ohmic current density,MA/m2 - "j_rf": ".profiles.astra:j_rf", # EC driven current density,MA/m2 - "j_tot": ".profiles.astra:j_tot", # Total current density,MA/m2 - "ne": ".profiles.astra:ne", # Electron density, 10^19 m^-3 - "ni": ".profiles.astra:ni", # Main ion density, 10^19 m^-3 - "nf": ".profiles.astra:nf", # Main ion density, 10^19 m^-3 - "n_d": ".profiles.astra:n_d", # Deuterium density,10E19/m3 - "n_t": ".profiles.astra:n_t", # Tritium density ,10E19/m3 - "omega_tor": ".profiles.astra:omega_tor", # Toroidal rot. freq., 1/s - "qe": ".profiles.astra:qe", # electron power flux, MW - "qi": ".profiles.astra:qi", # ion power flux, MW - "qn": ".profiles.astra:qn", # total electron flux, 10^19/s - "qnbe": ".profiles.astra:qnbe", # Beam power density to electrons, MW/m3 - "qnbi": ".profiles.astra:qnbi", # Beam power density to ions, MW/m3 - "q_oh": ".profiles.astra:q_oh", # Ohmic heating power profile, MW/m3 - "q_rf": ".profiles.astra:q_rf", # RF power density to electron,MW/m3 - "rho": ".profiles.astra:rho", # ASTRA rho-toroidal - "rmid": ".profiles.astra:rmid", # Centre of flux surfaces, m - "rminor": ".profiles.astra:rminor", # minor radius, m - "sbm": ".profiles.astra:sbm", # Particle source from beam, 10^19/m^3/s - "spel": ".profiles.astra:spel", # Particle source from pellets, 10^19/m^3/s - "stot": ".profiles.astra:stot", # Total electron source,10^19/s/m3 - "swall": ".profiles.astra:swall", # Wall neutrals source, 10^19/m^3/s - "te": ".profiles.astra:te", # Electron temperature, keV - "ti": ".profiles.astra:ti", # Ion temperature, keV - "tri": ".profiles.astra:tri", # Triangularity (up/down symmetrized) profile - "t_d": ".profiles.astra:t_d", # Deuterium temperature,keV - "t_t": ".profiles.astra:t_t", # Tritium temperature,keV - "zeff": ".profiles.astra:zeff", # Effective ion charge - "areat": ".profiles.psi_norm:areat", # Toroidal cross section,m2 - "p": ".profiles.psi_norm:p", # PRESSURE(PSI_NORM) - "pblon": ".profiles.astra:pblon", # PRESSURE(PSI_NORM) - "pbper": ".profiles.astra:pbper", # PRESSURE(PSI_NORM) - "pnb": ".global:pnb", # Injected NBI power, W - "pabs": ".global:pabs", # Absorber NBI power, W - "p_oh": ".global:p_oh", # Absorber NBI power, W - "q": ".profiles.psi_norm:q", # Q_PROFILE(PSI_NORM) - "sigmapar": ".profiles.psi_norm:sigmapar", # Paral. conduct.,1/(Ohm*m) - "nn": ".profiles.astra:nn", # Thermal neutral density, 10^19/m^3 - "niz1": ".profiles.astra:niz1", # Impurity density, 10^19/m^3 - "niz2": ".profiles.astra:niz2", # Impurity density, 10^19/m^3 - "niz3": ".profiles.astra:niz3", # Impurity density, 10^19/m^3 - } -} + "efit": { + "f": ".profiles.psi_norm:f", + "faxs": ".global:faxs", + "fbnd": ".global:fbnd", + "ftor": ".profiles.psi_norm:ftor", + "rmji": ".profiles.psi_norm:rmji", + "rmjo": ".profiles.psi_norm:rmjo", + "psi": ".psi2d:psi", + "vjac": ".profiles.psi_norm:vjac", + "ajac": ".profiles.psi_norm:ajac", + "rmag": ".global:rmag", + "rgeo": ".global:rgeo", + "rbnd": ".p_boundary:rbnd", + "zmag": ".global:zmag", + "zbnd": ".p_boundary:zbnd", + "ipla": ".constraints.ip:cvalue", + "wp": ".virial:wp", + "df": ".constraints.df:cvalue", + }, + "xrcs": { + "int_k": ".te_kw:int_k", + "int_w": ".te_kw:int_w", + "int_z": ".te_kw:int_z", + "int_q": ".te_kw:int_q", + "int_r": ".te_kw:int_r", + "int_a": ".te_kw:int_a", + "int_n3": ".te_n3w:int_n3", + "int_tot": ".te_n3w:int_tot", + "te_kw": ".te_kw:te", + "te_n3w": ".te_n3w:te", + "ti_w": ".ti_w:ti", + "ti_z": ".ti_z:ti", + "ampl_w": ".ti_w:amplitude", + "spectra": ":intensity", + }, + "nirh1": { + "ne": ".line_int:ne", + }, + "nirh1_bin": { + "ne": ".line_int:ne", + }, + "smmh1": { + "ne": ".line_int:ne", + }, + "smmh": { + "ne": ".global:ne_int", + }, + "lines": { + "brightness": ":emission", + }, + "sxr_spd": { + "brightness": ".profiles:emission", + }, + "sxr_mid1": { + "brightness": ".profiles:emission", + }, + "sxr_mid2": { + "brightness": ".profiles:emission", + }, + "sxr_mid3": { + "brightness": ".profiles:emission", + }, + "sxr_mid4": { + "brightness": ".profiles:emission", + }, + "diode_arrays": { + "brightness": ".middle_head.filter_4:", + "location": ".middle_head.geometry:location", + "direction": ".middle_head.geometry:direction", + }, + "sxrc_xy1": { + "brightness": ".profiles:emission", + }, + "sxrc_xy2": { + "brightness": ".profiles:emission", + }, + "blom_xy1": { + "brightness": ".profiles:emission", + }, + "sxr_diode_1": { + "brightness": ".filter_001:signal", + }, + "sxr_diode_2": { + "brightness": ".filter_002:signal", + }, + "sxr_diode_3": { + "brightness": ".filter_003:signal", + }, + "sxr_diode_4": { + "brightness": ".filter_004:signal", + }, + "cxff_pi": { + "int": ".profiles:int", + "ti": ".profiles:ti", + "vtor": ".profiles:vtor", + "spectra": ":spectra", + "fit": ":full_fit", + }, + "cxff_tws_c": { + "int": ".profiles:int", + "ti": ".profiles:ti", + "vtor": ".profiles:vtor", + "spectra": ":spectra", + "fit": ":full_fit", + }, + "pi": { + "spectra": ":emission", + }, + "tws_c": { + "spectra": ":emission", + }, + "ts": { + "ne": ".profiles:ne", + "te": ".profiles:te", + "pe": ".profiles:pe", + "chi2": ".profiles:chi2", + }, + "astra": { + "f": ".profiles.psi_norm:fpol", + "faxs": ".global:faxs", + "fbnd": ".global:fbnd", + "ftor": ".profiles.psi_norm:ftor", # Wb + # "rmji": ".profiles.psi_norm:rmji", + # "rmjo": ".profiles.psi_norm:rmjo", + "psi_1d": ".profiles.psi_norm:psi", + "psi": ".psi2d:psi", + # "vjac": ".profiles.psi_norm:vjac", + # "ajac": ".profiles.psi_norm:ajac", + "volume": ".profiles.psi_norm:volume", + "area": ".profiles.psi_norm:areat", + "rmag": ".global:rmag", + "rgeo": ".global:rgeo", + "zmag": ".global:zmag", + "zgeo": ".global:zgeo", + "rbnd": ".p_boundary:rbnd", + "zbnd": ".p_boundary:zbnd", + "wp": ".global:wth", + "ipla": ".global:ipl", + "upl": ".global:upl", + "wth": ".global:wth", + "wtherm": ".global:wtherm", + "wfast": ".global:wfast", + "df": ".global.df", + "elon": ".profiles.astra:elon", # Elongation profile + "j_bs": ".profiles.astra:j_bs", # Bootstrap current density,MA/m2 + "j_nbi": ".profiles.astra:j_nbi", # NB driven current density,MA/m2 + "j_oh": ".profiles.astra:j_oh", # Ohmic current density,MA/m2 + "j_rf": ".profiles.astra:j_rf", # EC driven current density,MA/m2 + "j_tot": ".profiles.astra:j_tot", # Total current density,MA/m2 + "ne": ".profiles.astra:ne", # Electron density, 10^19 m^-3 + "ni": ".profiles.astra:ni", # Main ion density, 10^19 m^-3 + "nf": ".profiles.astra:nf", # Main ion density, 10^19 m^-3 + "n_d": ".profiles.astra:n_d", # Deuterium density,10E19/m3 + "n_t": ".profiles.astra:n_t", # Tritium density ,10E19/m3 + "omega_tor": ".profiles.astra:omega_tor", # Toroidal rot. freq., 1/s + "qe": ".profiles.astra:qe", # electron power flux, MW + "qi": ".profiles.astra:qi", # ion power flux, MW + "qn": ".profiles.astra:qn", # total electron flux, 10^19/s + "qnbe": ".profiles.astra:qnbe", # Beam power density to electrons, MW/m3 + "qnbi": ".profiles.astra:qnbi", # Beam power density to ions, MW/m3 + "q_oh": ".profiles.astra:q_oh", # Ohmic heating power profile, MW/m3 + "q_rf": ".profiles.astra:q_rf", # RF power density to electron,MW/m3 + "rho": ".profiles.astra:rho", # ASTRA rho-toroidal + "rmid": ".profiles.astra:rmid", # Centre of flux surfaces, m + "rminor": ".profiles.astra:rminor", # minor radius, m + "sbm": ".profiles.astra:sbm", # Particle source from beam, 10^19/m^3/s + "spel": ".profiles.astra:spel", # Particle source from pellets, 10^19/m^3/s + "stot": ".profiles.astra:stot", # Total electron source,10^19/s/m3 + "swall": ".profiles.astra:swall", # Wall neutrals source, 10^19/m^3/s + "te": ".profiles.astra:te", # Electron temperature, keV + "ti": ".profiles.astra:ti", # Ion temperature, keV + "tri": ".profiles.astra:tri", # Triangularity (up/down symmetrized) profile + "t_d": ".profiles.astra:t_d", # Deuterium temperature,keV + "t_t": ".profiles.astra:t_t", # Tritium temperature,keV + "zeff": ".profiles.astra:zeff", # Effective ion charge + "areat": ".profiles.psi_norm:areat", # Toroidal cross section,m2 + "p": ".profiles.psi_norm:p", # PRESSURE(PSI_NORM) + "pblon": ".profiles.astra:pblon", # PRESSURE(PSI_NORM) + "pbper": ".profiles.astra:pbper", # PRESSURE(PSI_NORM) + "pnb": ".global:pnb", # Injected NBI power, W + "pabs": ".global:pabs", # Absorber NBI power, W + "p_oh": ".global:p_oh", # Absorber NBI power, W + "q": ".profiles.psi_norm:q", # Q_PROFILE(PSI_NORM) + "sigmapar": ".profiles.psi_norm:sigmapar", # Paral. conduct.,1/(Ohm*m) + "nn": ".profiles.astra:nn", # Thermal neutral density, 10^19/m^3 + "niz1": ".profiles.astra:niz1", # Impurity density, 10^19/m^3 + "niz2": ".profiles.astra:niz2", # Impurity density, 10^19/m^3 + "niz3": ".profiles.astra:niz3", # Impurity density, 10^19/m^3 + }, + } diff --git a/indica/readers/st40reader.py b/indica/readers/st40reader.py index 430ee018..f65b0909 100644 --- a/indica/readers/st40reader.py +++ b/indica/readers/st40reader.py @@ -9,18 +9,13 @@ from typing import Set from typing import Tuple - - -from .st40conf import ST40Conf - -from .mdsutils import MDSUtils - -from MDSplus import Connection from MDSplus.mdsExceptions import TreeNNF from MDSplus.mdsExceptions import TreeNODATA import numpy as np from .abstractreader import DataReader +from .mdsutils import MDSUtils +from .st40conf import ST40Conf from .. import session from ..numpy_typing import RevisionLike @@ -59,7 +54,6 @@ class ST40Reader(DataReader): """ - def __init__( self, pulse: int, @@ -83,18 +77,14 @@ def __init__( self.pulse: int = pulse self._default_error = default_error - self.mdsutils=MDSUtils(server,tree,pulse) - + self.mdsutils = MDSUtils(pulse, server, tree) - #ST40 configurations. ACtually should modify the code not to set as self.. + # ST40 configurations. ACtually should modify the code not to set as self.. self.st40conf = ST40Conf() - self.MACHINE_DIMS=self.st40conf.MACHINE_DIMS - self.INSTRUMENT_METHODS=self.st40conf.INSTRUMENT_METHODS - self.UIDS_MDS=self.st40conf.UIDS_MDS - self.QUANTITIES_MDS=self.st40conf.QUANTITIES_MDS - - - + self.MACHINE_DIMS = self.st40conf.MACHINE_DIMS + self.INSTRUMENT_METHODS = self.st40conf.INSTRUMENT_METHODS + self.UIDS_MDS = self.st40conf.UIDS_MDS + self.QUANTITIES_MDS = self.st40conf.QUANTITIES_MDS def _get_data( self, uid: str, instrument: str, quantity: str, revision: RevisionLike @@ -106,9 +96,7 @@ def _get_data( unit = self.mdsutils.get_signal_units(_path) return data, dims, unit, _path - - def _get_revision( self, uid: str, instrument: str, revision: RevisionLike ) -> RevisionLike: @@ -119,7 +107,9 @@ def _get_revision( return revision if revision == 0: - run_name, _ = self.mdsutils.get_signal(uid, instrument, ":best_run", revision) + run_name, _ = self.mdsutils.get_signal( + uid, instrument, ":best_run", revision + ) return run_name return revision @@ -217,7 +207,9 @@ def _get_astra( results["psi_z"], _ = self.mdsutils.get_signal( uid, instrument, ".psi2d:zgrid", revision ) - results["times"], t_path = self.mdsutils.get_signal(uid, instrument, ":time", revision) + results["times"], t_path = self.mdsutils.get_signal( + uid, instrument, ":time", revision + ) for q in quantities: qval, q_path = self.mdsutils.get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q], revision @@ -261,7 +253,7 @@ def _get_radiation( ) quantity = "brightness" - times, times_path = self.mdsutils.get_signal( + time, times_path = self.mdsutils.get_signal( uid, instrument, ":time", @@ -321,8 +313,12 @@ def _get_helike_spectroscopy( location = np.array([location]) direction = np.array([direction]) - results["times"], _ = self.mdsutils.get_signal(uid, instrument, ":time", revision) - wavelength, _ = self.mdsutils.get_signal(uid, instrument, ":wavelength", revision) + results["times"], _ = self.mdsutils.get_signal( + uid, instrument, ":time", revision + ) + wavelength, _ = self.mdsutils.get_signal( + uid, instrument, ":wavelength", revision + ) # TODO: change once wavelength in MDS+ has been fixed to nanometers! wavelength /= 10.0 if self.pulse >= 10307: @@ -376,10 +372,14 @@ def _get_charge_exchange( results["revision"] = self._get_revision(uid, instrument, revision) revision = results["revision"] - texp, texp_path = self.mdsutils.get_signal(uid, instrument, ":exposure", revision) - times, _ = self.mdsutils.get_signal(uid, instrument, ":time", revision) + texp, texp_path = self.mdsutils.get_signal( + uid, instrument, ":exposure", revision + ) + time, _ = self.mdsutils.get_signal(uid, instrument, ":time", revision) try: - wavelength, _ = self.mdsutils.get_signal(uid, instrument, ":wavelen", revision) + wavelength, _ = self.mdsutils.get_signal( + uid, instrument, ":wavelen", revision + ) except TreeNODATA: wavelength = None @@ -510,7 +510,7 @@ def _get_spectrometer( results[f"{q}_error"] = qval_err results["length"] = location[:, 0].size - results["t"] = time + results["t"] = times # TODO: check whether wlength should be channel agnostic or not... if wavelength is not None: results["wavelength"] = wavelength[0, :] @@ -565,7 +565,7 @@ def _get_diode_filters( else: labels = _labels - results["t"] = time + results["t"] = times results["labels"] = labels results[quantity + "_records"] = q_path results[quantity] = qval @@ -636,7 +636,7 @@ def _get_interferometry( ) if "t" not in results: - results["t"] = time + results["t"] = times results[q + "_records"] = q_path results[q] = qval @@ -739,7 +739,7 @@ def _get_thomson_scattering( results["y"] = y results["z"] = z results["R"] = R - results["t"] = time + results["t"] = times results["element"] = "" # results["location"] = location # results["direction"] = direction @@ -769,26 +769,6 @@ def requires_authentication(self): # return False - - - def get_revision_name(self, revision) -> str: - """Return string defining RUN## or BEST if revision = 0""" - - if type(revision) == int: - rev_str = "" - if revision < 0: - rev_str = "" - elif revision == 0: - rev_str = ".best" - elif revision < 10: - rev_str = f".run0{int(revision)}" - elif revision > 9: - rev_str = f".run{int(revision)}" - else: - rev_str = f".{revision}" - - return rev_str - def get_los(self, position, direction): """ Return start and stop (x, y, z) of line-of-sight given position and direction From a5aedb26da6ae402710e22cf58097d2d5c64d1dc Mon Sep 17 00:00:00 2001 From: Marco Sertoli Date: Wed, 10 Apr 2024 11:22:39 +0100 Subject: [PATCH 06/11] Deleted useless UIDS_MDS (will be completely scrapped soon) and simplified comments to ASTRA (that anyway has to be fixed) --- indica/readers/st40conf.py | 102 +++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 55 deletions(-) diff --git a/indica/readers/st40conf.py b/indica/readers/st40conf.py index 81f1f7e5..1ba83d11 100644 --- a/indica/readers/st40conf.py +++ b/indica/readers/st40conf.py @@ -1,3 +1,7 @@ +# TODO: implement test to check availability of instruments methods and +# quantities have corresponding DATATYPE + + class ST40Conf: def __init__(self): @@ -34,14 +38,6 @@ def __init__(self): self.UIDS_MDS = { "xrcs": "sxr", - "princeton": "spectrom", - "nirh1": "interferom", - "nirh1_bin": "interferom", - "smmh1": "interferom", - "sxr_diode_1": "sxr", - "sxr_diode_2": "sxr", - "sxr_diode_3": "sxr", - "sxr_diode_4": "sxr", } self.QUANTITIES_MDS = { "efit": { @@ -165,13 +161,9 @@ def __init__(self): "f": ".profiles.psi_norm:fpol", "faxs": ".global:faxs", "fbnd": ".global:fbnd", - "ftor": ".profiles.psi_norm:ftor", # Wb - # "rmji": ".profiles.psi_norm:rmji", - # "rmjo": ".profiles.psi_norm:rmjo", + "ftor": ".profiles.psi_norm:ftor", "psi_1d": ".profiles.psi_norm:psi", "psi": ".psi2d:psi", - # "vjac": ".profiles.psi_norm:vjac", - # "ajac": ".profiles.psi_norm:ajac", "volume": ".profiles.psi_norm:volume", "area": ".profiles.psi_norm:areat", "rmag": ".global:rmag", @@ -187,50 +179,50 @@ def __init__(self): "wtherm": ".global:wtherm", "wfast": ".global:wfast", "df": ".global.df", - "elon": ".profiles.astra:elon", # Elongation profile - "j_bs": ".profiles.astra:j_bs", # Bootstrap current density,MA/m2 - "j_nbi": ".profiles.astra:j_nbi", # NB driven current density,MA/m2 - "j_oh": ".profiles.astra:j_oh", # Ohmic current density,MA/m2 - "j_rf": ".profiles.astra:j_rf", # EC driven current density,MA/m2 - "j_tot": ".profiles.astra:j_tot", # Total current density,MA/m2 - "ne": ".profiles.astra:ne", # Electron density, 10^19 m^-3 - "ni": ".profiles.astra:ni", # Main ion density, 10^19 m^-3 - "nf": ".profiles.astra:nf", # Main ion density, 10^19 m^-3 - "n_d": ".profiles.astra:n_d", # Deuterium density,10E19/m3 - "n_t": ".profiles.astra:n_t", # Tritium density ,10E19/m3 - "omega_tor": ".profiles.astra:omega_tor", # Toroidal rot. freq., 1/s - "qe": ".profiles.astra:qe", # electron power flux, MW - "qi": ".profiles.astra:qi", # ion power flux, MW - "qn": ".profiles.astra:qn", # total electron flux, 10^19/s - "qnbe": ".profiles.astra:qnbe", # Beam power density to electrons, MW/m3 - "qnbi": ".profiles.astra:qnbi", # Beam power density to ions, MW/m3 - "q_oh": ".profiles.astra:q_oh", # Ohmic heating power profile, MW/m3 - "q_rf": ".profiles.astra:q_rf", # RF power density to electron,MW/m3 + "elon": ".profiles.astra:elon", # + "j_bs": ".profiles.astra:j_bs", # MA/m2 + "j_nbi": ".profiles.astra:j_nbi", # MA/m2 + "j_oh": ".profiles.astra:j_oh", # MA/m2 + "j_rf": ".profiles.astra:j_rf", # MA/m2 + "j_tot": ".profiles.astra:j_tot", # MA/m2 + "ne": ".profiles.astra:ne", # 10^19 m^-3 + "ni": ".profiles.astra:ni", # 10^19 m^-3 + "nf": ".profiles.astra:nf", # 10^19 m^-3 + "n_d": ".profiles.astra:n_d", # 10E19/m3 + "n_t": ".profiles.astra:n_t", # 10E19/m3 + "omega_tor": ".profiles.astra:omega_tor", # 1/s + "qe": ".profiles.astra:qe", # MW + "qi": ".profiles.astra:qi", # MW + "qn": ".profiles.astra:qn", # 10^19/s + "qnbe": ".profiles.astra:qnbe", # MW/m3 + "qnbi": ".profiles.astra:qnbi", # MW/m3 + "q_oh": ".profiles.astra:q_oh", # MW/m3 + "q_rf": ".profiles.astra:q_rf", # MW/m3 "rho": ".profiles.astra:rho", # ASTRA rho-toroidal "rmid": ".profiles.astra:rmid", # Centre of flux surfaces, m "rminor": ".profiles.astra:rminor", # minor radius, m - "sbm": ".profiles.astra:sbm", # Particle source from beam, 10^19/m^3/s - "spel": ".profiles.astra:spel", # Particle source from pellets, 10^19/m^3/s - "stot": ".profiles.astra:stot", # Total electron source,10^19/s/m3 - "swall": ".profiles.astra:swall", # Wall neutrals source, 10^19/m^3/s - "te": ".profiles.astra:te", # Electron temperature, keV - "ti": ".profiles.astra:ti", # Ion temperature, keV - "tri": ".profiles.astra:tri", # Triangularity (up/down symmetrized) profile - "t_d": ".profiles.astra:t_d", # Deuterium temperature,keV - "t_t": ".profiles.astra:t_t", # Tritium temperature,keV - "zeff": ".profiles.astra:zeff", # Effective ion charge - "areat": ".profiles.psi_norm:areat", # Toroidal cross section,m2 - "p": ".profiles.psi_norm:p", # PRESSURE(PSI_NORM) - "pblon": ".profiles.astra:pblon", # PRESSURE(PSI_NORM) - "pbper": ".profiles.astra:pbper", # PRESSURE(PSI_NORM) - "pnb": ".global:pnb", # Injected NBI power, W - "pabs": ".global:pabs", # Absorber NBI power, W - "p_oh": ".global:p_oh", # Absorber NBI power, W - "q": ".profiles.psi_norm:q", # Q_PROFILE(PSI_NORM) - "sigmapar": ".profiles.psi_norm:sigmapar", # Paral. conduct.,1/(Ohm*m) - "nn": ".profiles.astra:nn", # Thermal neutral density, 10^19/m^3 - "niz1": ".profiles.astra:niz1", # Impurity density, 10^19/m^3 - "niz2": ".profiles.astra:niz2", # Impurity density, 10^19/m^3 - "niz3": ".profiles.astra:niz3", # Impurity density, 10^19/m^3 + "sbm": ".profiles.astra:sbm", # 10^19/m^3/s + "spel": ".profiles.astra:spel", # 10^19/m^3/s + "stot": ".profiles.astra:stot", # 10^19/s/m3 + "swall": ".profiles.astra:swall", # 10^19/m^3/s + "te": ".profiles.astra:te", # keV + "ti": ".profiles.astra:ti", # keV + "tri": ".profiles.astra:tri", # Triangularity (up/down symmetrized) + "t_d": ".profiles.astra:t_d", # keV + "t_t": ".profiles.astra:t_t", # keV + "zeff": ".profiles.astra:zeff", + "areat": ".profiles.psi_norm:areat", # Toroidal cross section, m2 + "p": ".profiles.psi_norm:p", + "pblon": ".profiles.astra:pblon", + "pbper": ".profiles.astra:pbper", + "pnb": ".global:pnb", # W + "pabs": ".global:pabs", # W + "p_oh": ".global:p_oh", # W + "q": ".profiles.psi_norm:q", + "sigmapar": ".profiles.psi_norm:sigmapar", # 1/(Ohm*m) + "nn": ".profiles.astra:nn", # 10^19/m^3 + "niz1": ".profiles.astra:niz1", # 10^19/m^3 + "niz2": ".profiles.astra:niz2", # 10^19/m^3 + "niz3": ".profiles.astra:niz3", # 10^19/m^3 }, } From 2afbb7b940233ee16ef4b26d008a895b14c6f1c5 Mon Sep 17 00:00:00 2001 From: Marco Sertoli Date: Wed, 10 Apr 2024 11:47:23 +0100 Subject: [PATCH 07/11] Fixed missing var-name change times -> t --- indica/readers/st40reader.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/indica/readers/st40reader.py b/indica/readers/st40reader.py index f65b0909..9394b240 100644 --- a/indica/readers/st40reader.py +++ b/indica/readers/st40reader.py @@ -130,7 +130,7 @@ def _get_equilibrium( results["revision"] = self._get_revision(uid, instrument, revision) revision = results["revision"] times, _ = self.mdsutils.get_signal(uid, instrument, ":time", revision) - results["times"] = times + results["t"] = times results["psin"], results["psin_records"] = self.mdsutils.get_signal( uid, instrument, ".profiles.psi_norm:xpsn", revision ) @@ -207,7 +207,7 @@ def _get_astra( results["psi_z"], _ = self.mdsutils.get_signal( uid, instrument, ".psi2d:zgrid", revision ) - results["times"], t_path = self.mdsutils.get_signal( + results["t"], t_path = self.mdsutils.get_signal( uid, instrument, ":time", revision ) for q in quantities: @@ -313,9 +313,7 @@ def _get_helike_spectroscopy( location = np.array([location]) direction = np.array([direction]) - results["times"], _ = self.mdsutils.get_signal( - uid, instrument, ":time", revision - ) + results["t"], _ = self.mdsutils.get_signal(uid, instrument, ":time", revision) wavelength, _ = self.mdsutils.get_signal( uid, instrument, ":wavelength", revision ) From d062aadf77d1af02c5dd5b373add17ccab98dd48 Mon Sep 17 00:00:00 2001 From: Marco Sertoli Date: Wed, 10 Apr 2024 11:49:00 +0100 Subject: [PATCH 08/11] Fixed revision # defaults: if is int then RUN## (starting with 01); if ==0 then BEST. --- indica/readers/mdsutils.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/indica/readers/mdsutils.py b/indica/readers/mdsutils.py index 6ec87f11..498ead0d 100644 --- a/indica/readers/mdsutils.py +++ b/indica/readers/mdsutils.py @@ -44,19 +44,19 @@ def close(self) -> None: def requires_authentication(self) -> bool: return False - def get_revision_name(self, revision) -> str: + def get_revision_name(self, revision: RevisionLike) -> str: """Return string defining RUN## or BEST if revision = 0""" if type(revision) == int: - rev_str = "" - if revision < -1: + _revision = int(revision) + if _revision < 0: rev_str = "" - elif revision == -1: + elif _revision == 0: rev_str = ".best" - elif revision < 9: - rev_str = f".run-1{int(revision)}" - elif revision > 8: - rev_str = f".run{int(revision)}" + elif _revision < 10: + rev_str = f".run0{int(_revision)}" + else: + rev_str = f".run{int(_revision)}" else: rev_str = f".{revision}" From c65e616e619ce2b1399cfa15211f49e8d60a924a Mon Sep 17 00:00:00 2001 From: Marco Sertoli Date: Wed, 10 Apr 2024 11:49:24 +0100 Subject: [PATCH 09/11] Fixed PSIN coordinate in equilibrium class --- indica/equilibrium.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indica/equilibrium.py b/indica/equilibrium.py index 40169a08..cecd5299 100644 --- a/indica/equilibrium.py +++ b/indica/equilibrium.py @@ -91,8 +91,8 @@ def __init__( self.rho = rho self.t = self.rho.t if "vjac" in equilibrium_data and "ajac" in equilibrium_data: - self.psin = equilibrium_data["psin"] - dpsin = self.psin[1] - self.psin[0] + psin = equilibrium_data["vjac"].rho_poloidal ** 2 + dpsin = psin[1] - psin[0] self.volume = (equilibrium_data["vjac"] * dpsin).cumsum("rho_poloidal") self.area = (equilibrium_data["ajac"] * dpsin).cumsum("rho_poloidal") elif "volume" in equilibrium_data and "area" in equilibrium_data: From e5f304a6c8a493bb78ace603707a38a371e6f380 Mon Sep 17 00:00:00 2001 From: Marco Sertoli Date: Fri, 12 Apr 2024 16:50:50 +0100 Subject: [PATCH 10/11] Deleted unused method and tidied up revision methods so no can be directly called in st40reader.py. --- indica/readers/mdsutils.py | 67 ++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 28 deletions(-) diff --git a/indica/readers/mdsutils.py b/indica/readers/mdsutils.py index 498ead0d..05a129d0 100644 --- a/indica/readers/mdsutils.py +++ b/indica/readers/mdsutils.py @@ -44,24 +44,6 @@ def close(self) -> None: def requires_authentication(self) -> bool: return False - def get_revision_name(self, revision: RevisionLike) -> str: - """Return string defining RUN## or BEST if revision = 0""" - - if type(revision) == int: - _revision = int(revision) - if _revision < 0: - rev_str = "" - elif _revision == 0: - rev_str = ".best" - elif _revision < 10: - rev_str = f".run0{int(_revision)}" - else: - rev_str = f".run{int(_revision)}" - else: - rev_str = f".{revision}" - - return rev_str - def get_signal( self, uid: str, instrument: str, quantity: str, revision: RevisionLike ) -> Tuple[np.array, str]: @@ -72,7 +54,6 @@ def get_signal( data = str(self.conn.get(path)) else: data = np.array(self.conn.get(path)) - # data = np.array(self.conn.get(path_check)) return data, path @@ -88,7 +69,7 @@ def get_signal_dims( paths = [] for dim in range(ndims): path = f"dim_of({mds_path},{dim})" - dim_tmp = self.conn.get(self.mdsCheck(path)).data() + dim_tmp = self.conn.get(path).data() paths.append(path) dimensions.append(np.array(dim_tmp)) @@ -106,6 +87,42 @@ def get_signal_units( return unit + def get_data( + self, uid: str, instrument: str, quantity: str, revision: RevisionLike + ) -> Tuple[np.array, List[np.array], str, str]: + """Gets the signal and its coordinates for the given INSTRUMENT, at the + given revision.""" + data, _path = self.get_signal(uid, instrument, quantity, revision) + dims, _ = self.get_signal_dims(_path, len(data.shape)) + unit = self.get_signal_units(_path) + + return data, dims, unit, _path + + def revision_name(self, revision: RevisionLike) -> str: + """Return string defining RUN## or BEST if revision = 0""" + + if type(revision) == int: + _revision = int(revision) + if _revision < 0: + rev_str = "" + elif _revision == 0: + rev_str = "best" + elif _revision < 10: + rev_str = f"run0{int(_revision)}" + else: + rev_str = f"run{int(_revision)}" + else: + rev_str = f"{revision}" + + return rev_str.upper() + + def get_best_revision(self, uid: str, instrument: str): + """ + Return revision name to which BEST is pointing to + """ + best_revision, _ = self.get_signal(uid, instrument, ".best_run", "best") + return best_revision + def get_mds_path( self, uid: str, instrument: str, quantity: str, revision: RevisionLike ) -> Tuple[str, str]: @@ -116,21 +133,15 @@ def get_mds_path( quantity: e.g. ".global:cr0" # minor radius revision: if 0 --> looks for "best", else "run##" """ - revision_name = self.get_revision_name(revision) + revision_name = self.revision_name(revision) mds_path = "" if len(uid) > 0: mds_path += f".{uid}".upper() if len(instrument) > 0 and instrument.upper() != self.tree.upper(): mds_path += f".{instrument}".upper() - mds_path += f"{revision_name}{quantity}".upper() + mds_path += f".{revision_name}{quantity}".upper() return mds_path, self.mdsCheck(mds_path) - def get_mds_path_dims(self, mds_path: str, dim: int): - """Gets the dimensions' path given an mds_path""" - - dims_path = f"dim_of({mds_path},{dim})" - return dims_path - def mdsCheck(self, mds_path): """Return FAILED if node doesn't exist or other error Return FAILED if: lenght(data)==1 and data==nan""" From d6873a9113d7b732737333757b172daef6ca3ac6 Mon Sep 17 00:00:00 2001 From: Marco Sertoli Date: Fri, 12 Apr 2024 16:51:41 +0100 Subject: [PATCH 11/11] Moved get_data method to mdsutils, reading now all done through that, no other methods needed in st40reader.py. --- indica/readers/st40reader.py | 194 +++++++++++++++-------------------- 1 file changed, 81 insertions(+), 113 deletions(-) diff --git a/indica/readers/st40reader.py b/indica/readers/st40reader.py index 9394b240..4cadf029 100644 --- a/indica/readers/st40reader.py +++ b/indica/readers/st40reader.py @@ -5,7 +5,6 @@ from typing import Any from typing import Dict -from typing import List from typing import Set from typing import Tuple @@ -86,33 +85,10 @@ def __init__( self.UIDS_MDS = self.st40conf.UIDS_MDS self.QUANTITIES_MDS = self.st40conf.QUANTITIES_MDS - def _get_data( - self, uid: str, instrument: str, quantity: str, revision: RevisionLike - ) -> Tuple[np.array, List[np.array], str, str]: - """Gets the signal and its coordinates for the given INSTRUMENT, at the - given revision.""" - data, _path = self.mdsutils.get_signal(uid, instrument, quantity, revision) - dims, _ = self.mdsutils.get_signal_dims(_path, len(data.shape)) - unit = self.mdsutils.get_signal_units(_path) - - return data, dims, unit, _path - - def _get_revision( - self, uid: str, instrument: str, revision: RevisionLike - ) -> RevisionLike: - """ - Gets the effective revision name if latest/best is given in input - """ - if type(revision) == str: - return revision - - if revision == 0: - run_name, _ = self.mdsutils.get_signal( - uid, instrument, ":best_run", revision - ) - return run_name - - return revision + self._get_signal = self.mdsutils.get_signal + self._get_signal_dims = self.mdsutils.get_signal_dims + self._get_data = self.mdsutils.get_data + self._get_revision = self.mdsutils.get_best_revision def _get_equilibrium( self, @@ -127,24 +103,24 @@ def _get_equilibrium( uid = self.UIDS_MDS[instrument] results: Dict[str, Any] = {} - results["revision"] = self._get_revision(uid, instrument, revision) + results["revision"] = self._get_revision(uid, instrument) revision = results["revision"] - times, _ = self.mdsutils.get_signal(uid, instrument, ":time", revision) + times, _ = self._get_signal(uid, instrument, ":time", revision) results["t"] = times - results["psin"], results["psin_records"] = self.mdsutils.get_signal( + results["psin"], results["psin_records"] = self._get_signal( uid, instrument, ".profiles.psi_norm:xpsn", revision ) - results["psi_r"], results["psi_r_records"] = self.mdsutils.get_signal( + results["psi_r"], results["psi_r_records"] = self._get_signal( uid, instrument, ".psi2d:rgrid", revision ) - results["psi_z"], results["psi_z_records"] = self.mdsutils.get_signal( + results["psi_z"], results["psi_z_records"] = self._get_signal( uid, instrument, ".psi2d:zgrid", revision ) for q in quantities: if q not in self.QUANTITIES_MDS[instrument].keys(): continue try: - qval, q_path = self.mdsutils.get_signal( + qval, q_path = self._get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q], revision ) except TreeNNF: @@ -182,36 +158,34 @@ def _get_astra( uid = self.UIDS_MDS[instrument] results: Dict[str, Any] = {} - results["revision"] = self._get_revision(uid, instrument, revision) + results["revision"] = self._get_revision(uid, instrument) revision = results["revision"] # Read time and radial dimensions - results["boundary_index"], _ = self.mdsutils.get_signal( + results["boundary_index"], _ = self._get_signal( uid, instrument, ".p_boundary:index", revision ) - results["psi"], _ = self.mdsutils.get_signal( + results["psi"], _ = self._get_signal( uid, instrument, ".profiles.psi_norm:psi", revision ) - results["psin"], psin_path = self.mdsutils.get_signal( + results["psin"], psin_path = self._get_signal( uid, instrument, ".profiles.psi_norm:xpsn", revision ) - results["ftor"], _ = self.mdsutils.get_signal( + results["ftor"], _ = self._get_signal( uid, instrument, ".profiles.psi_norm:ftor", revision ) - results["rho"], rho_path = self.mdsutils.get_signal( + results["rho"], rho_path = self._get_signal( uid, instrument, ".profiles.astra:rho", revision ) - results["psi_r"], _ = self.mdsutils.get_signal( + results["psi_r"], _ = self._get_signal( uid, instrument, ".psi2d:rgrid", revision ) - results["psi_z"], _ = self.mdsutils.get_signal( + results["psi_z"], _ = self._get_signal( uid, instrument, ".psi2d:zgrid", revision ) - results["t"], t_path = self.mdsutils.get_signal( - uid, instrument, ":time", revision - ) + results["t"], t_path = self._get_signal(uid, instrument, ":time", revision) for q in quantities: - qval, q_path = self.mdsutils.get_signal( + qval, q_path = self._get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q], revision ) @@ -242,30 +216,30 @@ def _get_radiation( "machine_dims": self.MACHINE_DIMS, } - results["revision"] = self._get_revision(uid, instrument, revision) + results["revision"] = self._get_revision(uid, instrument) revision = results["revision"] - location, location_path = self.mdsutils.get_signal( + location, location_path = self._get_signal( uid, instrument, ".geometry:location", revision ) - direction, direction_path = self.mdsutils.get_signal( + direction, direction_path = self._get_signal( uid, instrument, ".geometry:direction", revision ) quantity = "brightness" - time, times_path = self.mdsutils.get_signal( + time, times_path = self._get_signal( uid, instrument, ":time", revision, ) - qval, qval_record = self.mdsutils.get_signal( + qval, qval_record = self._get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][quantity], revision, ) - qerr, qerr_record = self.mdsutils.get_signal( + qerr, qerr_record = self._get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][quantity] + "_err", @@ -300,23 +274,21 @@ def _get_helike_spectroscopy( "machine_dims": self.MACHINE_DIMS, } - results["revision"] = self._get_revision(uid, instrument, revision) + results["revision"] = self._get_revision(uid, instrument) revision = results["revision"] - location, location_path = self.mdsutils.get_signal( + location, location_path = self._get_signal( uid, instrument, ".geometry:location", revision ) - direction, direction_path = self.mdsutils.get_signal( + direction, direction_path = self._get_signal( uid, instrument, ".geometry:direction", revision ) if len(np.shape(location)) == 1: location = np.array([location]) direction = np.array([direction]) - results["t"], _ = self.mdsutils.get_signal(uid, instrument, ":time", revision) - wavelength, _ = self.mdsutils.get_signal( - uid, instrument, ":wavelength", revision - ) + results["t"], _ = self._get_signal(uid, instrument, ":time", revision) + wavelength, _ = self._get_signal(uid, instrument, ":wavelength", revision) # TODO: change once wavelength in MDS+ has been fixed to nanometers! wavelength /= 10.0 if self.pulse >= 10307: @@ -325,14 +297,14 @@ def _get_helike_spectroscopy( results["wavelength"] = wavelength for q in quantities: - qval, q_path = self.mdsutils.get_signal( + qval, q_path = self._get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q], revision ) results[q + "_records"] = q_path results[q] = qval try: - qval_err, q_path_err = self.mdsutils.get_signal( + qval_err, q_path_err = self._get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q] + "_err", @@ -367,31 +339,27 @@ def _get_charge_exchange( "machine_dims": self.MACHINE_DIMS, } - results["revision"] = self._get_revision(uid, instrument, revision) + results["revision"] = self._get_revision(uid, instrument) revision = results["revision"] - texp, texp_path = self.mdsutils.get_signal( - uid, instrument, ":exposure", revision - ) - time, _ = self.mdsutils.get_signal(uid, instrument, ":time", revision) + texp, texp_path = self._get_signal(uid, instrument, ":exposure", revision) + time, _ = self._get_signal(uid, instrument, ":time", revision) try: - wavelength, _ = self.mdsutils.get_signal( - uid, instrument, ":wavelen", revision - ) + wavelength, _ = self._get_signal(uid, instrument, ":wavelen", revision) except TreeNODATA: wavelength = None - x, x_path = self.mdsutils.get_signal(uid, instrument, ":x", revision) - y, y_path = self.mdsutils.get_signal(uid, instrument, ":y", revision) - z, z_path = self.mdsutils.get_signal(uid, instrument, ":z", revision) - R, R_path = self.mdsutils.get_signal(uid, instrument, ":R", revision) + x, x_path = self._get_signal(uid, instrument, ":x", revision) + y, y_path = self._get_signal(uid, instrument, ":y", revision) + z, z_path = self._get_signal(uid, instrument, ":z", revision) + R, R_path = self._get_signal(uid, instrument, ":R", revision) # TODO: temporary fix until geometry sorted (especially pulse if statement..) try: - location, location_path = self.mdsutils.get_signal( + location, location_path = self._get_signal( uid, instrument, ".geometry:location", revision ) - direction, direction_path = self.mdsutils.get_signal( + direction, direction_path = self._get_signal( uid, instrument, ".geometry:direction", revision ) if len(np.shape(location)) == 1: @@ -411,7 +379,7 @@ def _get_charge_exchange( for q in quantities: try: - qval, q_path = self.mdsutils.get_signal( + qval, q_path = self._get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q], @@ -421,7 +389,7 @@ def _get_charge_exchange( continue try: - qval_err, q_path_err = self.mdsutils.get_signal( + qval_err, q_path_err = self._get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q] + "_err", @@ -430,7 +398,7 @@ def _get_charge_exchange( except TreeNNF: qval_err = np.full_like(qval, 0.0) - dimensions, _ = self.mdsutils.get_signal_dims(q_path, len(qval.shape)) + dimensions, _ = self._get_signal_dims(q_path, len(qval.shape)) results[q + "_records"] = q_path results[q] = qval results[f"{q}_error"] = qval_err @@ -467,16 +435,16 @@ def _get_spectrometer( "machine_dims": self.MACHINE_DIMS, } - results["revision"] = self._get_revision(uid, instrument, revision) + results["revision"] = self._get_revision(uid, instrument) revision = results["revision"] - times, _ = self.mdsutils.get_signal(uid, instrument, ":time", revision) - wavelength, _ = self.mdsutils.get_signal(uid, instrument, ":wavelen", revision) + times, _ = self._get_signal(uid, instrument, ":time", revision) + wavelength, _ = self._get_signal(uid, instrument, ":wavelen", revision) - location, location_path = self.mdsutils.get_signal( + location, location_path = self._get_signal( uid, instrument, ".geometry:location", revision ) - direction, direction_path = self.mdsutils.get_signal( + direction, direction_path = self._get_signal( uid, instrument, ".geometry:direction", revision ) if len(np.shape(location)) == 1: @@ -484,7 +452,7 @@ def _get_spectrometer( direction = np.array([direction]) for q in quantities: - qval, q_path = self.mdsutils.get_signal( + qval, q_path = self._get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q], @@ -492,7 +460,7 @@ def _get_spectrometer( ) try: - qval_err, q_path_err = self.mdsutils.get_signal( + qval_err, q_path_err = self._get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q] + "_err", @@ -501,7 +469,7 @@ def _get_spectrometer( except TreeNNF: qval_err = np.full_like(qval, 0.0) - dimensions, _ = self.mdsutils.get_signal_dims(q_path, len(qval.shape)) + dimensions, _ = self._get_signal_dims(q_path, len(qval.shape)) results[q + "_records"] = q_path results[q] = qval @@ -530,10 +498,10 @@ def _get_diode_filters( if len(uid) == 0 and instrument in self.UIDS_MDS: uid = self.UIDS_MDS[instrument] - location, location_path = self.mdsutils.get_signal( + location, location_path = self._get_signal( uid, instrument, ".geometry:location", revision ) - direction, position_path = self.mdsutils.get_signal( + direction, position_path = self._get_signal( uid, instrument, ".geometry:direction", revision ) if len(np.shape(location)) == 1: @@ -548,16 +516,16 @@ def _get_diode_filters( } results["location"] = location results["direction"] = direction - results["revision"] = self._get_revision(uid, instrument, revision) + results["revision"] = self._get_revision(uid, instrument) results["revision"] = revision revision = results["revision"] quantity = "brightness" - qval, q_path = self.mdsutils.get_signal( + qval, q_path = self._get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][quantity], revision ) - times, _ = self.mdsutils.get_signal(uid, instrument, ":time", revision) - _labels, _ = self.mdsutils.get_signal(uid, instrument, ":label", revision) + times, _ = self._get_signal(uid, instrument, ":time", revision) + _labels, _ = self._get_signal(uid, instrument, ":label", revision) if type(_labels[0]) == np.bytes_: labels = np.array([label.decode("UTF-8") for label in _labels]) else: @@ -568,7 +536,7 @@ def _get_diode_filters( results[quantity + "_records"] = q_path results[quantity] = qval try: - qval_err, q_path_err = self.mdsutils.get_signal( + qval_err, q_path_err = self._get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][quantity] + "_ERR", @@ -602,21 +570,21 @@ def _get_interferometry( "machine_dims": self.MACHINE_DIMS, } - results["revision"] = self._get_revision(uid, instrument, revision) + results["revision"] = self._get_revision(uid, instrument) revision = results["revision"] - location, location_path = self.mdsutils.get_signal( + location, location_path = self._get_signal( uid, instrument, ".geometry:location", revision ) - direction, direction_path = self.mdsutils.get_signal( + direction, direction_path = self._get_signal( uid, instrument, ".geometry:direction", revision ) if instrument == "smmh": - location_r, _ = self.mdsutils.get_signal( + location_r, _ = self._get_signal( uid, instrument, ".geometry:location_r", revision ) - direction_r, _ = self.mdsutils.get_signal( + direction_r, _ = self._get_signal( uid, instrument, ".geometry:direction_r", revision ) location = (location + location_r) / 2.0 @@ -626,10 +594,10 @@ def _get_interferometry( location = np.array([location]) direction = np.array([direction]) - times, _ = self.mdsutils.get_signal(uid, instrument, ":time", revision) + times, _ = self._get_signal(uid, instrument, ":time", revision) for q in quantities: - qval, q_path = self.mdsutils.get_signal( + qval, q_path = self._get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q], revision ) @@ -639,7 +607,7 @@ def _get_interferometry( results[q] = qval try: - qval_err, q_path_err = self.mdsutils.get_signal( + qval_err, q_path_err = self._get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q] + "_err", @@ -652,7 +620,7 @@ def _get_interferometry( results[q + "_error" + "_records"] = q_path_err try: - qval_syserr, q_path_syserr = self.mdsutils.get_signal( + qval_syserr, q_path_syserr = self._get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q] + "_syserr", @@ -690,34 +658,34 @@ def _get_thomson_scattering( "machine_dims": self.MACHINE_DIMS, } - results["revision"] = self._get_revision(uid, instrument, revision) + results["revision"] = self._get_revision(uid, instrument) revision = results["revision"] - times, times_path = self.mdsutils.get_signal(uid, instrument, ":time", revision) + times, times_path = self._get_signal(uid, instrument, ":time", revision) print("\n Hardcoded correction to TS coordinates to be fixed in MDS+ \n") - # location, location_path = self.mdsutils.get_signal( + # location, location_path = self._get_signal( # uid, instrument, ".geometry:location", revision # ) - # direction, direction_path = self.mdsutils.get_signal( + # direction, direction_path = self._get_signal( # uid, instrument, ".geometry:direction", revision # ) - x, x_path = self.mdsutils.get_signal(uid, instrument, ":x", revision) - y, y_path = self.mdsutils.get_signal(uid, instrument, ":y", revision) - z, z_path = self.mdsutils.get_signal(uid, instrument, ":z", revision) - R, R_path = self.mdsutils.get_signal(uid, instrument, ":R", revision) + x, x_path = self._get_signal(uid, instrument, ":x", revision) + y, y_path = self._get_signal(uid, instrument, ":y", revision) + z, z_path = self._get_signal(uid, instrument, ":z", revision) + R, R_path = self._get_signal(uid, instrument, ":R", revision) z = R * 0.0 x = R y = R * 0.0 for q in quantities: - qval, q_path = self.mdsutils.get_signal( + qval, q_path = self._get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q], revision, ) try: - qval_err, q_path_err = self.mdsutils.get_signal( + qval_err, q_path_err = self._get_signal( uid, instrument, self.QUANTITIES_MDS[instrument][q] + "_err", @@ -726,7 +694,7 @@ def _get_thomson_scattering( except TreeNNF: qval_err = np.full_like(qval, 0.0) - dimensions, _ = self.mdsutils.get_signal_dims(q_path, len(qval.shape)) + dimensions, _ = self._get_signal_dims(q_path, len(qval.shape)) results[q + "_records"] = q_path results[q] = qval