11import importlib .resources
2+ import logging
23import xml .etree .ElementTree as ET
34
45import imas
1415from waveform_editor .shape_editor .plasma_properties import PlasmaProperties
1516from waveform_editor .shape_editor .plasma_shape import PlasmaShape
1617
18+ logger = logging .getLogger (__name__ )
19+
1720
1821def _reactive_title (title , is_valid ):
1922 return title if is_valid else f"{ title } ⚠️"
@@ -37,40 +40,52 @@ def __init__(self):
3740 self .plasma_properties = PlasmaProperties ()
3841 self .coil_currents = CoilCurrents ()
3942 self .nice_plotter = NicePlotter (
40- self .communicator , self .plasma_shape , self .plasma_properties
43+ communicator = self .communicator ,
44+ plasma_shape = self .plasma_shape ,
45+ plasma_properties = self .plasma_properties ,
4146 )
4247 self .nice_settings = settings .nice
4348
44- self .xml_params = ET .fromstring (
49+ self .xml_params_inv = ET .fromstring (
50+ importlib .resources .files ("waveform_editor.shape_editor.xml_param" )
51+ .joinpath ("inverse_param.xml" )
52+ .read_text ()
53+ )
54+ self .xml_params_dir = ET .fromstring (
4555 importlib .resources .files ("waveform_editor.shape_editor.xml_param" )
46- .joinpath ("param .xml" )
56+ .joinpath ("direct_param .xml" )
4757 .read_text ()
4858 )
4959
5060 # UI Configuration
5161 button_start = pn .widgets .Button (name = "Run" , on_click = self .submit )
5262 button_start .disabled = (
53- self .plasma_shape .param .has_shape .rx .not_ ()
63+ (
64+ self .plasma_shape .param .has_shape .rx .not_ ()
65+ & self .nice_settings .param .is_inverse_mode .rx ()
66+ )
5467 | self .plasma_properties .param .has_properties .rx .not_ ()
55- | param . rx ( self .nice_settings .required_params_filled ) .rx .not_ ()
68+ | self .nice_settings .param . are_required_filled .rx .not_ ()
5669 )
5770 button_stop = pn .widgets .Button (name = "Stop" , on_click = self .stop_nice )
58- buttons = pn .Row (button_start , button_stop )
71+ nice_mode_radio = pn .widgets .RadioBoxGroup .from_param (
72+ self .nice_settings .param .mode , inline = True , margin = (15 , 20 , 0 , 20 )
73+ )
74+ buttons = pn .Row (button_start , button_stop , nice_mode_radio )
5975
6076 # Accordion does not allow dynamic titles, so use separate card for each option
6177 options = pn .Column (
6278 self ._create_card (
6379 self .nice_settings .panel ,
6480 "NICE Configuration" ,
65- is_valid = param .rx (self .nice_settings .required_params_filled ),
66- ),
67- self ._create_card (
68- pn .Param (self .nice_plotter , show_name = False ), "Plotting Parameters"
81+ is_valid = self .nice_settings .param .are_required_filled .rx (),
6982 ),
83+ self ._create_card (self .nice_plotter , "Plotting Parameters" ),
7084 self ._create_card (
7185 self .plasma_shape ,
7286 "Plasma Shape" ,
7387 is_valid = self .plasma_shape .param .has_shape ,
88+ visible = self .nice_settings .param .is_inverse_mode .rx (),
7489 ),
7590 self ._create_card (
7691 pn .Column (self .plasma_properties , self .nice_plotter .profiles_pane ),
@@ -91,14 +106,15 @@ def __init__(self):
91106 ),
92107 )
93108
94- def _create_card (self , panel_object , title , is_valid = None ):
109+ def _create_card (self , panel_object , title , is_valid = None , visible = True ):
95110 """Create a collapsed card containing a panel object and a title.
96111
97112 Args:
98113 panel_object: The panel object to place into the card.
99114 title: The title to give the card.
100115 is_valid: If supplied, binds the card title to update reactively using
101116 `_reactive_title`.
117+ visible: Whether the card is visible.
102118 """
103119 if is_valid :
104120 title = param .bind (_reactive_title , title = title , is_valid = is_valid )
@@ -107,6 +123,7 @@ def _create_card(self, panel_object, title, is_valid=None):
107123 title = title ,
108124 sizing_mode = "stretch_width" ,
109125 collapsed = True ,
126+ visible = visible ,
110127 )
111128 return card
112129
@@ -169,9 +186,10 @@ def _create_equilibrium(self):
169186 equilibrium .time_slice .resize (1 )
170187 equilibrium .vacuum_toroidal_field .b0 .resize (1 )
171188
172- # Fill plasma shape
173- equilibrium .time_slice [0 ].boundary .outline .r = self .plasma_shape .outline_r
174- equilibrium .time_slice [0 ].boundary .outline .z = self .plasma_shape .outline_z
189+ # Only fill plasma shape for NICE inverse mode
190+ if self .nice_settings .is_inverse_mode :
191+ equilibrium .time_slice [0 ].boundary .outline .r = self .plasma_shape .outline_r
192+ equilibrium .time_slice [0 ].boundary .outline .z = self .plasma_shape .outline_z
175193
176194 # Fill plasma properties
177195 equilibrium .vacuum_toroidal_field .r0 = self .plasma_properties .r0
@@ -194,14 +212,21 @@ async def submit(self, event=None):
194212 description IDSs and an input equilibrium IDS."""
195213
196214 self .coil_currents .fill_pf_active (self .pf_active )
215+ if self .nice_settings .is_direct_mode :
216+ xml_params = self .xml_params_dir
217+ else :
218+ xml_params = self .xml_params_inv
219+ self .coil_currents .update_fixed_coils_in_xml (xml_params )
220+
197221 # Update XML parameters:
198- self .coil_currents .update_fixed_coils_in_xml (self .xml_params )
199- self .xml_params .find ("verbose" ).text = str (self .nice_settings .verbose )
222+ xml_params .find ("verbose" ).text = str (self .nice_settings .verbose )
200223 equilibrium = self ._create_equilibrium ()
201224 if not self .communicator .running :
202- await self .communicator .run ()
225+ await self .communicator .run (
226+ is_direct_mode = self .nice_settings .is_direct_mode
227+ )
203228 await self .communicator .submit (
204- ET .tostring (self . xml_params , encoding = "unicode" ),
229+ ET .tostring (xml_params , encoding = "unicode" ),
205230 equilibrium .serialize (),
206231 self .pf_active .serialize (),
207232 self .pf_passive .serialize (),
@@ -210,7 +235,9 @@ async def submit(self, event=None):
210235 )
211236 self .coil_currents .sync_ui_with_pf_active (self .communicator .pf_active )
212237
213- async def stop_nice (self , event ):
238+ @param .depends ("nice_settings.mode" , watch = True )
239+ async def stop_nice (self , event = None ):
240+ logger .info ("Stopping NICE..." )
214241 await self .communicator .close ()
215242
216243 def __panel__ (self ):
0 commit comments