Skip to content

Commit 0e73425

Browse files
committed
clean up
1 parent b5b995a commit 0e73425

File tree

2 files changed

+99
-43
lines changed

2 files changed

+99
-43
lines changed

waveform_editor/gui/shape_editor.py

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

44
import imas
5-
import numpy as np
65
import panel as pn
76
import param
87
from imas.ids_toplevel import IDSToplevel

waveform_editor/shape_editor/coil_currents.py

Lines changed: 99 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@
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

1412
class CoilCurrents(Viewer):
1513
coil_ui = param.List(
1614
doc="List of tuples containing the checkboxes and sliders for the coil currents"
1715
)
18-
export_time = param.Number(doc="Time to export coil currents to")
16+
export_time = param.Number(
17+
doc="Select a time at which coil currents will be saved to waveforms"
18+
)
1919

2020
def __init__(self, main_gui):
2121
super().__init__()
@@ -36,10 +36,13 @@ def __init__(self, main_gui):
3636
confirm_button = pn.widgets.Button(
3737
on_click=lambda event: self._store_coil_currents(),
3838
name="Save Currents as Waveforms",
39-
margin=30,
39+
margin=(30, 0, 0, 0),
4040
)
4141
self.panel = pn.Column(
42-
pn.Row(export_time_input, confirm_button, no_ids_message),
42+
pn.Row(
43+
export_time_input, confirm_button, visible=self.param.coil_ui.rx.bool()
44+
),
45+
no_ids_message,
4346
guide_message,
4447
self.grid_box,
4548
)
@@ -78,65 +81,119 @@ def create_ui(self, pf_active):
7881
self.coil_ui = new_coil_ui
7982

8083
def _store_coil_currents(self):
84+
"""Store the current values from the coil UI sliders into the waveform
85+
configuration.
86+
"""
8187
coil_currents = self._get_currents()
8288
config = self.main_gui.config
8389
new_waveforms_created = False
90+
group_name = "Coil Currents"
8491

85-
for i in range(len(self.coil_ui)):
86-
name = f"pf_active/coil({i + 1})/current/data"
87-
if name in self.main_gui.config.waveform_map:
88-
tendencies = self.main_gui.config[name].tendencies
89-
if tendencies:
90-
end_time = tendencies[-1].end
91-
if end_time >= self.export_time:
92-
pn.state.notifications.error(
93-
"Export time must be later than the end of any existing waveforms"
94-
)
95-
return
92+
if not self._has_valid_export_time():
93+
return
9694

9795
for i, current in enumerate(coil_currents):
9896
name = f"pf_active/coil({i + 1})/current/data"
99-
eps = 1e-100
100-
# Piecewise tendencies must contain at least two points
101-
new_piecewise = f"- {{type: piecewise, time: [{self.export_time}, {self.export_time + eps}], value: [{current}, {current}]}}"
102-
if not name in config.waveform_map:
103-
group_name = "Coil Currents"
97+
if name not in config.waveform_map:
10498
if group_name not in config.groups:
10599
config.add_group(group_name, [])
106-
waveform = config.parser.parse_waveform(f"{name}:\n{new_piecewise}")
107-
config.add_waveform(waveform, [group_name])
100+
self._create_new_waveform(config, name, current, group_name)
108101
new_waveforms_created = True
109102
else:
110103
waveform = config[name]
111104
if isinstance(waveform, DerivedWaveform):
112-
pn.state.error(
113-
f"Could not store coil current in {name}, because it is a derived waveform"
105+
pn.state.notifications.error(
106+
f"Could not store coil current in waveform {name!r}, "
107+
"because it is a derived waveform"
114108
)
115109
continue
116-
117-
last_tendency = waveform.tendencies[-1]
118-
if isinstance(last_tendency, PiecewiseLinearTendency):
119-
waveform.yaml[-1]["time"].append(float(self.export_time))
120-
waveform.yaml[-1]["value"].append(float(current))
121-
yaml_str = f"{name}:\n{waveform.get_yaml_string()}"
122-
else:
123-
end = waveform.tendencies[-1].end
124-
append_new_piecewise = f"- {{type: piecewise, time: [{end}, {self.export_time}], value: [{current}, {current}]}}"
125-
yaml_str = (
126-
f"{name}:\n{waveform.get_yaml_string()}{append_new_piecewise}"
127-
)
128-
new_waveform = config.parse_waveform(yaml_str)
129-
config.replace_waveform(new_waveform)
110+
self._append_to_existing_waveform(config, name, current)
130111

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

141198
def fill_pf_active(self, pf_active):
142199
"""Update the coil currents of the provided pf_active IDS. Only coils with
@@ -151,11 +208,11 @@ def fill_pf_active(self, pf_active):
151208
pf_active.coil[i].current.data = np.array([slider.value])
152209

153210
def _get_currents(self):
211+
"""Returns the coil current values in a list."""
154212
coil_currents = []
155213
for coil_ui in self.coil_ui:
156214
_, slider = coil_ui.objects
157215
coil_currents.append(slider.value)
158-
159216
return coil_currents
160217

161218
def sync_ui_with_pf_active(self, pf_active):

0 commit comments

Comments
 (0)