diff --git a/docs/source/shape_editor_install.rst b/docs/source/shape_editor_install.rst
index 232278cb..b568ddf5 100644
--- a/docs/source/shape_editor_install.rst
+++ b/docs/source/shape_editor_install.rst
@@ -87,6 +87,7 @@ https://blfauger.gitlabpages.inria.fr/nice/install.html.
cp Makefile.TEMPLATE Makefile
make -j
make nice_imas_inv_muscle3
+ make nice_imas_dir_muscle3
-If this was successful, you should find the program ``nice_imas_inv_muscle3`` in the
-``nice/run`` folder.
+If this was successful, you should find the programs ``nice_imas_inv_muscle3`` and
+``nice_imas_dir_muscle3`` in the ``nice/run`` folder.
diff --git a/waveform_editor/gui/shape_editor.py b/waveform_editor/gui/shape_editor.py
index e7b6228f..20001580 100644
--- a/waveform_editor/gui/shape_editor.py
+++ b/waveform_editor/gui/shape_editor.py
@@ -1,4 +1,5 @@
import importlib.resources
+import logging
import xml.etree.ElementTree as ET
import imas
@@ -14,6 +15,8 @@
from waveform_editor.shape_editor.plasma_properties import PlasmaProperties
from waveform_editor.shape_editor.plasma_shape import PlasmaShape
+logger = logging.getLogger(__name__)
+
def _reactive_title(title, is_valid):
return title if is_valid else f"{title} ⚠️"
@@ -37,40 +40,52 @@ def __init__(self):
self.plasma_properties = PlasmaProperties()
self.coil_currents = CoilCurrents()
self.nice_plotter = NicePlotter(
- self.communicator, self.plasma_shape, self.plasma_properties
+ communicator=self.communicator,
+ plasma_shape=self.plasma_shape,
+ plasma_properties=self.plasma_properties,
)
self.nice_settings = settings.nice
- self.xml_params = ET.fromstring(
+ self.xml_params_inv = ET.fromstring(
+ importlib.resources.files("waveform_editor.shape_editor.xml_param")
+ .joinpath("inverse_param.xml")
+ .read_text()
+ )
+ self.xml_params_dir = ET.fromstring(
importlib.resources.files("waveform_editor.shape_editor.xml_param")
- .joinpath("param.xml")
+ .joinpath("direct_param.xml")
.read_text()
)
# UI Configuration
button_start = pn.widgets.Button(name="Run", on_click=self.submit)
button_start.disabled = (
- self.plasma_shape.param.has_shape.rx.not_()
+ (
+ self.plasma_shape.param.has_shape.rx.not_()
+ & self.nice_settings.param.is_inverse_mode.rx()
+ )
| self.plasma_properties.param.has_properties.rx.not_()
- | param.rx(self.nice_settings.required_params_filled).rx.not_()
+ | self.nice_settings.param.are_required_filled.rx.not_()
)
button_stop = pn.widgets.Button(name="Stop", on_click=self.stop_nice)
- buttons = pn.Row(button_start, button_stop)
+ nice_mode_radio = pn.widgets.RadioBoxGroup.from_param(
+ self.nice_settings.param.mode, inline=True, margin=(15, 20, 0, 20)
+ )
+ buttons = pn.Row(button_start, button_stop, nice_mode_radio)
# Accordion does not allow dynamic titles, so use separate card for each option
options = pn.Column(
self._create_card(
self.nice_settings.panel,
"NICE Configuration",
- is_valid=param.rx(self.nice_settings.required_params_filled),
- ),
- self._create_card(
- pn.Param(self.nice_plotter, show_name=False), "Plotting Parameters"
+ is_valid=self.nice_settings.param.are_required_filled.rx(),
),
+ self._create_card(self.nice_plotter, "Plotting Parameters"),
self._create_card(
self.plasma_shape,
"Plasma Shape",
is_valid=self.plasma_shape.param.has_shape,
+ visible=self.nice_settings.param.is_inverse_mode.rx(),
),
self._create_card(
pn.Column(self.plasma_properties, self.nice_plotter.profiles_pane),
@@ -91,7 +106,7 @@ def __init__(self):
),
)
- def _create_card(self, panel_object, title, is_valid=None):
+ def _create_card(self, panel_object, title, is_valid=None, visible=True):
"""Create a collapsed card containing a panel object and a title.
Args:
@@ -99,6 +114,7 @@ def _create_card(self, panel_object, title, is_valid=None):
title: The title to give the card.
is_valid: If supplied, binds the card title to update reactively using
`_reactive_title`.
+ visible: Whether the card is visible.
"""
if is_valid:
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):
title=title,
sizing_mode="stretch_width",
collapsed=True,
+ visible=visible,
)
return card
@@ -169,9 +186,10 @@ def _create_equilibrium(self):
equilibrium.time_slice.resize(1)
equilibrium.vacuum_toroidal_field.b0.resize(1)
- # Fill plasma shape
- equilibrium.time_slice[0].boundary.outline.r = self.plasma_shape.outline_r
- equilibrium.time_slice[0].boundary.outline.z = self.plasma_shape.outline_z
+ # Only fill plasma shape for NICE inverse mode
+ if self.nice_settings.is_inverse_mode:
+ equilibrium.time_slice[0].boundary.outline.r = self.plasma_shape.outline_r
+ equilibrium.time_slice[0].boundary.outline.z = self.plasma_shape.outline_z
# Fill plasma properties
equilibrium.vacuum_toroidal_field.r0 = self.plasma_properties.r0
@@ -194,14 +212,21 @@ async def submit(self, event=None):
description IDSs and an input equilibrium IDS."""
self.coil_currents.fill_pf_active(self.pf_active)
+ if self.nice_settings.is_direct_mode:
+ xml_params = self.xml_params_dir
+ else:
+ xml_params = self.xml_params_inv
+ self.coil_currents.update_fixed_coils_in_xml(xml_params)
+
# Update XML parameters:
- self.coil_currents.update_fixed_coils_in_xml(self.xml_params)
- self.xml_params.find("verbose").text = str(self.nice_settings.verbose)
+ xml_params.find("verbose").text = str(self.nice_settings.verbose)
equilibrium = self._create_equilibrium()
if not self.communicator.running:
- await self.communicator.run()
+ await self.communicator.run(
+ is_direct_mode=self.nice_settings.is_direct_mode
+ )
await self.communicator.submit(
- ET.tostring(self.xml_params, encoding="unicode"),
+ ET.tostring(xml_params, encoding="unicode"),
equilibrium.serialize(),
self.pf_active.serialize(),
self.pf_passive.serialize(),
@@ -210,7 +235,9 @@ async def submit(self, event=None):
)
self.coil_currents.sync_ui_with_pf_active(self.communicator.pf_active)
- async def stop_nice(self, event):
+ @param.depends("nice_settings.mode", watch=True)
+ async def stop_nice(self, event=None):
+ logger.info("Stopping NICE...")
await self.communicator.close()
def __panel__(self):
diff --git a/waveform_editor/settings.py b/waveform_editor/settings.py
index ab09f606..ce030efa 100644
--- a/waveform_editor/settings.py
+++ b/waveform_editor/settings.py
@@ -16,17 +16,23 @@
class NiceSettings(param.Parameterized):
- REQUIRED = (
- "executable",
+ INVERSE_MODE = "NICE Inverse"
+ DIRECT_MODE = "NICE Direct"
+
+ BASE_REQUIRED = (
"md_pf_active",
"md_pf_passive",
"md_wall",
"md_iron_core",
)
- executable = param.String(
- label="NICE executable path",
+ inv_executable = param.String(
+ label="NICE inverse executable path",
doc="Path to NICE inverse IMAS MUSCLE3 executable",
)
+ dir_executable = param.String(
+ label="NICE direct executable path",
+ doc="Path to NICE direct IMAS MUSCLE3 executable",
+ )
environment = param.Dict(
default={},
label="NICE environment variables",
@@ -37,10 +43,32 @@ class NiceSettings(param.Parameterized):
md_wall = param.String(label="'wall' machine description URI")
md_iron_core = param.String(label="'iron_core' machine description URI")
verbose = param.Integer(label="NICE verbosity (set to 1 for more verbose output)")
+ mode = param.Selector(
+ objects=[INVERSE_MODE, DIRECT_MODE], default=INVERSE_MODE, precedence=-1
+ )
+ are_required_filled = param.Boolean(precedence=-1)
+ is_direct_mode = param.Boolean(precedence=-1)
+ is_inverse_mode = param.Boolean(precedence=-1)
+
+ @param.depends("mode", watch=True, on_init=True)
+ def set_mode_flags(self):
+ self.is_direct_mode = self.mode == self.DIRECT_MODE
+ self.is_inverse_mode = self.mode == self.INVERSE_MODE
+
+ @param.depends(
+ *BASE_REQUIRED, "inv_executable", "dir_executable", "mode", watch=True
+ )
+ def check_required_params_filled(self):
+ base_ready = all(getattr(self, p) for p in self.BASE_REQUIRED)
- @param.depends(*REQUIRED)
- def required_params_filled(self):
- return all(getattr(self, required) for required in self.REQUIRED)
+ if not base_ready:
+ self.are_required_filled = False
+ return
+
+ if self.mode == self.INVERSE_MODE:
+ self.are_required_filled = bool(self.inv_executable)
+ else:
+ self.are_required_filled = bool(self.dir_executable)
def apply_settings(self, params):
"""Update parameters from a dictionary, skipping unknown keys."""
@@ -51,24 +79,33 @@ def apply_settings(self, params):
self.param.update(**params)
def to_dict(self):
- """Returns a dictionary representation of current parameter values."""
- return {p: getattr(self, p) for p in self.param if p != "name"}
+ """Returns a dictionary representation of current parameter values, excluding
+ params with a precendence of -1."""
+ result = {}
+ for p in self.param:
+ param_obj = self.param[p]
+ if p != "name" and param_obj.precedence != -1:
+ result[p] = getattr(self, p)
+ return result
def panel(self):
items = []
for p in self.param:
if p == "name":
- pass
- elif p in self.REQUIRED:
- items.append(
- pn.Row(
- pn.Param(self.param[p], show_name=False),
- WarningIndicator(visible=self.param[p].rx.not_()),
- )
- )
- else:
- items.append(pn.Param(self.param[p], show_name=False))
+ continue
+
+ # Add warning indicator if required parameter is not filled
+ is_inv_required = p == "inv_executable" and self.is_inverse_mode
+ is_dir_required = p == "dir_executable" and self.is_direct_mode
+ is_base_required = p in self.BASE_REQUIRED
+
+ row_content = [pn.Param(self.param[p], show_name=False)]
+ if is_inv_required or is_dir_required or is_base_required:
+ warning = WarningIndicator(visible=self.param[p].rx.not_())
+ row_content.append(warning)
+
+ items.append(pn.Row(*row_content))
return pn.Column(*items)
diff --git a/waveform_editor/shape_editor/coil_currents.py b/waveform_editor/shape_editor/coil_currents.py
index d561b3e5..0f009d14 100644
--- a/waveform_editor/shape_editor/coil_currents.py
+++ b/waveform_editor/shape_editor/coil_currents.py
@@ -5,14 +5,17 @@
import param
from panel.viewable import Viewer
+from waveform_editor.settings import settings
+
class CoilCurrents(Viewer):
coil_ui = param.List(
doc="List of tuples containing the checkboxes and sliders for the coil currents"
)
- def __init__(self):
- super().__init__()
+ def __init__(self, **params):
+ super().__init__(**params)
+ self.nice_settings = settings.nice
self.sliders_ui = pn.Column(visible=self.param.coil_ui.rx.bool())
guide_message = pn.pane.Markdown(
"_To fix a coil to a specific current, enable the checkbox and provide "
@@ -44,13 +47,15 @@ def create_ui(self, pf_active):
new_coil_ui = []
for coil in pf_active.coil:
coil_current = coil.current
- checkbox = pn.widgets.Checkbox(value=False, margin=(30, 10, 10, 10))
+ checkbox = pn.widgets.Checkbox(
+ margin=(30, 10, 10, 10),
+ disabled=self.nice_settings.param.is_direct_mode,
+ )
slider = pn.widgets.EditableFloatSlider(
name=f"{coil.name} Current [{coil_current.metadata.units}]",
value=coil_current.data[0] if coil_current.data.has_value else 0.0,
start=-5e4,
end=5e4,
- disabled=checkbox.param.value.rx.not_(),
format="0",
width=450,
)
@@ -67,9 +72,8 @@ def fill_pf_active(self, pf_active):
pf_active: pf_active IDS to update the coil currents for.
"""
for i, coil_ui in enumerate(self.coil_ui):
- checkbox, slider = coil_ui.objects
- if checkbox.value:
- pf_active.coil[i].current.data = np.array([slider.value])
+ _, slider = coil_ui.objects
+ pf_active.coil[i].current.data = np.array([slider.value])
def sync_ui_with_pf_active(self, pf_active):
"""Synchronize UI sliders with the current values from the pf_active IDS.
diff --git a/waveform_editor/shape_editor/nice_integration.py b/waveform_editor/shape_editor/nice_integration.py
index f117171c..d4345ce8 100644
--- a/waveform_editor/shape_editor/nice_integration.py
+++ b/waveform_editor/shape_editor/nice_integration.py
@@ -1,4 +1,4 @@
-"""Module that enables running the NICE inverse equilibrium solver through MUSCLE3."""
+"""Module that enables running the NICE equilibrium solver through MUSCLE3."""
import asyncio
import multiprocessing
@@ -18,7 +18,8 @@
from waveform_editor.settings import settings
-_muscle3_configuration = """
+# YMMSL configuration for NICE inverse mode
+_muscle3_inv_configuration = """
ymmsl_version: v0.1
model:
name: shape_editor
@@ -42,9 +43,33 @@
nice_inv.xml_path: {xml_path}
"""
+# YMMSL configuration for NICE direct mode
+_muscle3_dir_configuration = """
+ymmsl_version: v0.1
+model:
+ name: shape_editor
+ components:
+ shape_editor:
+ implementation: shape_editor
+ nice_dir:
+ implementation: nice_dir
+
+ conduits:
+ shape_editor.equilibrium_out: nice_dir.equilibrium_in
+ shape_editor.pf_passive_out: nice_dir.pf_passive_in
+ shape_editor.pf_active_out: nice_dir.pf_active_in
+ shape_editor.iron_core_out: nice_dir.iron_core_in
+ shape_editor.wall_out: nice_dir.wall_in
+ nice_dir.equilibrium_out: shape_editor.equilibrium_in
+
+settings:
+ muscle_profile_level: none # Disable profiling
+ nice_dir.xml_path: {xml_path}
+"""
+
class NiceIntegration(param.Parameterized):
- """Main API for running NICE, submitting inverse problems and getting the resulting
+ """Main API for running NICE, submitting problems and getting the resulting
equilibrium back.
"""
@@ -118,7 +143,7 @@ async def close(self):
self.closing = self.running = False
self._update_state()
- async def run(self):
+ async def run(self, is_direct_mode=False):
"""Start NICE and the controlling processes."""
if self.running:
raise RuntimeError("Already running!")
@@ -130,7 +155,7 @@ async def run(self):
self.manager_pipe, pipe = multiprocessing.Pipe()
self.manager = multiprocessing.Process(
target=run_muscle_manager,
- args=[pipe, self.xml_config_file.name],
+ args=[pipe, self.xml_config_file.name, is_direct_mode],
name="MUSCLE Manager",
)
self.manager.start()
@@ -140,7 +165,7 @@ async def run(self):
self.communicator_pipe, pipe = multiprocessing.Pipe()
self.communicator = multiprocessing.Process(
target=run_muscle3_communicator,
- args=[manager_location, pipe],
+ args=[manager_location, pipe, is_direct_mode],
name="NICE Communicator",
)
self.communicator.start()
@@ -148,15 +173,22 @@ async def run(self):
# NICE
nice_env = os.environ.copy()
nice_env.update(settings.nice.environment)
- nice_env["MUSCLE_INSTANCE"] = "nice_inv"
nice_env["MUSCLE_MANAGER"] = manager_location
- self.terminal.write(f"{os.getcwd()}$ {settings.nice.executable}\n")
+ if is_direct_mode:
+ executable = settings.nice.dir_executable
+ nice_env["MUSCLE_INSTANCE"] = "nice_dir"
+ else:
+ executable = settings.nice.inv_executable
+ nice_env["MUSCLE_INSTANCE"] = "nice_inv"
+
+ self.terminal.write(f"{os.getcwd()}$ {executable}\n")
+
loop = asyncio.get_running_loop()
try:
self.nice_transport, self.nice_protocol = await loop.subprocess_exec(
self.create_communicator_protocol,
- settings.nice.executable,
+ executable,
env=nice_env,
stdin=subprocess.DEVNULL,
)
@@ -267,6 +299,7 @@ def pipe_data_received(self, fd, data):
def run_muscle3_communicator(
server_location: str,
pipe: multiprocessing.connection.Connection,
+ is_direct_mode: bool,
):
"""Run MUSCLE3 actor for communicating with NICE."""
os.environ["MUSCLE_INSTANCE"] = "shape_editor"
@@ -280,8 +313,11 @@ def run_muscle3_communicator(
"wall_out",
"iron_core_out",
],
- Operator.S: ["equilibrium_in", "pf_active_in"],
+ Operator.S: ["equilibrium_in"],
}
+ if not is_direct_mode:
+ ports[Operator.S].append("pf_active_in")
+
instance = Instance(ports)
while instance.reuse_instance():
@@ -299,13 +335,19 @@ def run_muscle3_communicator(
# Wait for nice to process
eq = instance.receive("equilibrium_in").data
- pfa = instance.receive("pf_active_in").data
+ if not is_direct_mode:
+ pfa = instance.receive("pf_active_in").data
pipe.send((eq, pfa))
-def run_muscle_manager(pipe: multiprocessing.connection.Connection, xml_path: str):
- """Run the muscle_manager"""
- config = ymmsl.load(_muscle3_configuration.format(xml_path=xml_path))
+def run_muscle_manager(
+ pipe: multiprocessing.connection.Connection, xml_path: str, is_direct_mode: bool
+):
+ """Run the muscle_manager with a given configuration."""
+ config_str = (
+ _muscle3_dir_configuration if is_direct_mode else _muscle3_inv_configuration
+ )
+ config = ymmsl.load(config_str.format(xml_path=xml_path))
manager = Manager(config)
server_location = manager.get_server_location()
pipe.send(server_location)
diff --git a/waveform_editor/shape_editor/nice_plotter.py b/waveform_editor/shape_editor/nice_plotter.py
index d96caaec..f9f2b021 100644
--- a/waveform_editor/shape_editor/nice_plotter.py
+++ b/waveform_editor/shape_editor/nice_plotter.py
@@ -8,7 +8,9 @@
import param
import scipy
from imas.ids_toplevel import IDSToplevel
+from panel.viewable import Viewer
+from waveform_editor.settings import NiceSettings, settings
from waveform_editor.shape_editor.nice_integration import NiceIntegration
from waveform_editor.shape_editor.plasma_properties import PlasmaProperties
from waveform_editor.shape_editor.plasma_shape import PlasmaShape
@@ -17,13 +19,14 @@
logger = logging.getLogger(__name__)
-class NicePlotter(param.Parameterized):
+class NicePlotter(Viewer):
# Input data, use negative precedence to hide from the UI
communicator = param.ClassSelector(class_=NiceIntegration, precedence=-1)
wall = param.ClassSelector(class_=IDSToplevel, precedence=-1)
pf_active = param.ClassSelector(class_=IDSToplevel, precedence=-1)
plasma_shape = param.ClassSelector(class_=PlasmaShape, precedence=-1)
plasma_properties = param.ClassSelector(class_=PlasmaProperties, precedence=-1)
+ nice_settings = param.ClassSelector(class_=NiceSettings, precedence=-1)
# Plot parameters
show_contour = param.Boolean(default=True, label="Show contour lines")
@@ -45,13 +48,8 @@ class NicePlotter(param.Parameterized):
PROFILE_WIDTH = 350
PROFILE_HEIGHT = 350
- def __init__(self, communicator, plasma_shape, plasma_properties, **params):
- super().__init__(
- **params,
- communicator=communicator,
- plasma_shape=plasma_shape,
- plasma_properties=plasma_properties,
- )
+ def __init__(self, **params):
+ super().__init__(**params)
self.DEFAULT_OPTS = hv.opts.Overlay(
xlim=(0, 13),
ylim=(-10, 10),
@@ -59,6 +57,7 @@ def __init__(self, communicator, plasma_shape, plasma_properties, **params):
xlabel="r [m]",
ylabel="z [m]",
)
+ self.nice_settings = settings.nice
self.CONTOUR_OPTS = hv.opts.Contours(
cmap="viridis",
colorbar=True,
@@ -90,6 +89,15 @@ def __init__(self, communicator, plasma_shape, plasma_properties, **params):
self.profiles_pane = pn.pane.HoloViews(
profiles_plot, width=self.PROFILE_WIDTH, height=self.PROFILE_HEIGHT
)
+ self.panel_layout = pn.Param(
+ self.param,
+ show_name=False,
+ widgets={
+ "show_desired_shape": {
+ "visible": self.nice_settings.param.is_inverse_mode
+ }
+ },
+ )
@pn.depends("plasma_properties.profile_updated")
def _plot_profiles(self):
@@ -124,9 +132,15 @@ def _plot_profiles(self):
hv.opts.Overlay(title="Plasma Profiles"), hv.opts.Curve(framewise=True)
)
- @pn.depends("plasma_shape.shape_updated", "show_desired_shape")
+ @pn.depends(
+ "plasma_shape.shape_updated", "show_desired_shape", "nice_settings.mode"
+ )
def _plot_plasma_shape(self):
- if not self.show_desired_shape or not self.plasma_shape.has_shape:
+ if (
+ self.nice_settings.is_direct_mode
+ or not self.show_desired_shape
+ or not self.plasma_shape.has_shape
+ ):
return hv.Overlay([hv.Curve([]).opts(self.DESIRED_SHAPE_OPTS)])
r = self.plasma_shape.outline_r
@@ -388,3 +402,6 @@ def _plot_xo_points(self):
hover_tooltips=[("", "X-point")],
)
return o_scatter * x_scatter
+
+ def __panel__(self):
+ return self.panel_layout
diff --git a/waveform_editor/shape_editor/xml_param/direct_param.xml b/waveform_editor/shape_editor/xml_param/direct_param.xml
new file mode 100644
index 00000000..2bb5615d
--- /dev/null
+++ b/waveform_editor/shape_editor/xml_param/direct_param.xml
@@ -0,0 +1,262 @@
+
+
+
+ 1
+
+ 0
+ 0
+ 11
+ 2
+ 0
+ 0
+ 1
+ 0
+ 2
+ 1
+ 0
+ 0
+ 0
+ 0
+ 1
+ 1
+ 0
+ 1
+ 40
+ 1.0e-10
+ 2
+ 0
+ 20
+ 1.0e-10
+ 40
+ 1.0e-10
+ 50
+ 1.0e-10
+ 1
+ 2.25
+ 6.2
+ 0.0
+ 0
+ 1
+ 4
+ 4.45 5.39 5.78 4.70
+ -3.5 -3.86 -3.20 -2.81
+ 5.1
+ -3.3
+ 0.0005
+ 0
+ 4
+ 2.44 1.91 1.94 2.44
+ 0.79 0.573 0.49 0.66
+ 2.18
+ 0.6
+ 0.00003
+ 1
+ 10
+ 6.0 6.2 6.2 6.4 6.6 6.6 6.4 6.4 6.2 6.0
+ 0.2 0.2 0.4 0.2 0.2 1.0 1.0 0.8 1.0 1.0
+ 6.1
+ 0.3
+ 0.0005
+ 0.002
+ 0.04
+ 0.01
+ 0.005
+ 0.005
+ 0.005
+ 0.005
+ 1
+ 17
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 17
+ 17
+ 50
+ 0
+ 6.2
+
+ 0
+ 11
+ 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
+ 2 0.6 1.4
+ 0
+ 11
+ 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
+ 2 0.4 1.4
+ 1
+
+ 0
+ 11
+ 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
+ 1e20
+ 4
+ 3 1 0 1
+
+ 0
+ 11
+ 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
+ 25
+ 1 1.5 0 1
+
+ 1.0e-1
+ 1 1 1 1 1 1 1 1 1 1 1
+ 1.0e12
+ 0.0e10
+ 1.0e-1
+ 1 1 1 1 1 1 1 1 1 1 1
+ 1.0e12
+ 1.0e-1
+ 1 1 1 1 1 1 1 1 1 1 1
+ 1.0e12
+ 1.0e3 1.0e3 1.0e0 1.0e12 1.0e0
+ 1.0e-1
+ 1 1 1 1 1 1 1 1 1 1 1 1
+ 0.0e20
+ 0.0e0
+
+ 0.1
+ 1e-3
+ 0.01
+ 0
+ 0
+ 0
+ 0
+ 0.01
+ 0.01
+ 0
+ 0
+ 0
+ 0
+ 0
+
+ 0.01
+ 0
+ 1e18
+ 0.1
+ 0
+ 0
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
+
+ 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
+
+
+ 0.195
+ 2.42e-20
+ 5.23e-19
+ 0.001
+ 0.1
+ 0
+ 0
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
+
+ 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
+ 0.001
+ 0.1
+ 0
+ 0
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
+
+
+ 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
+
+
+ 1 1 1
+
+ 1.0e3
+ 0.1
+ 0
+ 0
+ 0
+ 0
+
+ 0.001
+ 0.1
+ 0
+ 25
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 0 0
+
+ 13
+
+
+ 3.88 4.00 5.55 7.36 8.0 8.45 8.66 8.44 7.62 5.80 4.87 4.18 3.88
+ -2.53 -3.92 -4.65 -2.45 -1.4 -0.47 0.66 1.65 3.21 4.65 4.85 4.39 3.58
+ 0.05
+ 0
+ 0.15
+ 0.15
+ 0.05
+ 1
+ 0
+ 8
+ 0 1 2 3 4 5 6 7
+ 7
+ 1 2 3 4 5 6 7
+ 8
+ 0 1 2 3 4 5 6 7
+ 7
+ 1 2 3 4 5 6 7
+ 1
+ 0.05
+ 3
+ 0.1
+ 1.0e-6
+ 1.0e-3
+ 1
+ 60
+ 1
+
+ 0
+ 1.9
+ 6.2
+ 0.545
+ 1.8
+ 0.43
+ 5.089
+ -3.346
+ 96
+ 0
+
+ 3e7
+ 0
+ 14
+ 0 1 2 2 3 4 5 6 7 8 9 10 11 12
+ 13
+ 0 1 2 4 5 6 7 8 9 10 11 12 13
+ 2
+ 11 12
+ 0
+ 0 1 2 3 4 5 6 7 8 9 10
+
+
+ 2
+ 6
+ 0 0.2 0.4 0.6 0.8 1
+ 1.0
+ 1.0e-3
+ 0.0e12
+ 0.0e12
+ 1.0e-3
+
+ 0
+ 5
+
+ 0
+ 2
+ 10
+ 1
+ 20
+ 1.0e-3
+
+ 101
+
diff --git a/waveform_editor/shape_editor/xml_param/inverse_param.xml b/waveform_editor/shape_editor/xml_param/inverse_param.xml
new file mode 100644
index 00000000..864f91a5
--- /dev/null
+++ b/waveform_editor/shape_editor/xml_param/inverse_param.xml
@@ -0,0 +1,267 @@
+
+
+
+ 1
+
+ 0
+ 0
+ 31
+ 2
+ 0
+ 0
+ 1
+ 0
+ 2
+ 1
+ 0
+ 0
+ 0
+ 0
+ 1
+ 1
+ 0
+ 1
+ 40
+ 1.0e-10
+ 2
+ 0
+ 20
+ 1.0e-10
+ 40
+ 1.0e-10
+ 50
+ 1.0e-10
+ 1
+ 2.25
+ 6.2
+ 0.0
+ 0
+ 1
+ 4
+ 4.45 5.39 5.78 4.70
+ -3.5 -3.86 -3.20 -2.81
+ 5.1
+ -3.3
+ 0.0005
+ 0
+ 4
+ 2.44 1.91 1.94 2.44
+ 0.79 0.573 0.49 0.66
+ 2.18
+ 0.6
+ 0.00003
+ 1
+ 10
+ 6.0 6.2 6.2 6.4 6.6 6.6 6.4 6.4 6.2 6.0
+ 0.2 0.2 0.4 0.2 0.2 1.0 1.0 0.8 1.0 1.0
+ 6.1
+ 0.3
+ 0.0005
+ 0.002
+ 0.04
+ 0.01
+ 0.005
+ 0.005
+ 0.005
+ 0.005
+ 1
+ 17
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 17
+ 17
+ 1
+ 50
+ 0
+ 6.2
+
+ 0
+ 11
+ 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
+ 2 0.6 1.4
+ 0
+ 11
+ 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
+ 2 0.4 1.4
+ 1
+
+ 0
+ 11
+ 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
+ 1e20
+ 4
+ 3 1 0 1
+
+ 0
+ 11
+ 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
+ 25
+ 1 1.5 0 1
+
+ 1.0e-1
+ 1 1 1 1 1 1 1 1 1 1 1
+ 1.0e12
+ 0.0e10
+ 1.0e-1
+ 1 1 1 1 1 1 1 1 1 1 1
+ 1.0e12
+ 1.0e-1
+ 1 1 1 1 1 1 1 1 1 1 1
+ 1.0e12
+ 1.0e3 1.0e3 1.0e0 1.0e12 1.0e0
+ 1.0e-1
+ 1 1 1 1 1 1 1 1 1 1 1 1
+ 0.0e20
+ 0.0e0
+
+ 0.1
+ 1e-3
+ 0.01
+ 0
+ 0
+ 0
+ 0
+ 0.01
+ 0.01
+ 0
+ 0
+ 0
+ 0
+ 0
+
+ 0.01
+ 0
+ 1e18
+ 0.1
+ 0
+ 0
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
+
+ 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
+
+
+ 0.195
+ 2.42e-20
+ 5.23e-19
+ 0.001
+ 0.1
+ 0
+ 0
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
+
+ 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
+ 0.001
+ 0.1
+ 0
+ 0
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
+
+
+ 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
+
+
+ 1 1 1
+
+ 1.0e3
+ 0.1
+ 0
+ 0
+ 0
+ 0
+
+ 0.001
+ 0.1
+ 0
+ 25
+ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
+ 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 0 0
+
+ 13
+
+
+ 3.88 4.00 5.55 7.36 8.0 8.45 8.66 8.44 7.62 5.80 4.87 4.18 3.88
+ -2.53 -3.92 -4.65 -2.45 -1.4 -0.47 0.66 1.65 3.21 4.65 4.85 4.39 3.58
+ 0.05
+ 0
+ 0.15
+ 0.15
+ 0.05
+ 1
+ 0
+ 8
+ 0 1 2 3 4 5 6 7
+ 7
+ 1 2 3 4 5 6 7
+ 8
+ 0 1 2 3 4 5 6 7
+ 7
+ 1 2 3 4 5 6 7
+ 1
+ 0.05
+ 3
+ 0.1
+ 1.0e-6
+ 1.0e-3
+ 1
+ 60
+ 1
+
+ 0
+ 1.9
+ 6.2
+ 0.545
+ 1.8
+ 0.43
+ 5.089
+ -3.346
+ 96
+ 0
+
+
+
+
+ 3e5
+ 0
+ 14
+ 0 1 2 2 3 4 5 6 7 8 9 10 11 12
+ 13
+ 0 1 2 4 5 6 7 8 9 10 11 12 13
+
+ 2
+ 11 12
+ 0
+ 0 1 2 3 4 5 6 7 8 9 10
+
+
+ 2
+ 6
+ 0 0.2 0.4 0.6 0.8 1
+ 1.0
+ 1.0e-3
+ 0.0e12
+ 0.0e12
+ 1.0e-3
+
+ 0
+ 5
+
+ 0
+ 2
+ 10
+ 1
+ 20
+ 1.0e-3
+
+ 101
+
diff --git a/waveform_editor/shape_editor/xml_param/param.xml b/waveform_editor/shape_editor/xml_param/param.xml
deleted file mode 100644
index d8a25eb8..00000000
--- a/waveform_editor/shape_editor/xml_param/param.xml
+++ /dev/null
@@ -1,323 +0,0 @@
-
-
-
- 1
- 0
- 0
- 31
- 2
- 0
- 0
- 1
- 0
- 2
- 1
- 0
- 0
- 0
- 0
- 1
- 1
- 0
- 1
- 40
- 1.0e-10
- 2
- 0
- 20
- 1.0e-10
- 40
- 1.0e-10
- 50
- 1.0e-10
- 1
- 2.25
- 6.2
- 0.0
-
- 0
-
- 1
- 4
- 4.45 5.39 5.78 4.70
- -3.5 -3.86 -3.20 -2.81
- 5.1
- -3.3
- 0.0005
-
- 0
- 4
- 2.44 1.91 1.94 2.44
- 0.79 0.573 0.49 0.66
- 2.18
- 0.6
- 0.00003
-
- 1
- 10
- 6.0 6.2 6.2 6.4 6.6 6.6 6.4 6.4 6.2 6.0
- 0.2 0.2 0.4 0.2 0.2 1.0 1.0 0.8 1.0 1.0
- 6.1
- 0.3
- 0.0005
-
- 0.002
- 0.04
- 0.01
- 0.005
- 0.005
- 0.005
- 0.005
-
- 1
- 17
-
- 1
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
- 0
-
- 17
- 17
-
- 1
-
- 50
- 0
-
- 6.2
-
-
- 0
- 11
- 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
- 2 0.6 1.4
-
- 0
- 11
- 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
- 2 0.4 1.4
-
- 1
-
-
- 0
- 11
- 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
- 1e20
- 4
- 3 1 0 1
-
-
- 0
- 11
- 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
- 25
- 1 1.5 0 1
-
-
-
- 1.0e-1
- 1 1 1 1 1 1 1 1 1 1 1
- 1.0e12
- 0.0e10
-
- 1.0e-1
- 1 1 1 1 1 1 1 1 1 1 1
- 1.0e12
-
- 1.0e-1
- 1 1 1 1 1 1 1 1 1 1 1
- 1.0e12
- 1.0e3 1.0e3 1.0e0 1.0e12 1.0e0
-
- 1.0e-1
- 1 1 1 1 1 1 1 1 1 1 1 1
- 0.0e20
- 0.0e0
-
-
- 0.1
-
- 1e-3
- 0.01
- 0
- 0
- 0
- 0
-
- 0.01
- 0.01
- 0
- 0
- 0
- 0
- 0
-
-
-
- 0.01
- 0
-
- 1e18
- 0.1
- 0
- 0
- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
-
- 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
-
-
-
- 0.195
- 2.42e-20
- 5.23e-19
-
- 0.001
- 0.1
- 0
- 0
- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
-
- 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
-
- 0.001
- 0.1
- 0
- 0
- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
-
-
- 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
-
-
- 1 1 1
-
-
- 1.0e3
- 0.1
- 0
- 0
- 0
- 0
-
-
- 0.001
- 0.1
- 0
- 25
- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
- 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 0 0
-
-
-
-
- 13
-
-
- 3.88 4.00 5.55 7.36 8.0 8.45 8.66 8.44 7.62 5.80 4.87 4.18 3.88
- -2.53 -3.92 -4.65 -2.45 -1.4 -0.47 0.66 1.65 3.21 4.65 4.85 4.39 3.58
-
- 0.05
- 0
-
- 0.15
- 0.15
- 0.05
-
- 1
-
- 0
- 8
- 0 1 2 3 4 5 6 7
- 7
- 1 2 3 4 5 6 7
- 8
- 0 1 2 3 4 5 6 7
- 7
- 1 2 3 4 5 6 7
- 1
- 0.05
-
- 3
- 0.1
- 1.0e-6
- 1.0e-3
-
- 1
- 60
- 1
-
-
- 0
- 1.9
- 6.2
- 0.545
- 1.8
- 0.43
- 5.089
- -3.346
- 96
-
- 0
-
-
-
-
-
- 3e5
- 0
- 14
- 0 1 2 2 3 4 5 6 7 8 9 10 11 12
- 13
- 0 1 2 4 5 6 7 8 9 10 11 12 13
-
-
- 2
- 11 12
-
- 0
- 0 1 2 3 4 5 6 7 8 9 10
-
-
-
-
-
- 2
- 6
- 0 0.2 0.4 0.6 0.8 1
-
- 1.0
- 1.0e-3
- 0.0e12
- 0.0e12
- 1.0e-3
-
-
- 0
- 5
-
-
- 0
-
- 2
- 10
- 1
- 20
-
- 1.0e-3
-
-
- 101
-
-
-