Skip to content

Commit 6132481

Browse files
committed
clean up
1 parent d9c282f commit 6132481

File tree

2 files changed

+99
-48
lines changed

2 files changed

+99
-48
lines changed

waveform_editor/gui/shape_editor.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import xml.etree.ElementTree as ET
44

55
import imas
6-
import numpy as np
76
import panel as pn
87
import param
98
from imas.ids_toplevel import IDSToplevel

waveform_editor/shape_editor/coil_currents.py

Lines changed: 99 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
from panel.viewable import Viewer
77

88
from waveform_editor.derived_waveform import DerivedWaveform
9-
from waveform_editor.tendencies.linear import LinearTendency
109
from waveform_editor.tendencies.piecewise import PiecewiseLinearTendency
11-
from waveform_editor.waveform import Waveform
1210

1311
from waveform_editor.settings import settings
1412

@@ -17,7 +15,9 @@ class CoilCurrents(Viewer):
1715
coil_ui = param.List(
1816
doc="List of tuples containing the checkboxes and sliders for the coil currents"
1917
)
20-
export_time = param.Number(doc="Time to export coil currents to")
18+
export_time = param.Number(
19+
doc="Select a time at which coil currents will be saved to waveforms"
20+
)
2121

2222
def __init__(self, main_gui, **params):
2323
super().__init__(**params)
@@ -39,19 +39,17 @@ def __init__(self, main_gui, **params):
3939
confirm_button = pn.widgets.Button(
4040
on_click=lambda event: self._store_coil_currents(),
4141
name="Save Currents as Waveforms",
42-
margin=30,
42+
margin=(30, 0, 0, 0),
4343
)
4444
self.panel = pn.Column(
45-
pn.Row(export_time_input, confirm_button, no_ids_message),
45+
pn.Row(
46+
export_time_input, confirm_button, visible=self.param.coil_ui.rx.bool()
47+
),
48+
no_ids_message,
4649
guide_message,
4750
self.sliders_ui,
48-
self.modal,
4951
)
5052

51-
def _open_modal(self):
52-
self._coil_currents_valid()
53-
self.modal.show()
54-
5553
@param.depends("export_time", watch=True)
5654
def _coil_currents_valid(self):
5755
self.coil_export_valid = True
@@ -100,65 +98,119 @@ def create_ui(self, pf_active):
10098
self.coil_ui = new_coil_ui
10199

102100
def _store_coil_currents(self):
101+
"""Store the current values from the coil UI sliders into the waveform
102+
configuration.
103+
"""
103104
coil_currents = self._get_currents()
104105
config = self.main_gui.config
105106
new_waveforms_created = False
107+
group_name = "Coil Currents"
106108

107-
for i in range(len(self.coil_ui)):
108-
name = f"pf_active/coil({i + 1})/current/data"
109-
if name in self.main_gui.config.waveform_map:
110-
tendencies = self.main_gui.config[name].tendencies
111-
if tendencies:
112-
end_time = tendencies[-1].end
113-
if end_time >= self.export_time:
114-
pn.state.notifications.error(
115-
"Export time must be later than the end of any existing waveforms"
116-
)
117-
return
109+
if not self._has_valid_export_time():
110+
return
118111

119112
for i, current in enumerate(coil_currents):
120113
name = f"pf_active/coil({i + 1})/current/data"
121-
eps = 1e-100
122-
# Piecewise tendencies must contain at least two points
123-
new_piecewise = f"- {{type: piecewise, time: [{self.export_time}, {self.export_time + eps}], value: [{current}, {current}]}}"
124-
if not name in config.waveform_map:
125-
group_name = "Coil Currents"
114+
if name not in config.waveform_map:
126115
if group_name not in config.groups:
127116
config.add_group(group_name, [])
128-
waveform = config.parser.parse_waveform(f"{name}:\n{new_piecewise}")
129-
config.add_waveform(waveform, [group_name])
117+
self._create_new_waveform(config, name, current, group_name)
130118
new_waveforms_created = True
131119
else:
132120
waveform = config[name]
133121
if isinstance(waveform, DerivedWaveform):
134-
pn.state.error(
135-
f"Could not store coil current in {name}, because it is a derived waveform"
122+
pn.state.notifications.error(
123+
f"Could not store coil current in waveform {name!r}, "
124+
"because it is a derived waveform"
136125
)
137126
continue
138-
139-
last_tendency = waveform.tendencies[-1]
140-
if isinstance(last_tendency, PiecewiseLinearTendency):
141-
waveform.yaml[-1]["time"].append(float(self.export_time))
142-
waveform.yaml[-1]["value"].append(float(current))
143-
yaml_str = f"{name}:\n{waveform.get_yaml_string()}"
144-
else:
145-
end = waveform.tendencies[-1].end
146-
append_new_piecewise = f"- {{type: piecewise, time: [{end}, {self.export_time}], value: [{current}, {current}]}}"
147-
yaml_str = (
148-
f"{name}:\n{waveform.get_yaml_string()}{append_new_piecewise}"
149-
)
150-
new_waveform = config.parse_waveform(yaml_str)
151-
config.replace_waveform(new_waveform)
127+
self._append_to_existing_waveform(config, name, current)
152128

153129
if new_waveforms_created:
154130
self.main_gui.selector.refresh()
155131
pn.state.notifications.warning(
156-
f"Could not find an existing waveform to store the coil current. A new waveform is created in the {group_name!r} group"
132+
"Could not find an existing waveform to store the coil current. "
133+
f"New waveform(s) are created in the {group_name!r} group"
157134
)
158135
else:
159136
pn.state.notifications.success(
160-
"The coil currents were appended to their respective waveforms."
137+
"The values of the coil currents were appended to their respective "
138+
"waveforms."
139+
)
140+
141+
def _append_to_existing_waveform(self, config, name, current):
142+
"""Append coil current value to an existing waveform. If the last tendency is a
143+
piecewise tendency, it is extended, otherwise a new piecewise tendency
144+
is added.
145+
146+
Args:
147+
config: The waveform configuration.
148+
name: Name of the waveform.
149+
current: Coil current value to append.
150+
"""
151+
waveform = config[name]
152+
last_tendency = waveform.tendencies[-1]
153+
154+
# Either append to existing piecewise linear tendency, or create new
155+
# piecewise linear tendency
156+
if isinstance(last_tendency, PiecewiseLinearTendency):
157+
waveform.yaml[-1]["time"].append(float(self.export_time))
158+
waveform.yaml[-1]["value"].append(float(current))
159+
yaml_str = f"{name}:\n{waveform.get_yaml_string()}"
160+
else:
161+
end = waveform.tendencies[-1].end
162+
new_piecewise = (
163+
f"- {{type: piecewise, time: [{end}, {self.export_time}], "
164+
f"value: [{current}, {current}]}}"
161165
)
166+
yaml_str = f"{name}:\n{waveform.get_yaml_string()}{new_piecewise}"
167+
168+
new_waveform = config.parse_waveform(yaml_str)
169+
config.replace_waveform(new_waveform)
170+
171+
def _create_new_waveform(self, config, name, current, group_name):
172+
"""Create a new waveform for a coil current when none exists.
173+
174+
Args:
175+
config: The waveform configuration.
176+
name: Name of the waveform.
177+
current: Coil current value to append.
178+
group_name: Name of the group to place the new waveform in.
179+
"""
180+
# Piecewise tendencies must contain at least two points
181+
eps = 1e-9
182+
new_piecewise = (
183+
f"- {{type: piecewise, time: [{self.export_time - eps}, "
184+
f"{self.export_time}], value: [{current}, {current}]}}"
185+
)
186+
waveform = config.parser.parse_waveform(f"{name}:\n{new_piecewise}")
187+
config.add_waveform(waveform, [group_name])
188+
189+
def _has_valid_export_time(self):
190+
"""Check whether the export time is later than the last tendency endpoint
191+
in all existing coil current waveforms.
192+
193+
Returns:
194+
True if export time is valid, False otherwise.
195+
"""
196+
latest_time = None
197+
for i in range(len(self.coil_ui)):
198+
name = f"pf_active/coil({i + 1})/current/data"
199+
if name in self.main_gui.config.waveform_map:
200+
tendencies = self.main_gui.config[name].tendencies
201+
if tendencies:
202+
end_time = tendencies[-1].end
203+
if latest_time is None or end_time > latest_time:
204+
latest_time = end_time
205+
206+
if latest_time is not None and latest_time >= self.export_time:
207+
pn.state.notifications.error(
208+
f"Invalid export time: {self.export_time}. It must be greater than the "
209+
f"last endpoint of existing coil current waveforms ({latest_time})."
210+
)
211+
return False
212+
213+
return True
162214

163215
def fill_pf_active(self, pf_active):
164216
"""Update the coil currents of the provided pf_active IDS. Only coils with
@@ -172,11 +224,11 @@ def fill_pf_active(self, pf_active):
172224
pf_active.coil[i].current.data = np.array([slider.value])
173225

174226
def _get_currents(self):
227+
"""Returns the coil current values in a list."""
175228
coil_currents = []
176229
for coil_ui in self.coil_ui:
177230
_, slider = coil_ui.objects
178231
coil_currents.append(slider.value)
179-
180232
return coil_currents
181233

182234
def sync_ui_with_pf_active(self, pf_active):

0 commit comments

Comments
 (0)