diff --git a/omas/machine_mappings/_efit_no_py2tdi.json b/omas/machine_mappings/_efit_no_py2tdi.json new file mode 100644 index 000000000..6909f5c9a --- /dev/null +++ b/omas/machine_mappings/_efit_no_py2tdi.json @@ -0,0 +1,402 @@ +{ + "__cocos_rules__": { + "EFIT_tree": { + "PYTHON": "MDS_gEQDSK_COCOS_identify(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + } + }, + "equilibrium.code.name": { + "EVAL": "{EFIT_tree!r}" + }, + "equilibrium.code.version": { + "EVAL": "{EFIT_tree!r}" + }, + "equilibrium.ids_properties.homogeneous_time": { + "VALUE": 1 + }, + "equilibrium.time": { + "TDI": "\\{EFIT_tree}::TOP.RESULTS.GEQDSK.GTIME/1000.", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.time": { + "TDI": "\\{EFIT_tree}::TOP.RESULTS.GEQDSK.GTIME/1000.", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:": { + "TDI": "size(\\{EFIT_tree}::TOP.RESULTS.GEQDSK.GTIME)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.boundary.outline.r": { + "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.boundary.outline.z": { + "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.boundary.x_point.:": { + "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.boundary.x_point.:.r": { + "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.boundary.x_point.:.z": { + "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.boundary_separatrix.outline.r": { + "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.boundary_separatrix.outline.z": { + "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.boundary_separatrix.x_point.:": { + "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.boundary_separatrix.x_point.:.r": { + "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.boundary_separatrix.x_point.:.z": { + "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.boundary_separatrix.geometric_axis.r": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.RSURF)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.boundary_separatrix.geometric_axis.z": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZSURF)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.boundary_separatrix.closest_wall_point.distance": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.SEPLIM)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.boundary_separatrix.gap.:": { + "VALUE": 4 + }, + "equilibrium.time_slice.:.boundary_separatrix.gap.0.name": { + "VALUE": "inboard" + }, + "equilibrium.time_slice.:.boundary_separatrix.gap.0.value": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.GAPIN)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.boundary_separatrix.gap.1.name": { + "VALUE": "outboard" + }, + "equilibrium.time_slice.:.boundary_separatrix.gap.1.value": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.GAPOUT)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.boundary_separatrix.gap.2.name": { + "VALUE": "top" + }, + "equilibrium.time_slice.:.boundary_separatrix.gap.2.value": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.GAPTOP)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.boundary_separatrix.gap.3.name": { + "VALUE": "bottom" + }, + "equilibrium.time_slice.:.boundary_separatrix.gap.3.value": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.GAPBOT)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.boundary_separatrix.strike_point.:": { + "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.boundary_separatrix.strike_point.:.r": { + "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.boundary_separatrix.strike_point.:.z": { + "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.boundary_separatrix.triangularity_upper": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.TRITOP)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.boundary_separatrix.triangularity_lower": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.TRIBOT)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.boundary_separatrix.elongation": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.KAPPA)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.boundary_separatrix.minor_radius": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.AMINOR)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.boundary_separatrix.psi": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.GEQDSK.SSIBRY)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.constraints.ip.measured": { + "PYTHON": "scalar_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'ip', 'PLASMA', 'SIGPASMA', 'FWTPASMA', 'CPASMA', 'CHIPASMA', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.ip.measured_error_upper": { + "PYTHON": "scalar_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'ip', 'PLASMA', 'SIGPASMA', 'FWTPASMA', 'CPASMA', 'CHIPASMA', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.ip.weight": { + "PYTHON": "scalar_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'ip', 'PLASMA', 'SIGPASMA', 'FWTPASMA', 'CPASMA', 'CHIPASMA', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.ip.reconstructed": { + "PYTHON": "scalar_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'ip', 'PLASMA', 'SIGPASMA', 'FWTPASMA', 'CPASMA', 'CHIPASMA', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.ip.chi_squared": { + "PYTHON": "scalar_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'ip', 'PLASMA', 'SIGPASMA', 'FWTPASMA', 'CPASMA', 'CHIPASMA', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.bpol_probe.:": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'bpol_probe', 'EXPMPI', 'SIGMPI', 'FWTMP2', 'CMPR2', 'SAIMPI', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.bpol_probe.:.measured": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'bpol_probe', 'EXPMPI', 'SIGMPI', 'FWTMP2', 'CMPR2', 'SAIMPI', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.bpol_probe.:.measured_error_upper": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'bpol_probe', 'EXPMPI', 'SIGMPI', 'FWTMP2', 'CMPR2', 'SAIMPI', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.bpol_probe.:.weight": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'bpol_probe', 'EXPMPI', 'SIGMPI', 'FWTMP2', 'CMPR2', 'SAIMPI', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.bpol_probe.:.reconstructed": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'bpol_probe', 'EXPMPI', 'SIGMPI', 'FWTMP2', 'CMPR2', 'SAIMPI', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.bpol_probe.:.chi_squared": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'bpol_probe', 'EXPMPI', 'SIGMPI', 'FWTMP2', 'CMPR2', 'SAIMPI', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.diamagnetic_flux.measured": { + "PYTHON": "scalar_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'diamagnetic_flux', 'DIAMAG', 'SIGDIA', 'FWTDIA', 'CDFLUX', 'CHIDFLUX', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.diamagnetic_flux.measured_error_upper": { + "PYTHON": "scalar_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'diamagnetic_flux', 'DIAMAG', 'SIGDIA', 'FWTDIA', 'CDFLUX', 'CHIDFLUX', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.diamagnetic_flux.weight": { + "PYTHON": "scalar_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'diamagnetic_flux', 'DIAMAG', 'SIGDIA', 'FWTDIA', 'CDFLUX', 'CHIDFLUX', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.diamagnetic_flux.reconstructed": { + "PYTHON": "scalar_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'diamagnetic_flux', 'DIAMAG', 'SIGDIA', 'FWTDIA', 'CDFLUX', 'CHIDFLUX', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.diamagnetic_flux.chi_squared": { + "PYTHON": "scalar_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'diamagnetic_flux', 'DIAMAG', 'SIGDIA', 'FWTDIA', 'CDFLUX', 'CHIDFLUX', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.flux_loop.:": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'flux_loop', 'SILOPT', 'SIGSIL', 'FWTSI', 'CSILOP', 'SAISIL', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.flux_loop.:.measured": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'flux_loop', 'SILOPT', 'SIGSIL', 'FWTSI', 'CSILOP', 'SAISIL', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.flux_loop.:.measured_error_upper": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'flux_loop', 'SILOPT', 'SIGSIL', 'FWTSI', 'CSILOP', 'SAISIL', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.flux_loop.:.weight": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'flux_loop', 'SILOPT', 'SIGSIL', 'FWTSI', 'CSILOP', 'SAISIL', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.flux_loop.:.reconstructed": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'flux_loop', 'SILOPT', 'SIGSIL', 'FWTSI', 'CSILOP', 'SAISIL', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.flux_loop.:.chi_squared": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'flux_loop', 'SILOPT', 'SIGSIL', 'FWTSI', 'CSILOP', 'SAISIL', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.mse_polarisation_angle.:": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'mse_polarisation_angle', 'TANGAM', 'SIGGAM', 'FWTGAM', 'CMGAM', 'CHIGAM', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.mse_polarisation_angle.:.measured": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'mse_polarisation_angle', 'TANGAM', 'SIGGAM', 'FWTGAM', 'CMGAM', 'CHIGAM', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.mse_polarisation_angle.:.measured_error_upper": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'mse_polarisation_angle', 'TANGAM', 'SIGGAM', 'FWTGAM', 'CMGAM', 'CHIGAM', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.mse_polarisation_angle.:.weight": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'mse_polarisation_angle', 'TANGAM', 'SIGGAM', 'FWTGAM', 'CMGAM', 'CHIGAM', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.mse_polarisation_angle.:.reconstructed": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'mse_polarisation_angle', 'TANGAM', 'SIGGAM', 'FWTGAM', 'CMGAM', 'CHIGAM', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.mse_polarisation_angle.:.chi_squared": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'mse_polarisation_angle', 'TANGAM', 'SIGGAM', 'FWTGAM', 'CMGAM', 'CHIGAM', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.pf_current.:": { + "PYTHON": "concat_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'pf_current', ['ECCURT','FCCURT'], ['SIGECC','SIGFCC'], ['FWTEC','FWTFC'], ['CECURR','CCBRSP'], ['CHIECC','CHIFCC'], {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.pf_current.:.measured": { + "PYTHON": "concat_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'pf_current', ['ECCURT','FCCURT'], ['SIGECC','SIGFCC'], ['FWTEC','FWTFC'], ['CECURR','CCBRSP'], ['CHIECC','CHIFCC'], {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.pf_current.:.measured_error_upper": { + "PYTHON": "concat_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'pf_current', ['ECCURT','FCCURT'], ['SIGECC','SIGFCC'], ['FWTEC','FWTFC'], ['CECURR','CCBRSP'], ['CHIECC','CHIFCC'], {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.pf_current.:.weight": { + "PYTHON": "concat_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'pf_current', ['ECCURT','FCCURT'], ['SIGECC','SIGFCC'], ['FWTEC','FWTFC'], ['CECURR','CCBRSP'], ['CHIECC','CHIFCC'], {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.pf_current.:.reconstructed": { + "PYTHON": "concat_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'pf_current', ['ECCURT','FCCURT'], ['SIGECC','SIGFCC'], ['FWTEC','FWTFC'], ['CECURR','CCBRSP'], ['CHIECC','CHIFCC'], {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.pf_current.:.chi_squared": { + "PYTHON": "concat_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'pf_current', ['ECCURT','FCCURT'], ['SIGECC','SIGFCC'], ['FWTEC','FWTFC'], ['CECURR','CCBRSP'], ['CHIECC','CHIFCC'], {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.pressure.:": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'pressure', 'PRESSR', 'SIGPRE', 'FWTPRE', 'CPRESS', 'SAIPRE', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.pressure.:.measured": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'pressure', 'PRESSR', 'SIGPRE', 'FWTPRE', 'CPRESS', 'SAIPRE', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.pressure.:.measured_error_upper": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'pressure', 'PRESSR', 'SIGPRE', 'FWTPRE', 'CPRESS', 'SAIPRE', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.pressure.:.weight": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'pressure', 'PRESSR', 'SIGPRE', 'FWTPRE', 'CPRESS', 'SAIPRE', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.pressure.:.reconstructed": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'pressure', 'PRESSR', 'SIGPRE', 'FWTPRE', 'CPRESS', 'SAIPRE', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.pressure.:.chi_squared": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'pressure', 'PRESSR', 'SIGPRE', 'FWTPRE', 'CPRESS', 'SAIPRE', {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.pressure.:.position.psi": { + "PYTHON": "constraint_psi_to_real_psi(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'pressure', 'RPRESS', EFIT_run_id={EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.j_tor.:": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'j_tor', 'VZEROJ', EFIT_run_id={EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.j_tor.:.measured": { + "PYTHON": "vector_constraint_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'j_tor', 'VZEROJ', EFIT_run_id={EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.constraints.j_tor.:.position.psi": { + "PYTHON": "constraint_psi_to_real_psi(ods, {machine!r}, {pulse}, {EFIT_tree!r}, 'j_tor', 'SIZEROJ', EFIT_run_id={EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.global_quantities.ip": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.GEQDSK.CPASMA)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.global_quantities.li_3": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.LI3)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.global_quantities.magnetic_axis.r": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.GEQDSK.RMAXIS)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.global_quantities.magnetic_axis.z": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.GEQDSK.ZMAXIS)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.global_quantities.magnetic_axis.b_field_tor": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.BT0)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.global_quantities.psi_axis": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.GEQDSK.SSIMAG)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.global_quantities.psi_boundary": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.GEQDSK.SSIBRY)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.global_quantities.area": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.AREA)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.global_quantities.surface": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.PSURFA)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.global_quantities.volume": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.VOLUME)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.global_quantities.beta_pol": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.BETAP)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.global_quantities.beta_tor": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.BETAT)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.global_quantities.beta_normal": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.BETAN)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.global_quantities.q_95": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.Q95)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.global_quantities.q_axis": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.Q0)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.global_quantities.q_min.value": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.QMIN)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.profiles_1d.dpressure_dpsi": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.GEQDSK.PPRIME)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.profiles_1d.f": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.GEQDSK.FPOL)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.profiles_1d.f_df_dpsi": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.GEQDSK.FFPRIM)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.profiles_1d.pressure": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.GEQDSK.PRES)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.profiles_1d.psi": { + "PYTHON": "efit.psi_profiles(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.profiles_1d.q": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.GEQDSK.QPSI)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.profiles_1d.rho_tor_norm": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.GEQDSK.RHOVN)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.profiles_1d.j_tor": { + "PYTHON": "efit.fluxfun_profiles(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.profiles_1d.j_parallel": { + "PYTHON": "efit.fluxfun_profiles(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.profiles_1d.volume": { + "PYTHON": "efit.fluxfun_profiles(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.profiles_2d.:": { + "VALUE": 1 + }, + "equilibrium.time_slice.:.profiles_2d.:.grid.dim1": { + "PYTHON": "efit.grid_2d_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.profiles_2d.:.grid.dim2": { + "PYTHON": "efit.grid_2d_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.profiles_2d.:.grid_type.index": { + "PYTHON": "efit.grid_2d_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.profiles_2d.:.psi": { + "TDI": "[data(\\{EFIT_tree}::TOP.RESULTS.GEQDSK.PSIRZ)]", + "TRANSPOSE": [ + 1, + 0, + 3, + 2 + ], + "treename": "{EFIT_tree}" + }, + "equilibrium.vacuum_toroidal_field.b0": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.GEQDSK.BCENTR)", + "treename": "{EFIT_tree}" + }, + "equilibrium.vacuum_toroidal_field.r0": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.GEQDSK.RZERO)[0]", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.convergence.iterations_n": { + "PYTHON": "efit_iteration_number(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" + }, + "equilibrium.time_slice.:.convergence.grad_shafranov_deviation_value": { + "TDI": "data(\\{EFIT_tree}::TOP.RESULTS.AEQDSK.ERROR)", + "treename": "{EFIT_tree}" + }, + "equilibrium.time_slice.:.convergence.grad_shafranov_deviation_expression.index": { + "EVAL": "3" + } +} diff --git a/omas/machine_mappings/_efit_toksearch.json b/omas/machine_mappings/_efit_toksearch.json deleted file mode 100644 index cbb268e92..000000000 --- a/omas/machine_mappings/_efit_toksearch.json +++ /dev/null @@ -1,129 +0,0 @@ -{ - "__cocos_rules__": { - "EFIT_tree": { - "PYTHON": "MDS_gEQDSK_COCOS_identify(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - } - }, - - "equilibrium.time_slice.:.boundary.outline.r": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.boundary.outline.z": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.boundary.x_point.0.r": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.boundary.x_point.1.r": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.boundary.x_point.0.z": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.boundary.x_point.1.z": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.boundary_separatrix.outline.r": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.boundary_separatrix.outline.z": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.boundary_separatrix.x_point.0.r": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.boundary_separatrix.x_point.1.r": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.boundary_separatrix.x_point.0.z": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.boundary_separatrix.x_point.1.z": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.boundary_separatrix.strike_point.0.r": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.boundary_separatrix.strike_point.0.z": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.boundary_separatrix.strike_point.1.r": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.boundary_separatrix.strike_point.1.z": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.boundary_separatrix.strike_point.2.r": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.boundary_separatrix.strike_point.2.z": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.boundary_separatrix.strike_point.3.r": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.boundary_separatrix.strike_point.3.z": { - "PYTHON": "efit.equilibrium_time_slice_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - - "equilibrium.time_slice.:.constraints.pf_current.:": { - "PYTHON": "efit.pf_current_measurements(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.constraints.pf_current.:.measured": { - "PYTHON": "efit.pf_current_measurements(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.constraints.pf_current.:.measured_error_upper": { - "PYTHON": "efit.pf_current_measurements(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.constraints.pf_current.:.weight": { - "PYTHON": "efit.pf_current_measurements(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.constraints.pf_current.:.reconstructed": { - "PYTHON": "efit.pf_current_measurements(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.constraints.pf_current.:.chi_squared": { - "PYTHON": "efit.pf_current_measurements(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - - "equilibrium.time_slice.:.constraints.pressure.:.measured": { - "PYTHON": "efit.pressure_measurements(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.constraints.pressure.:.measured_error_upper": { - "PYTHON": "efit.pressure_measurements(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.constraints.pressure.:.weight": { - "PYTHON": "efit.pressure_measurements(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.constraints.pressure.:.reconstructed": { - "PYTHON": "efit.pressure_measurements(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.constraints.pressure.:.chi_squared": { - "PYTHON": "efit.pressure_measurements(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.constraints.pressure.:.position.psi": { - "PYTHON": "efit.psi_profiles(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.constraints.j_tor.:.measured": { - "PYTHON": "efit.jtor_measurements(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.constraints.j_tor.:.position.psi": { - "PYTHON": "efit.psi_profiles(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.profiles_1d.psi": { - "PYTHON": "efit.psi_profiles(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - - "equilibrium.time_slice.:.profiles_2d.:.grid.dim1": { - "PYTHON": "efit.grid_2d_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.profiles_2d.:.grid.dim2": { - "PYTHON": "efit.grid_2d_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - "equilibrium.time_slice.:.profiles_2d.:.grid_type.index": { - "PYTHON": "efit.grid_2d_data(ods, {machine!r}, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - }, - - "equilibrium.time_slice.:.convergence.iterations_n": { - "PYTHON": "efit.convergence_data(ods, {pulse}, {EFIT_tree!r}, {EFIT_run_id!r})" - } -} \ No newline at end of file diff --git a/omas/machine_mappings/d3d.json b/omas/machine_mappings/d3d.json index 1cd1c8ac6..8669329f7 100644 --- a/omas/machine_mappings/d3d.json +++ b/omas/machine_mappings/d3d.json @@ -2,7 +2,7 @@ "__cocos_rules__": {}, "__include__": [ "_common", - "_efit" + "_efit_no_py2tdi" ], "__mdsserver__": "atlas.gat.com:8000", "__options__": { @@ -21,9 +21,6 @@ "revision": "BLESSED", "store_differential": false }, - "__toksearch_overrides__": [ - "_efit_toksearch" - ], "bolometer.channel.:": { "PYTHON": "bolometer_hardware(ods, {pulse})" }, diff --git a/omas/machine_mappings/d3d.py b/omas/machine_mappings/d3d.py index 9a1e05f76..3445cc669 100644 --- a/omas/machine_mappings/d3d.py +++ b/omas/machine_mappings/d3d.py @@ -1715,7 +1715,7 @@ def charge_exchange_data(ods, pulse, analysis_type='CERQUICK', _measurements=Tru else: pos1 = pos TDIs[f'{sub}_{channel}_{pos}__data'] = f"CER.{analysis_type}.{sub}.CHANNEL{channel:02d}.{pos1}" - TDIs[f'{sub}_{channel}_{pos}__time'] = f"dim_of(CER.{analysis_type}.{sub}.CHANNEL{channel:02d}.{pos1}, 0)/1000" + TDIs[f'{sub}_{channel}_{pos}__time'] = f"dim_of(CER.{analysis_type}.{sub}.CHANNEL{channel:02d}.{pos1}, 0)" for pos in ['FZ', 'ZEFF', 'NZ']: look_up[f'{sub}_{channel}_{pos}__data'] = f"TCL('decomp IMPDENS.{analysis_type}.{pos}{sub[0]}{channel}', _output), _output" @@ -1737,7 +1737,7 @@ def charge_exchange_data(ods, pulse, analysis_type='CERQUICK', _measurements=Tru else: assert impcon_tree_name==tree_name, "References to multiple IMCPON trees in one IMPDENS analysis type are not supported." impcon_TDIs[key] = new_path - impcon_TDIs[key.replace("_data", "_time")] = f"dim_of({new_path},0)/1000" + impcon_TDIs[key.replace("_data", "_time")] = f"dim_of({new_path},0)" # fetch data = provider.raw('IONS', pulse, TDIs) if sys.version_info >= (3, 9): @@ -1754,7 +1754,6 @@ def charge_exchange_data(ods, pulse, analysis_type='CERQUICK', _measurements=Tru postime = data[f'{sub}_{channel}_TIME'] if isinstance(postime, Exception): continue - postime = postime / 1000.0 # Convert ms to s ch = ods['charge_exchange.channel.+'] # + does the next channel ch['name'] = 'impCER_{}{:02d}'.format(sub, channel) ch['identifier'] = '{}{:02d}'.format(sub[0], channel) @@ -1770,12 +1769,12 @@ def charge_exchange_data(ods, pulse, analysis_type='CERQUICK', _measurements=Tru chpos['data'] = posdat * -np.pi / 180.0 if pos == 'VIEW_PHI' and not isinstance(posdat, Exception) else posdat if _measurements: if not isinstance(data[f'{sub}_{channel}_TEMP__data'], Exception): - ch['ion.0.t_i.time'] = data[f'{sub}_{channel}_TEMP__time'] + ch['ion.0.t_i.time'] = data[f'{sub}_{channel}_TEMP__time'] / 1000.e0 ch['ion.0.t_i.data'] = unumpy.uarray(data[f'{sub}_{channel}_TEMP__data'], data[f'{sub}_{channel}_TEMP_ERR_PS__data'] + data[f'{sub}_{channel}_TEMP_ERR__data']) if not isinstance(data[f'{sub}_{channel}_ROT__data'], Exception): - ch['ion.0.velocity_tor.time'] = data[f'{sub}_{channel}_ROT__time'] + ch['ion.0.velocity_tor.time'] = data[f'{sub}_{channel}_ROT__time']/1000.0 ch['ion.0.velocity_tor.data'] = unumpy.uarray(data[f'{sub}_{channel}_ROT__data'] * 1000.0, data[f'{sub}_{channel}_ROT_ERR_PS__data'] * 1000.0 + data[f'{sub}_{channel}_ROT_ERR__data'] * 1000.0) # from Km/s to m/s @@ -1783,7 +1782,7 @@ def charge_exchange_data(ods, pulse, analysis_type='CERQUICK', _measurements=Tru ch['ion.0.n_i_over_n_e.time'] = data[f'{sub}_{channel}_FZ__time']/1000.0 ch['ion.0.n_i_over_n_e.data'] = data[f'{sub}_{channel}_FZ__data'] * 0.01 if not isinstance(data[f'{sub}_{channel}_NZ__data'], Exception): - ch['ion.0.n_i.time'] = data[f'{sub}_{channel}_FZ__time'] + ch['ion.0.n_i.time'] = data[f'{sub}_{channel}_FZ__time']/1000.0 ch['ion.0.n_i.data'] = data[f'{sub}_{channel}_NZ__data'] if not isinstance(data[f'{sub}_{channel}_ZEFF__data'], Exception): ch['zeff.time'] = data[f'{sub}_{channel}_ZEFF__time'] / 1000.0 @@ -1840,21 +1839,21 @@ def magnetics_floops_data(ods, pulse, store_differential=False, nref=0): if pulse > shot: compshot = shot break - for compsig in comp[compshot]: - if compsig == 'N1COIL' and pulse > 112962: + for compsig_name in comp[compshot]: + if compsig_name == 'N1COIL' and pulse > 112962: continue provider = ods.get_mds_provider('d3d') - compsig_data = provider.data(None, pulse, f'ptdata("{compsig}",{pulse})') - compsig_time = provider.dim_of(None, pulse, f'ptdata("{compsig}",{pulse})', 0) / 1000.0 + compsig_data = provider.data(None, pulse, f'ptdata("{compsig_name}",{pulse})') + compsig_time = provider.dim_of(None, pulse, f'ptdata("{compsig_name}",{pulse})', 0) / 1000.0 for channel in ods['magnetics.flux_loop']: if f'magnetics.flux_loop.{channel}.identifier' in ods1 and ods[f'magnetics.flux_loop.{channel}.flux.validity'] >= 0: sig = ods1[f'magnetics.flux_loop.{channel}.identifier'] - if sig in comp[compshot][compsig]: + if sig in comp[compshot][compsig_name]: sigraw_time = ods[f'magnetics.flux_loop.{channel}.flux.time'] compsig_data_interp = np.interp(sigraw_time, compsig_time, compsig_data) - ods[f'magnetics.flux_loop.{channel}.flux.data'] -= comp[compshot][compsig][sig] * compsig_data_interp + ods[f'magnetics.flux_loop.{channel}.flux.data'] -= comp[compshot][compsig_name][sig] * compsig_data_interp else: - printe(f"No {compsig} compensation for {sig}, skipping") + printe(f"No {compsig_name} compensation for {sig}, skipping") # Fetch uncertainties TDIs = {} @@ -1988,24 +1987,31 @@ def magnetics_probes_data(ods, pulse): if pulse > shot: compshot = shot break - for compsig in comp[compshot]: - if compsig == 'N1COIL' and pulse > 112962: - continue - provider = ods.get_mds_provider('d3d') - compsig_data = provider.data(None, pulse, f"[ptdata2(\"{compsig}\",{pulse})]") - compsig_time = provider.dim_of(None, pulse, f"[ptdata2(\"{compsig}\",{pulse})]", 0) / 1000.0 + compsig_TDIs = {} + if pulse > 112962 and 'N1COIL' in comp[compshot]: + comp[compshot].pop('N1COIL') + for compsig_name in comp[compshot]: + compsig_TDIs[compsig_name] = f"ptdata2(\"{compsig_name}\",{pulse})" + compsig_TDIs[compsig_name+"_time"] = f"dim_of(ptdata2(\"{compsig_name}\",{pulse}),0)" + + provider = ods.get_mds_provider('d3d') + compsig_data = provider.raw(None, pulse, compsig_TDIs) + + for compsig_name in comp[compshot]: + compsig = compsig_data[compsig_name] + compsig_time = compsig_data[compsig_name+"_time"] * 1.e-3 for channel in ods1['magnetics.b_field_pol_probe']: if ( f'magnetics.b_field_pol_probe.{channel}.identifier' in ods1 and ods[f'magnetics.b_field_pol_probe.{channel}.field.validity'] >= 0 ): sig = ods1[f'magnetics.b_field_pol_probe.{channel}.identifier'] - if sig in comp[compshot][compsig]: + if sig in comp[compshot][compsig_name]: sigraw_time = ods[f'magnetics.b_field_pol_probe.{channel}.field.time'] - compsig_data_interp = np.interp(sigraw_time, compsig_time, compsig_data) - ods[f'magnetics.b_field_pol_probe.{channel}.field.data'] -= comp[compshot][compsig][sig] * compsig_data_interp + compsig_data_interp = np.interp(sigraw_time, compsig_time, compsig) + ods[f'magnetics.b_field_pol_probe.{channel}.field.data'] -= comp[compshot][compsig_name][sig] * compsig_data_interp else: - printe(f"No {compsig} compensation for {sig}, skipping") + printe(f"No {compsig_name} compensation for {sig}, skipping") # Fetch uncertainties diff --git a/omas/machine_mappings/efit.py b/omas/machine_mappings/efit.py index cfecf4753..f0c0c5a63 100644 --- a/omas/machine_mappings/efit.py +++ b/omas/machine_mappings/efit.py @@ -1,4 +1,5 @@ import numpy as np +from scipy.interpolate import interp1d from omas import * from omas.omas_utils import printd, printe from omas.machine_mappings._common import * @@ -13,261 +14,158 @@ @machine_mapping_function(__regression_arguments__, pulse=194844, EFIT_tree='EFIT01', EFIT_run_id='') def equilibrium_time_slice_data(ods, machine, pulse, EFIT_tree='EFIT01', EFIT_run_id=''): """ - Load EFIT equilibrium time slice data that requires complex TDI expressions - - This function replaces the complex py2tdi expressions in _efit.json that + Load EFIT boundary outline, X-point and strike point data + + This function replaces the py2tdi(nan_where, ...) expressions in _efit.json that TokSearch cannot handle, providing backend-agnostic access to EFIT data. - + :param ods: OMAS ODS instance + :param machine: machine name :param pulse: shot number - :param EFIT_tree: EFIT tree name (e.g., 'EFIT01', 'EFIT02') + :param EFIT_tree: EFIT tree name (e.g., 'EFIT01', 'EFIT02') :param EFIT_run_id: run id extension for pulse number """ - printd(f'Loading EFIT equilibrium data from {EFIT_tree}...', topic='machine') - + printd(f'Loading EFIT boundary data from {EFIT_tree}...', topic='machine') + # Get provider from ODS - provider = ods.get_mds_provider('d3d') + provider = ods.get_mds_provider(machine) pulse_id = get_pulse_id(pulse, EFIT_run_id) - - # Fetch only data requiring NaN filtering (not available via simple TDI) - printd('Loading EFIT data requiring NaN filtering...', topic='machine') + TDIs = { # Boundary data requiring NaN filtering 'rbbbs': f'\\{EFIT_tree}::TOP.RESULTS.GEQDSK.RBBBS', 'zbbbs': f'\\{EFIT_tree}::TOP.RESULTS.GEQDSK.ZBBBS', # X-point data requiring NaN filtering 'rxpt1': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.RXPT1', - 'zxpt1': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZXPT1', + 'zxpt1': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZXPT1', 'rxpt2': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.RXPT2', 'zxpt2': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZXPT2', - # Strike point data requiring NaN filtering (with /100. conversion) - 'rvsid': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.RVSID/100.', - 'zvsid': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZVSID/100.', - 'rvsod': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.RVSOD/100.', - 'zvsod': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZVSOD/100.', - 'rvsiu': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.RVSIU/100.', - 'zvsiu': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZVSIU/100.', - 'rvsou': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.RVSOU/100.', - 'zvsou': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZVSOU/100.' + # Strike point data requiring NaN filtering + 'rvsid': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.RVSID', + 'zvsid': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZVSID', + 'rvsod': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.RVSOD', + 'zvsod': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZVSOD', + 'rvsiu': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.RVSIU', + 'zvsiu': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZVSIU', + 'rvsou': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.RVSOU', + 'zvsou': f'\\{EFIT_tree}::TOP.RESULTS.AEQDSK.ZVSOU' } - + # Single provider call for all data efit_data = provider.raw(EFIT_tree, pulse_id, TDIs) with omas_environment(ods, cocosio=MDS_gEQDSK_COCOS_identify(ods, machine, pulse, EFIT_tree, EFIT_run_id)): - # Get time data just for array sizing (time data is handled by simple TDI expressions) - # We need this just to know how many time slices to process - n_times = len(efit_data['rbbbs']) if len(efit_data['rbbbs'].shape) > 1 else 1 - - # Process boundary data with NaN filtering - rbbbs = efit_data['rbbbs'] - zbbbs = efit_data['zbbbs'] - - # Set NaN where R boundary is 0 (invalid data) - rbbbs[rbbbs == 0] = np.nan - zbbbs[rbbbs == 0] = np.nan # Use same mask for Z - - # Set boundary data for all time slices - for i in range(n_times): - if i < rbbbs.shape[0]: - ods['equilibrium']['time_slice'][i]['boundary']['outline']['r'] = rbbbs[i, :] - ods['equilibrium']['time_slice'][i]['boundary']['outline']['z'] = zbbbs[i, :] - - # Process X-point data with NaN filtering - rxpt1 = efit_data['rxpt1'] - zxpt1 = efit_data['zxpt1'] - rxpt2 = efit_data['rxpt2'] - zxpt2 = efit_data['zxpt2'] - - # Set NaN where X-point data is 0 (invalid) - rxpt1[rxpt1 == 0] = np.nan - zxpt1[rxpt1 == 0] = np.nan - rxpt2[rxpt2 == 0] = np.nan - zxpt2[rxpt2 == 0] = np.nan - - # Set X-point data for all time slices (up to 2 X-points) - for i in range(n_times): - time_slice = ods['equilibrium']['time_slice'][i] - - # Set X-point array size - if i < rxpt1.shape[0]: - time_slice['boundary']['x_point'][0]['r'] = rxpt1[i] - time_slice['boundary']['x_point'][0]['z'] = zxpt1[i] - - if i < rxpt2.shape[0]: - time_slice['boundary']['x_point'][1]['r'] = rxpt2[i] - time_slice['boundary']['x_point'][1]['z'] = zxpt2[i] - - # Process strike point data with NaN filtering (nan_where with -0.89 threshold) - strike_data = { - 'rvsid': efit_data['rvsid'], 'zvsid': efit_data['zvsid'], - 'rvsod': efit_data['rvsod'], 'zvsod': efit_data['zvsod'], - 'rvsiu': efit_data['rvsiu'], 'zvsiu': efit_data['zvsiu'], - 'rvsou': efit_data['rvsou'], 'zvsou': efit_data['zvsou'] - } - - # Apply nan_where logic: set NaN where data equals -0.89 - for key in strike_data: - strike_data[key][strike_data[key] == -0.89] = np.nan - - # Set strike point data for all time slices (4 strike points) + # Boundary outline: RBBBS == 0 marks the unused tail of the fixed size arrays, + # and masks Z as well so that both keep the same length once the NaNs are dropped + rbbbs = np.atleast_2d(efit_data['rbbbs']) + zbbbs = np.atleast_2d(efit_data['zbbbs']) + unset = rbbbs == 0 + rbbbs[unset] = np.nan + zbbbs[unset] = np.nan + + n_times = rbbbs.shape[0] for i in range(n_times): - time_slice = ods['equilibrium']['time_slice'][i] - - # Strike point 0 (RVSID, ZVSID) - if i < strike_data['rvsid'].shape[0]: - time_slice['boundary_separatrix']['strike_point'][0]['r'] = strike_data['rvsid'][i] - time_slice['boundary_separatrix']['strike_point'][0]['z'] = strike_data['zvsid'][i] - - # Strike point 1 (RVSOD, ZVSOD) - if i < strike_data['rvsod'].shape[0]: - time_slice['boundary_separatrix']['strike_point'][1]['r'] = strike_data['rvsod'][i] - time_slice['boundary_separatrix']['strike_point'][1]['z'] = strike_data['zvsod'][i] - - # Strike point 2 (RVSIU, ZVSIU) - if i < strike_data['rvsiu'].shape[0]: - time_slice['boundary_separatrix']['strike_point'][2]['r'] = strike_data['rvsiu'][i] - time_slice['boundary_separatrix']['strike_point'][2]['z'] = strike_data['zvsiu'][i] - - # Strike point 3 (RVSOU, ZVSOU) - if i < strike_data['rvsou'].shape[0]: - time_slice['boundary_separatrix']['strike_point'][3]['r'] = strike_data['rvsou'][i] - time_slice['boundary_separatrix']['strike_point'][3]['z'] = strike_data['zvsou'][i] - - # Note: Global quantities, vacuum field, COCOS, and code info are handled by simple TDI expressions - + valid = ~np.isnan(rbbbs[i]) + for boundary in ['boundary', 'boundary_separatrix']: + ods['equilibrium']['time_slice'][i][boundary]['outline']['r'] = rbbbs[i][valid] + ods['equilibrium']['time_slice'][i][boundary]['outline']['z'] = zbbbs[i][valid] + + # X-points and strike points keep their slot like the _efit.json mappings do: + # R <= 0 (0 for X-points, the -0.89 sentinel for strike points) means there is + # no point at that time, and both R and Z are NaN there + for i in range(len(efit_data['rxpt1'])): + for n, (r_node, z_node) in enumerate([('rxpt1', 'zxpt1'), ('rxpt2', 'zxpt2')]): + r = np.atleast_1d(efit_data[r_node])[i] + z = np.atleast_1d(efit_data[z_node])[i] + if r <= 0.0: + r = z = np.nan + for boundary in ['boundary', 'boundary_separatrix']: + ods['equilibrium']['time_slice'][i][boundary]['x_point'][n]['r'] = r + ods['equilibrium']['time_slice'][i][boundary]['x_point'][n]['z'] = z + for i in range(len(efit_data['rvsid'])): + for n, (r_node, z_node) in enumerate([('rvsid', 'zvsid'), ('rvsod', 'zvsod'), ('rvsiu', 'zvsiu'), ('rvsou', 'zvsou')]): + r = np.atleast_1d(efit_data[r_node])[i] + z = np.atleast_1d(efit_data[z_node])[i] + if r <= 0.0: + r = z = np.nan + ods['equilibrium']['time_slice'][i]['boundary_separatrix']['strike_point'][n]['r'] = r + ods['equilibrium']['time_slice'][i]['boundary_separatrix']['strike_point'][n]['z'] = z printd(f'Successfully loaded EFIT data for {n_times} time slices', topic='machine') return ods # ================================ @machine_mapping_function(__regression_arguments__, pulse=194844, EFIT_tree='EFIT01', EFIT_run_id='') -def pf_current_measurements(ods, machine, pulse, EFIT_tree='EFIT01', EFIT_run_id=''): +def psi_profiles(ods, machine, pulse, EFIT_tree='EFIT01', EFIT_run_id=''): """ - Load PF current measurements that require stacking multiple signals - - Replaces py2tdi(stack_outer_2, ...) expressions for TokSearch compatibility + Load the 1D psi grid + + Replaces the py2tdi(geqdsk_psi, ...) expression for TokSearch compatibility. + The constraint positions are handled by constraint_psi_to_real_psi in _common.py """ - printd(f'Loading PF current measurements from {EFIT_tree}...', topic='machine') - - provider = ods.get_mds_provider('d3d') + printd(f'Loading PSI profiles from {EFIT_tree}...', topic='machine') + + provider = ods.get_mds_provider(machine) pulse_id = get_pulse_id(pulse, EFIT_run_id) - - # Get E-coil and F-coil current measurements + TDIs = { - 'eccurt': f'\\{EFIT_tree}::TOP.MEASUREMENTS.ECCURT', - 'fccurt': f'\\{EFIT_tree}::TOP.MEASUREMENTS.FCCURT', - 'sigecc': f'\\{EFIT_tree}::TOP.MEASUREMENTS.SIGECC', - 'sigfcc': f'\\{EFIT_tree}::TOP.MEASUREMENTS.SIGFCC', - 'fwtec': f'\\{EFIT_tree}::TOP.MEASUREMENTS.FWTEC', - 'fwtfc': f'\\{EFIT_tree}::TOP.MEASUREMENTS.FWTFC', - 'cecurr': f'\\{EFIT_tree}::TOP.MEASUREMENTS.CECURR', - 'ccbrsp': f'\\{EFIT_tree}::TOP.MEASUREMENTS.CCBRSP', - 'chiecc': f'\\{EFIT_tree}::TOP.MEASUREMENTS.CHIECC', - 'chifcc': f'\\{EFIT_tree}::TOP.MEASUREMENTS.CHIFCC' + 'ssimag': f'\\{EFIT_tree}::TOP.RESULTS.GEQDSK.SSIMAG', + 'ssibry': f'\\{EFIT_tree}::TOP.RESULTS.GEQDSK.SSIBRY', + 'psin': f'\\{EFIT_tree}::TOP.RESULTS.GEQDSK.PSIN' } - + efit_data = provider.raw(EFIT_tree, pulse_id, TDIs) - - # Stack E-coil and F-coil data along outer dimension (axis=1 as per stack_outer_2 function) - measured = np.concatenate([efit_data['eccurt'], efit_data['fccurt']], axis=1) - measured_error = np.concatenate([efit_data['sigecc'], efit_data['sigfcc']], axis=1) - weight = np.concatenate([efit_data['fwtec'], efit_data['fwtfc']], axis=1) - reconstructed = np.concatenate([efit_data['cecurr'], efit_data['ccbrsp']], axis=1) - chi_squared = np.concatenate([efit_data['chiecc'], efit_data['chifcc']], axis=1) - - # Set PF current constraint data - n_times = measured.shape[1] if len(measured.shape) > 1 else 1 - n_pf = measured.shape[0] + + # geqdsk_psi algorithm from python_tdi.py: a[:, None] + np.linspace(0, 1, n) * (b[:, None] - a[:, None]) + ssimag = efit_data['ssimag'] + ssibry = efit_data['ssibry'] + n = len(efit_data['psin']) + geqdsk_psi = ssimag[:, None] + np.linspace(0, 1, n) * (ssibry[:, None] - ssimag[:, None]) + with omas_environment(ods, cocosio=MDS_gEQDSK_COCOS_identify(ods, machine, pulse, EFIT_tree, EFIT_run_id)): - for i in range(n_times): - time_slice = ods['equilibrium']['time_slice'][i] - - # Set data for all PF coils - for j in range(n_pf): - if len(measured.shape) > 1: - time_slice['constraints']['pf_current'][j]['measured'] = measured[j, i] - time_slice['constraints']['pf_current'][j]['measured_error_upper'] = measured_error[j, i] - time_slice['constraints']['pf_current'][j]['weight'] = weight[j, i] - time_slice['constraints']['pf_current'][j]['reconstructed'] = reconstructed[j, i] - time_slice['constraints']['pf_current'][j]['chi_squared'] = chi_squared[j, i] - else: - time_slice['constraints']['pf_current'][j]['measured'] = measured[j] - time_slice['constraints']['pf_current'][j]['measured_error_upper'] = measured_error[j] - time_slice['constraints']['pf_current'][j]['weight'] = weight[j] - time_slice['constraints']['pf_current'][j]['reconstructed'] = reconstructed[j] - time_slice['constraints']['pf_current'][j]['chi_squared'] = chi_squared[j] + for i in range(len(geqdsk_psi)): + ods['equilibrium']['time_slice'][i]['profiles_1d']['psi'] = geqdsk_psi[i] return ods - # ================================ @machine_mapping_function(__regression_arguments__, pulse=194844, EFIT_tree='EFIT01', EFIT_run_id='') -def psi_profiles(ods, machine, pulse, EFIT_tree='EFIT01', EFIT_run_id=''): +def fluxfun_profiles(ods, machine, pulse, EFIT_tree='EFIT01', EFIT_run_id=''): """ - Load PSI profiles that require complex transformations - - Replaces py2tdi(efit_psi_to_real_psi_2d, ...) and py2tdi(geqdsk_psi, ...) expressions + Load the FLUXFUN profiles interpolated onto the GEQDSK psi grid + + Replaces py2tdi(interpolate_psi_1d, ...) expressions for TokSearch compatibility """ - printd(f'Loading PSI profiles from {EFIT_tree}...', topic='machine') - - provider = ods.get_mds_provider('d3d') + printd(f'Loading FLUXFUN profiles from {EFIT_tree}...', topic='machine') + + provider = ods.get_mds_provider(machine) pulse_id = get_pulse_id(pulse, EFIT_run_id) - - # Get data for complex PSI transformations (simple PSI data handled by TDI expressions) + TDIs = { 'ssimag': f'\\{EFIT_tree}::TOP.RESULTS.GEQDSK.SSIMAG', 'ssibry': f'\\{EFIT_tree}::TOP.RESULTS.GEQDSK.SSIBRY', 'psin': f'\\{EFIT_tree}::TOP.RESULTS.GEQDSK.PSIN', - 'rpress': f'\\{EFIT_tree}::TOP.MEASUREMENTS.RPRESS', - 'sizeroj': f'\\{EFIT_tree}::TOP.MEASUREMENTS.SIZEROJ' + 'psi': f'\\{EFIT_tree}::TOP.RESULTS.FLUXFUN.PSI', + 'j_tor': f'\\{EFIT_tree}::TOP.RESULTS.FLUXFUN.JEFF', + 'j_parallel': f'\\{EFIT_tree}::TOP.RESULTS.FLUXFUN.JLL', + 'volume': f'\\{EFIT_tree}::TOP.RESULTS.FLUXFUN.VOL' } - + efit_data = provider.raw(EFIT_tree, pulse_id, TDIs) - - # Convert EFIT PSI to real PSI (following geqdsk_psi algorithm from python_tdi.py) - ssimag = efit_data['ssimag'] # a - ssibry = efit_data['ssibry'] # b - psin = efit_data['psin'] # c - - # geqdsk_psi algorithm: a[:, None] + np.linspace(0, 1, n).T * (b[:, None] - a[:, None]) - n = len(psin) - geqdsk_psi = ssimag[:, None] + np.linspace(0, 1, n).T * (ssibry[:, None] - ssimag[:, None]) - - # Set PSI profiles - n_times = len(ssimag) if hasattr(ssimag, '__len__') else 1 + + # interpolate_psi_1d algorithm from python_tdi.py: the FLUXFUN quantities live on + # their own psi grid and are interpolated onto the geqdsk_psi grid, holding the + # end values constant outside the range + ssimag = efit_data['ssimag'] + ssibry = efit_data['ssibry'] + n = len(efit_data['psin']) + geqdsk_psi = ssimag[:, None] + np.linspace(0, 1, n) * (ssibry[:, None] - ssimag[:, None]) + x1 = efit_data['psi'].T + with omas_environment(ods, cocosio=MDS_gEQDSK_COCOS_identify(ods, machine, pulse, EFIT_tree, EFIT_run_id)): - for i in range(n_times): - time_slice = ods['equilibrium']['time_slice'][i] - - # Set profiles_1d PSI (only this complex calculation needed) - if i < len(geqdsk_psi): - time_slice['profiles_1d']['psi'] = geqdsk_psi[i] if len(geqdsk_psi.shape) > 1 else geqdsk_psi - - # Set pressure constraint positions (efit_psi_to_real_psi_2d replacement) - # efit_psi_to_real_psi_2d algorithm: (a.T * (c - b) + b).T - if type(efit_data.get("rpress", Exception())) != Exception and len(efit_data['rpress']) > 0: - rpress = -efit_data['rpress'] # a (note: negative sign from TDI) - - # Handle flexible dimensions: rpress needs time and space dimensions - if len(rpress.shape) == 1: - # Only time dimension - add spatial dimension as singleton - rpress = rpress[:, np.newaxis] - # Apply transformation for this time slice - if i < rpress.shape[0]: - for j, press_pos in enumerate(rpress[i]): - pressure_psi = (press_pos * (ssibry[i] - ssimag[i]) + ssimag[i]).T - time_slice['constraints.pressure'][j]['position.psi'] = pressure_psi - - # Set j_tor constraint positions (efit_psi_to_real_psi_2d replacement) - if type(efit_data.get("sizeroj", Exception())) != Exception and len(efit_data['sizeroj']) > 0: - sizeroj = efit_data['sizeroj'] # a - if len(sizeroj.shape) == 1: - # Only time dimension - add spatial dimension as singleton - sizeroj = sizeroj[:, np.newaxis] - - # Apply transformation for this time slice - if i < sizeroj.shape[0]: - for j, jtor_pos in enumerate(sizeroj[i]): - jtor_psi = (jtor_pos * (ssibry[i] - ssimag[i]) + ssimag[i]).T - time_slice[f'constraints.j_tor'][j]['position.psi'] = jtor_psi + for entry in ['j_tor', 'j_parallel', 'volume']: + y1 = efit_data[entry].T + for i in range(x1.shape[0]): + fill_value = (y1[i][0], y1[i][-1]) + interpolator = interp1d(x1[i], y1[i], kind='cubic', bounds_error=False, fill_value=fill_value) + ods['equilibrium']['time_slice'][i]['profiles_1d'][entry] = interpolator(geqdsk_psi[i]) return ods # ================================ @@ -280,7 +178,7 @@ def grid_2d_data(ods, machine, pulse, EFIT_tree='EFIT01', EFIT_run_id=''): """ printd(f'Loading 2D grid data from {EFIT_tree}...', topic='machine') - provider = ods.get_mds_provider('d3d') + provider = ods.get_mds_provider(machine) pulse_id = get_pulse_id(pulse, EFIT_run_id) # Get grid data @@ -309,158 +207,3 @@ def grid_2d_data(ods, machine, pulse, EFIT_tree='EFIT01', EFIT_run_id=''): ods['equilibrium']['time_slice'][itime]['profiles_2d'][0]['grid_type']['index'] = 1 return ods - -# ================================ -@machine_mapping_function(__regression_arguments__, pulse=194844, EFIT_tree='EFIT01', EFIT_run_id='') -def convergence_data(ods, pulse, EFIT_tree='EFIT01', EFIT_run_id=''): - """ - Load convergence data that requires complex axis operations - - Replaces py2tdi(get_largest_axis_value, ...) expressions - """ - printd(f'Loading convergence data from {EFIT_tree}...', topic='machine') - - provider = ods.get_mds_provider('d3d') - pulse_id = get_pulse_id(pulse, EFIT_run_id) - - # Get convergence error data - TDIs = { - 'cerror': f'\\{EFIT_tree}::TOP.MEASUREMENTS.CERROR', - 'cerror_dim': f'dim_of(\\{EFIT_tree}::TOP.MEASUREMENTS.CERROR,0)' - } - - efit_data = provider.raw(EFIT_tree, pulse_id, TDIs) - - # get_largest_axis_value algorithm from python_tdi.py - cerror_dim = efit_data['cerror_dim'] # a - cerror = efit_data['cerror'] # b - - # get_largest_axis_value algorithm: - # a = np.array([a for k in range(b.shape[0])]) - # a[b == 0] = 0 - # return np.nanmax(a, axis=1) - a = np.array([cerror_dim for k in range(cerror.shape[0])]) - a[cerror == 0] = 0 - max_axis_values = np.nanmax(a, axis=1) - - # Set convergence data - n_times = len(max_axis_values) if hasattr(max_axis_values, '__len__') else 1 - - for i in range(n_times): - time_slice = ods['equilibrium']['time_slice'][i] - iterations_n = max_axis_values[i] if hasattr(max_axis_values, '__len__') else max_axis_values - time_slice['convergence']['iterations_n'] = iterations_n - return ods - -# ================================ -@machine_mapping_function(__regression_arguments__, pulse=194844, EFIT_tree='EFIT01', EFIT_run_id='') -def pressure_measurements(ods, machine, pulse, EFIT_tree='EFIT01', EFIT_run_id=''): - """ - Load pressure measurements that require ensure_2d transformation - - Replaces py2tdi(ensure_2d, -...) expressions for TokSearch compatibility - """ - printd(f'Loading pressure measurements from {EFIT_tree}...', topic='machine') - - provider = ods.get_mds_provider('d3d') - pulse_id = get_pulse_id(pulse, EFIT_run_id) - - # Get pressure measurement data - TDIs = { - 'pressr': f'\\{EFIT_tree}::TOP.MEASUREMENTS.PRESSR', - 'sigpre': f'\\{EFIT_tree}::TOP.MEASUREMENTS.SIGPRE', - 'fwtpre': f'\\{EFIT_tree}::TOP.MEASUREMENTS.FWTPRE', - 'cpress': f'\\{EFIT_tree}::TOP.MEASUREMENTS.CPRESS', - 'saipre': f'\\{EFIT_tree}::TOP.MEASUREMENTS.SAIPRE' - } - - efit_data = provider.raw(EFIT_tree, pulse_id, TDIs) - - # Apply ensure_2d transformation: ensure array has at least 2 dimensions - # Note: negative sign applied as per TDI expressions - measured = -efit_data['pressr'] - measured_error = -efit_data['sigpre'] - weight = -efit_data['fwtpre'] - reconstructed = -efit_data['cpress'] - chi_squared = -efit_data['saipre'] - - # Ensure 2D: if 1D, add singleton dimension - for data in [measured, measured_error, weight, reconstructed, chi_squared]: - if len(data.shape) == 1: - data = data[:, np.newaxis] - - # Set pressure constraint data - n_times = measured.shape[0] if len(measured.shape) > 1 else 1 - n_pressure = measured.shape[1] if len(measured.shape) > 1 else len(measured) - - with omas_environment(ods, cocosio=MDS_gEQDSK_COCOS_identify(ods, machine, pulse, EFIT_tree, EFIT_run_id)): - for i in range(n_times): - time_slice = ods['equilibrium']['time_slice'][i] - - # Set data for all pressure measurements - for j in range(n_pressure): - if len(measured.shape) > 1: - time_slice['constraints']['pressure'][j]['measured'] = measured[i, j] - time_slice['constraints']['pressure'][j]['measured_error_upper'] = measured_error[i, j] - time_slice['constraints']['pressure'][j]['weight'] = weight[i, j] - time_slice['constraints']['pressure'][j]['reconstructed'] = reconstructed[i, j] - time_slice['constraints']['pressure'][j]['chi_squared'] = chi_squared[i, j] - else: - time_slice['constraints']['pressure'][j]['measured'] = measured[j] - time_slice['constraints']['pressure'][j]['measured_error_upper'] = measured_error[j] - time_slice['constraints']['pressure'][j]['weight'] = weight[j] - time_slice['constraints']['pressure'][j]['reconstructed'] = reconstructed[j] - time_slice['constraints']['pressure'][j]['chi_squared'] = chi_squared[j] - return ods - -# ================================ -@machine_mapping_function(__regression_arguments__, pulse=194844, EFIT_tree='EFIT01', EFIT_run_id='') -def jtor_measurements(ods, machine, pulse, EFIT_tree='EFIT01', EFIT_run_id=''): - """ - Load j_tor measurements that require convert_from_mega_2d transformation - - Replaces py2tdi(convert_from_mega_2d, -...) expressions for TokSearch compatibility - """ - printd(f'Loading j_tor measurements from {EFIT_tree}...', topic='machine') - - provider = ods.get_mds_provider('d3d') - pulse_id = get_pulse_id(pulse, EFIT_run_id) - - # Get j_tor measurement data - TDIs = { - 'vzeroj': f'\\{EFIT_tree}::TOP.MEASUREMENTS.VZEROJ' - } - - efit_data = provider.raw(EFIT_tree, pulse_id, TDIs) - - # Apply convert_from_mega_2d transformation: divide by 1e6 and ensure 2D - # Note: negative sign applied as per TDI expression - measured = -efit_data['vzeroj'] / 1e6 - - # Ensure 2D: if 1D, add singleton dimension - if len(measured.shape) == 1: - measured = measured[:, np.newaxis] - - # Set j_tor constraint data - n_times = measured.shape[0] if len(measured.shape) > 1 else 1 - n_jtor = measured.shape[1] if len(measured.shape) > 1 else len(measured) - - with omas_environment(ods, cocosio=MDS_gEQDSK_COCOS_identify(ods, machine, pulse, EFIT_tree, EFIT_run_id)): - for i in range(n_times): - time_slice = ods['equilibrium']['time_slice'][i] - - # Set data for all j_tor measurements - for j in range(n_jtor): - if len(measured.shape) > 1: - time_slice['constraints']['j_tor'][j]['measured'] = measured[i, j] - else: - time_slice['constraints']['j_tor'][j]['measured'] = measured[j] - return ods - -# ================================ -# Add test function call -if __name__ == '__main__': - # Test with d3d pulse - test_ods = ODS() - equilibrium_time_slice_data(test_ods, 'd3d', 194844) - print(f"Loaded equilibrium data with {len(test_ods['equilibrium']['time'])} time points") \ No newline at end of file diff --git a/omas/omas_machine.py b/omas/omas_machine.py index 40db35fde..b0034d183 100644 --- a/omas/omas_machine.py +++ b/omas/omas_machine.py @@ -248,7 +248,7 @@ def resolve_mapped(ods, machine, pulse, mappings, location, idm, options_with_d # Add machine specific module call_w_update_mapping = machine + "." + call[:-1] + ", update_callback=update_mapping)" local_vars = {"ods": ods} - exec("ods = " + call_w_update_mapping, globals(), local_vars) + exec(call_w_update_mapping, globals(), local_vars) ods = local_vars['ods'] if isinstance(cache, dict): cache[call] = ods @@ -565,8 +565,7 @@ def machines(machine=None, branch=''): _machines_dict[branch] = {} for filename in glob.glob(f'{dir}/*.json'): m = os.path.splitext(os.path.split(filename)[1])[0] - # Allow backend-specific mappings (e.g., _efit_toksearch.json) alongside regular machine mappings - if not m.startswith('_') or m.startswith('_efit_toksearch'): + if not m.startswith('_'): _machines_dict[branch][m] = os.path.abspath(filename) # return list of supported machines diff --git a/omas/omas_physics.py b/omas/omas_physics.py index 7f035a293..ca7af541b 100644 --- a/omas/omas_physics.py +++ b/omas/omas_physics.py @@ -715,9 +715,11 @@ def add_volume_profile(ods, grid_index=0): * numpy.sign(numpy.mean(bp)) * int_fluxexpansion_dl * (2.0 * numpy.pi) ** (1.0 - cocos['exp_Bp'])) - - volume_spline = InterpolatedUnivariateSpline(eq1d_psi, eq_slice['profiles_1d.dvolume_dpsi']).antiderivative() - eq_slice['profiles_1d.volume'] = volume_spline(eq1d_psi) + # normalize so we have an increasing x-axis for the spline + dpsi_psi_n = (eq1d_psi[-1] - eq1d_psi[0]) + eq1d_psi_n = (eq1d_psi - eq1d_psi[0])/dpsi_psi_n + volume_spline = InterpolatedUnivariateSpline(eq1d_psi_n, eq_slice['profiles_1d.dvolume_dpsi']).antiderivative() + eq_slice['profiles_1d.volume'] = volume_spline(eq1d_psi_n) * numpy.abs(dpsi_psi_n) return ods def remove_integrator_drift(time, data, time_after_shot):