diff --git a/bluesky_cmds/_plot.py b/bluesky_cmds/_plot.py index 599e0a6..4571afb 100644 --- a/bluesky_cmds/_plot.py +++ b/bluesky_cmds/_plot.py @@ -14,11 +14,12 @@ import WrightTools as wt import bluesky_cmds.project.project_globals as g import bluesky_cmds.project.widgets as pw -import bluesky_cmds.project.classes as pc import bluesky_cmds.somatic as somatic from bluesky_cmds.__main__ import config from bluesky_cmds._main_window import window +import qtypes + from .logging import getLogger logger = getLogger("plot") @@ -35,16 +36,16 @@ def create_frame(self): self.main_widget = window.plot_widget # create main daq tab main_widget = self.main_widget - layout = QtWidgets.QHBoxLayout() - layout.setContentsMargins(0, 10, 0, 0) - main_widget.setLayout(layout) + self.layout = QtWidgets.QHBoxLayout() + self.layout.setContentsMargins(0, 10, 0, 0) + main_widget.setLayout(self.layout) # display # container widget display_container_widget = pw.ExpandingWidget() display_container_widget.setLayout(QtWidgets.QVBoxLayout()) display_layout = display_container_widget.layout() display_layout.setContentsMargins(0, 0, 0, 0) - layout.addWidget(display_container_widget) + self.layout.addWidget(display_container_widget) # big number big_number_container_widget = QtWidgets.QWidget() big_number_container_widget.setLayout(QtWidgets.QHBoxLayout()) @@ -63,60 +64,50 @@ def create_frame(self): display_layout.addWidget(self.plot_widget) # vertical line line = pw.line("V") - layout.addWidget(line) - # settings - settings_container_widget = QtWidgets.QWidget() - settings_scroll_area = pw.scroll_area() - settings_scroll_area.setWidget(settings_container_widget) - settings_scroll_area.setMinimumWidth(300) - settings_scroll_area.setMaximumWidth(300) - settings_container_widget.setLayout(QtWidgets.QVBoxLayout()) - self.settings_layout = settings_container_widget.layout() - self.settings_layout.setContentsMargins(5, 5, 5, 5) - layout.addWidget(settings_scroll_area) + self.layout.addWidget(line) def create_settings(self): # display settings - input_table = pw.InputTable() - input_table.add("Display", None) - self.channel = pc.Combo() - input_table.add("Channel", self.channel) - self.axis = pc.Combo() - input_table.add("X-Axis", self.axis) - self.axis_units = pc.Combo() - input_table.add("X-Units", self.axis_units) - self.settings_layout.addWidget(input_table) - # global daq settings - input_table = pw.InputTable() - # input_table.add("ms Wait", ms_wait) - input_table.add("Scan", None) - # input_table.add("Loop Time", loop_time) - self.idx_string = pc.String(initial_value="None", display=True) - input_table.add("Scan Index", self.idx_string) - self.settings_layout.addWidget(input_table) - # stretch - self.settings_layout.addStretch(1) + input_table = qtypes.Null() + tree_widget = qtypes.TreeWidget(input_table) + display = qtypes.Null("Display") + self.channel = qtypes.Enum("Channel") + display.append(self.channel) + self.axis = qtypes.Enum("X-Axis") + display.append(self.axis) + self.axis_units = qtypes.Enum("X-Units") + display.append(self.axis_units) + input_table.append(display) + scan = qtypes.Null("Scan") + self.idx_string = qtypes.String("Scan Index", value="None", disabled=True) + scan.append(self.idx_string) + input_table.append(scan) + tree_widget[0].expand() + tree_widget.setMinimumWidth(250) + self.layout.addWidget(tree_widget) def set_units_map(self, units_map): self._units_map = units_map - self.on_axis_updated() + self.on_axis_updated({"value": self.axis.get_value()}) - def on_axis_updated(self): - units = self._units_map.get(self.axis.read()) + def on_axis_updated(self, value): + units = self._units_map.get(value["value"]) units = [units] + list(wt.units.get_valid_conversions(units)) - self.axis_units.set_allowed_values(units) + self.axis_units.set({"allowed": units}) - def update_plot(self): + def update_plot(self, _=None): # data if not plot_callback.events: return - x_units = self.axis_units.read() - axis = self.axis.read() - channel = self.channel.read() + x_units = self.axis_units.get_value() + axis = self.axis.get_value() + channel = self.channel.get_value() self.plot_widget.clear() def plot_0d(start, stop, color="c"): - stop = min(stop, len(plot_callback.events)) + stop = min(stop, len(plot_callback.events)-1) + from pprint import pprint + pprint(plot_callback.events[stop]) if axis == "time": x = [plot_callback.events[i]["time"] for i in range(start, stop)] else: @@ -182,7 +173,7 @@ def plot_1d(event, color="c"): ncolors = min(len(plot_callback.events), 5) colors = np.linspace([60, 60, 60], [0, 160, 160], ncolors, dtype="u1") colors[-1] = [0, 255, 255] - for e, c in zip(range(-5, 0), colors): + for e, c in zip(range(max(-5, -1 * len(plot_callback.events)), 0), colors): plot_1d(plot_callback.events[e], c) num = plot_callback.events[-1]["data"][channel] @@ -226,7 +217,7 @@ def start(self, doc): # Default if the hints are not given self.dimensions = ["time"] self.all_dimensions = ["time"] - gui.axis.set_allowed_values(self.dimensions) + gui.axis.set({"allowed": self.dimensions}) if self.start_doc.get("shape"): self.shape = self.start_doc["shape"] @@ -248,7 +239,7 @@ def descriptor(self, doc): self.dimensions.extend([dim for dim, val in self.descriptor_doc.get("data_keys", {}).items() if val.get("independent")]) - gui.axis.set_allowed_values(self.dimensions) + gui.axis.set({"allowed": self.dimensions}) self.units_map = { dim: self.descriptor_doc.get("data_keys", {}).get(dim, {}).get("units") for dim in self.dimensions @@ -261,9 +252,11 @@ def descriptor(self, doc): for field in hint.get("fields", []): if field not in self.all_dimensions: self.channels.append(field) - gui.channel.set_allowed_values(self.channels) + gui.channel.set({"allowed": self.channels}) def event(self, doc): + if not self.descriptor_doc: + return if doc["descriptor"] != self.descriptor_doc["uid"]: return super().event(doc) @@ -273,7 +266,7 @@ def event(self, doc): index = doc["seq_num"] - 1 if self.shape and index: index = np.unravel_index(index, self.shape) - gui.idx_string.write(str(index)) + gui.idx_string.set_value(str(index)) somatic.signals.update_plot.emit() @@ -294,7 +287,7 @@ def stop(self, doc): somatic.signals.update_plot.connect(gui.update_plot) # somatic.signals.data_file_created.connect(gui.on_data_file_created) -gui.axis.updated.connect(gui.on_axis_updated) -gui.axis.updated.connect(gui.update_plot) -gui.axis_units.updated.connect(gui.update_plot) -gui.channel.updated.connect(gui.update_plot) +gui.axis.updated_connect(gui.on_axis_updated) +gui.axis.updated_connect(gui.update_plot) +gui.axis_units.updated_connect(gui.update_plot) +gui.channel.updated_connect(gui.update_plot) diff --git a/bluesky_cmds/somatic/plan_ui.py b/bluesky_cmds/somatic/plan_ui.py index ee09511..67678a2 100644 --- a/bluesky_cmds/somatic/plan_ui.py +++ b/bluesky_cmds/somatic/plan_ui.py @@ -5,13 +5,12 @@ import toolz import numpy as np from qtpy import QtWidgets +import qtypes from .comms import RM from .signals import plans_allowed_updated, devices_allowed_updated from bluesky_hwproxy import zmq_single_request as hwproxy_request import WrightTools as wt -from bluesky_cmds.project import widgets as pw -from bluesky_cmds.project import classes as pc def get_all_components(k, v): @@ -74,12 +73,7 @@ def __init__(self, items=None): ] else: self.items = items - self.frame = QtWidgets.QWidget() - self.frame.setLayout(QtWidgets.QVBoxLayout()) - layout = self.frame.layout() - layout.setContentsMargins(0, 0, 0, 0) - for x in self.items: - layout.addWidget(x.frame) + self.frame = [x.frame for x in self.items] @property def args(self): @@ -127,18 +121,17 @@ def load(self, *args, **kwargs): class MetadataWidget: def __init__(self): self.nargs = 0 - self.fields = { - "Name": pc.String(), - "Info": pc.String(), - "Experimentor": pc.Combo(["unspecified"] + list(sorted(["Kyle", "Emily", "Kelson", "Dan", "Kent", "Peter", "Ryan", "Jason", "David", "John", "Chris", "James"]))), - } + exp_list = ["unspecified"] + list(sorted(["Kyle", "Emily", "Kelson", "Dan", "Kent", "Peter", "Ryan", "Jason", "David", "John", "Chris", "James"])) + self.fields = [ + qtypes.String("Name"), + qtypes.String("Info"), + qtypes.Enum("Experimentor", allowed=exp_list), + ] @property def frame(self): - frame = pw.InputTable() - frame.add("Metadata", None) - for k, v in self.fields.items(): - frame.add(k, v) + frame = qtypes.Null("Metadata") + frame.extend(self.fields) return frame @property @@ -151,30 +144,29 @@ def args(self, arg): @property def kwargs(self): - return {"md": {k: v.read() for k, v in self.fields.items()}} + return {"md": {v.get()["label"]: v.get_value() for v in self.fields}} @kwargs.setter def kwargs(self, kwargs): md = kwargs.get("md", {}) - for k, v in self.fields.items(): + for v in self.fields: + k = b.get()["label"] if k in md: - v.write(md[k]) + v.set_value(md[k]) class ArgsWidget: def __init__(self): self.nargs = -1 - self.frame = pw.InputTable() - self.args_input = pc.String() - self.frame.add("Args", self.args_input) + self.frame = qtypes.String("Args") @property def args(self): - return json.loads(self.args_input.read() or "[]") + return json.loads(self.frame.get_value() or "[]") @args.setter def args(self, args): - self.args_input.write(json.dumps(args)) + self.frame.set_value(json.dumps(args)) @property def kwargs(self): @@ -188,17 +180,15 @@ def kwargs(self, kwargs): class KwargsWidget: def __init__(self): self.nargs = 0 - self.frame = pw.InputTable() - self.kwargs_input = pc.String() - self.frame.add("Kwargs", self.kwargs_input) + self.frame = qtypes.String("Kwargs") @property def kwargs(self): - return json.loads(self.kwargs_input.read() or "{}") + return json.loads(self.frame.get_value() or "{}") @kwargs.setter def kwargs(self, kwargs): - self.kwargs_input.write(json.dumps(kwargs)) + self.frame.set_value(json.dumps(kwargs)) @property def args(self): @@ -214,22 +204,21 @@ def __init__(self, name, kwarg=None, kw_only=False): self.nargs = 1 if kw_only: self.nargs = 0 - self.frame = pw.InputTable() - self.frame.add(name, self.input) + self.frame = qtypes.Null(name) self.kwarg = kwarg @property def args(self): - return [self.input.read()] if not self.kwarg else [] + return [self.frame.get_value()] if not self.kwarg else [] @args.setter def args(self, arg): if arg: - self.input.write(arg[0]) + self.frame.set_value(arg[0]) @property def kwargs(self): - return {self.kwarg: self.input.read()} if self.kwarg else {} + return {self.kwarg: self.frame.get_value()} if self.kwarg else {} @kwargs.setter def kwargs(self, kwargs): @@ -239,33 +228,33 @@ def kwargs(self, kwargs): class BoolWidget(SingleWidget): def __init__(self, name, kwarg=None): - self.input = pc.Bool() super().__init__(name, kwarg) + self.frame = qtypes.Bool(name) class StrWidget(SingleWidget): def __init__(self, name, kwarg=None): - self.input = pc.String() super().__init__(name, kwarg) + self.frame = qtypes.String(name) class IntWidget(SingleWidget): def __init__(self, name, kwarg=None, default=0): - self.input = pc.Number(decimals=0, initial_value=default) super().__init__(name, kwarg) + self.frame = qtypes.Integer(name, value=default) @property def args(self): - return [int(self.input.read())] if not self.kwarg else [] + return [int(self.frame.get_value())] if not self.kwarg else [] @args.setter def args(self, arg): if arg: - self.input.write(arg[0]) + self.frame.set_value(arg[0]) @property def kwargs(self): - return {self.kwarg: int(self.input.read())} if self.kwarg else {} + return {self.kwarg: int(self.frame.get_value())} if self.kwarg else {} @kwargs.setter def kwargs(self, kwargs): @@ -275,14 +264,14 @@ def kwargs(self, kwargs): class FloatWidget(SingleWidget): def __init__(self, name, kwarg=None, default=0): - self.input = pc.Number(initial_value=default) super().__init__(name, kwarg) + self.frame = qtypes.Float(name, value=default) class EnumWidget(SingleWidget): def __init__(self, name, options: dict, kwarg=None): - self.input = pc.Combo(options.keys()) super().__init__(name, kwarg) + self.frame = qtypes.Enum(name, allowed=list(options.keys())) self._options = options @property @@ -291,24 +280,24 @@ def options(self): @options.setter def options(self, value): - self.input.set_allowed_values(value.keys()) + self.frame.set({"allowed": list(value.keys())}) self._options = value @property def args(self): - return [self.options[self.input.read()]] if not self.kwarg else [] + return [self.options[self.frame.get_value()]] if not self.kwarg else [] @args.setter def args(self, arg): if arg: for k, v in self.options.items(): if arg[0] == v: - self.input.write(k) + self.frame.set_value(k) break @property def kwargs(self): - return {self.kwarg: self.options[self.input.read()]} if self.kwarg else {} + return {self.kwarg: self.options[self.frame.get_value()]} if self.kwarg else {} @kwargs.setter def kwargs(self, kwargs): @@ -319,11 +308,9 @@ def kwargs(self, kwargs): class DeviceListWidget: def __init__(self): self.nargs = 1 - self.inputs = {k: pc.Bool(True) for k in devices_not_movable} - self.frame = pw.InputTable() - self.frame.add("Devices", None) - for k, v in self.inputs.items(): - self.frame.add(k, v) + self.inputs = [qtypes.Bool(k, value=True) for k in devices_not_movable] + self.frame = qtypes.Null("Devices") + self.frame.extend(self.inputs) @property def kwargs(self): @@ -335,16 +322,13 @@ def kwargs(self, kwargs): @property def args(self): - return [[k for k, v in self.inputs.items() if v.read()]] + return [[v.get()["label"] for v in self.inputs if v.get_value()]] @args.setter def args(self, args): arg = args[0] for device in self.inputs: - if device in arg: - self.inputs[device].write(True) - else: - self.inputs[device].write(False) + self.inputs[device].set_value(device in arg) class ConstantWidget: @@ -405,19 +389,19 @@ def kwargs(self, kwargs): self.add_constant(*c) -class Constant(pw.InputTable): +class Constant(qtypes.Null): def __init__(self, hardware, units, terms): super().__init__() self.add("Constant", None) self.hardware = pc.Combo(devices_movable) - self.hardware.write(hardware) + self.hardware.set_value(hardware) self.hardware.updated.connect(self.on_hardware_updated) self.add("Hardware", self.hardware) self.units = pc.Combo(wt.units.blessed_units) - self.units.write(units) + self.units.set_value(units) self.add("Units", self.units) self.expression = pc.String() - self.expression.write( + self.expression.set_value( " + ".join(f"{coeff}*{hw}" if hw else f"{coeff}" for coeff, hw in terms) ) self.add("Expression", self.expression) @@ -425,16 +409,16 @@ def __init__(self, hardware, units, terms): @property def args(self): - units = self.units.read() + units = self.units.get_value() if units == "None": units = None - return [self.hardware.read(), units, self.terms] + return [self.hardware.get_value(), units, self.terms] @property def terms(self): import sympy - expr = sympy.parse_expr(self.expression.read()) + expr = sympy.parse_expr(self.expression.get_value()) coeffs = expr.as_coefficients_dict() for k, v in list(coeffs.items()): @@ -448,7 +432,7 @@ def terms(self): return [(v, k) for k, v in coeffs.items()] def on_hardware_updated(self): - hw_name = self.hardware.read() + hw_name = self.hardware.get_value() native = get_units(hw_name) units_list = [ i for i in (native,) + wt.units.get_valid_conversions(native) if i != "mm_delay" @@ -508,32 +492,32 @@ def kwargs(self): def kwargs(self, kwargs): pass -class MvAxis(pw.InputTable): +class MvAxis(qtypes.Null): def __init__(self, hardware, position): super().__init__() self.add("Axis", None) self.hardware = pc.Combo(devices_movable) - self.hardware.write(hardware) + self.hardware.set_value(hardware) self.add("Hardware", self.hardware) self.native = get_units(hardware) self.position = pc.Number(units=self.native) - self.position.limits.write(*get_limits(self.hardware.read()), self.native) - self.position.write(position) + self.position.limits.set_value(*get_limits(self.hardware.get_value()), self.native) + self.position.set_value(position) self.add("Position", self.position) self.hardware.updated.connect(self.set_unit) @property def args(self): return [ - self.hardware.read(), - self.position.read(self.native), + self.hardware.get_value(), + self.position.get_value(self.native), ] def set_unit(self): - self.native = get_units(self.hardware.read()) + self.native = get_units(self.hardware.get_value()) self.position.set_units(self.native) self.position.limits.units = self.native - self.position.limits.write(*get_limits(self.hardware.read()), self.native) + self.position.limits.set_value(*get_limits(self.hardware.get_value()), self.native) class MvArgsWidget(GenericScanArgsWidget): @@ -547,12 +531,12 @@ def add_axis(self, hardware=None, position=0): self.axes.append(axis) self.axis_container_widget.layout().addWidget(axis) -class GridscanAxis(pw.InputTable): +class GridscanAxis(qtypes.Null): def __init__(self, hardware, start, stop, npts, units): super().__init__() self.add("Axis", None) self.hardware = pc.Combo(devices_movable) - self.hardware.write(hardware) + self.hardware.set_value(hardware) self.hardware.updated.connect(self.on_hardware_updated) self.add("Hardware", self.hardware) self.start = pc.Number(start) @@ -562,25 +546,25 @@ def __init__(self, hardware, start, stop, npts, units): self.npts = pc.Number(npts, decimals=0) self.add("Npts", self.npts) self.units = pc.Combo(wt.units.blessed_units) - self.units.write(units) + self.units.set_value(units) self.add("Units", self.units) self.on_hardware_updated() @property def args(self): - units = self.units.read() + units = self.units.get_value() if units == "None": units = None return [ - self.hardware.read(), - self.start.read(), - self.stop.read(), - int(self.npts.read()), + self.hardware.get_value(), + self.start.get_value(), + self.stop.get_value(), + int(self.npts.get_value()), units, ] def on_hardware_updated(self): - hw_name = self.hardware.read() + hw_name = self.hardware.get_value() base_name = hw_name.split(".")[0] key_name = hw_name.replace(".", "_") native = hwproxy_request("describe", {"device": base_name})[0]["return"][key_name].get( @@ -604,12 +588,12 @@ def add_axis(self, hardware=None, start=0, stop=1, npts=11, units="ps"): self.axis_container_widget.layout().addWidget(axis) -class ScanAxis(pw.InputTable): +class ScanAxis(qtypes.Null): def __init__(self, hardware, start, stop, units): super().__init__() self.add("Axis", None) self.hardware = pc.Combo(devices_movable) - self.hardware.write(hardware) + self.hardware.set_value(hardware) self.add("Hardware", self.hardware) self.hardware.updated.connect(self.on_hardware_updated) self.start = pc.Number(start) @@ -617,24 +601,24 @@ def __init__(self, hardware, start, stop, units): self.stop = pc.Number(stop) self.add("Stop", self.stop) self.units = pc.Combo(wt.units.blessed_units) - self.units.write(units) + self.units.set_value(units) self.add("Units", self.units) self.on_hardware_updated() @property def args(self): - units = self.units.read() + units = self.units.get_value() if units == "None": units = None return [ - self.hardware.read(), - self.start.read(), - self.stop.read(), + self.hardware.get_value(), + self.start.get_value(), + self.stop.get_value(), units, ] def on_hardware_updated(self): - hw_name = self.hardware.read() + hw_name = self.hardware.get_value() native = get_units(hw_name) units_list = [ i for i in (native,) + wt.units.get_valid_conversions(native) if i != "mm_delay" @@ -654,35 +638,35 @@ def add_axis(self, hardware=None, start=0, stop=1, units="ps"): self.axis_container_widget.layout().addWidget(axis) -class ListAxis(pw.InputTable): +class ListAxis(qtypes.Null): def __init__(self, hardware, list, units): super().__init__() self.add("Axis", None) self.hardware = pc.Combo(devices_movable) - self.hardware.write(hardware) + self.hardware.set_value(hardware) self.add("Hardware", self.hardware) self.hardware.updated.connect(self.on_hardware_updated) self.list = pc.String() - self.list.write(json.dumps(list) or "[]") + self.list.set_value(json.dumps(list) or "[]") self.add("List", self.list) self.units = pc.Combo(wt.units.blessed_units) - self.units.write(units) + self.units.set_value(units) self.add("Units", self.units) self.on_hardware_updated() @property def args(self): - units = self.units.read() + units = self.units.get_value() if units == "None": units = None return [ - self.hardware.read(), - json.loads(self.list.read()) or [], + self.hardware.get_value(), + json.loads(self.list.get_value()) or [], units, ] def on_hardware_updated(self): - hw_name = self.hardware.read() + hw_name = self.hardware.get_value() native = get_units(hw_name) units_list = [ i for i in (native,) + wt.units.get_valid_conversions(native) if i != "mm_delay" @@ -727,7 +711,7 @@ def on_opa_selected(self): motors = {"None": None} self.options = motors -class OpaMotorAxis(pw.InputTable): +class OpaMotorAxis(qtypes.Null): def __init__(self, motor, method, center, width, npts, opa_selector): super().__init__() self.opa_selector = opa_selector @@ -735,7 +719,7 @@ def __init__(self, motor, method, center, width, npts, opa_selector): motor = list(devices_all_json[self.opa_selector.args[0]]["components"].keys())[0] self.add("Motor Axis", None) self.motor = pc.Combo(devices_all_json[self.opa_selector.args[0]]["components"].keys()) - self.motor.write(motor) + self.motor.set_value(motor) self.add("Motor", self.motor) self.center = pc.Number(center) self.add("Center", self.center) @@ -748,7 +732,7 @@ def __init__(self, motor, method, center, width, npts, opa_selector): @property def kwargs(self): # TODO 'static' method does not work so I don't give it a gui element yet -- 2022-05-16 KFS - return {"method": "scan", "center": self.center.read(), "width": self.width.read(), "npts": int(self.npts.read())} + return {"method": "scan", "center": self.center.get_value(), "width": self.width.get_value(), "npts": int(self.npts.get_value())} def on_opa_updated(self): self.motor.set_allowed_values(devices_all_json[self.opa_selector.args[0]]["components"].keys()) @@ -773,7 +757,7 @@ def args(self): @property def kwargs(self): - return {"motors":{a.motor.read(): a.kwargs for a in self.axes}} + return {"motors":{a.motor.get_value(): a.kwargs for a in self.axes}} @kwargs.setter def kwargs(self, value): @@ -784,7 +768,7 @@ def kwargs(self, value): self.add_axis(motor=mot, **params) -class SpectrometerWidget(pw.InputTable): +class SpectrometerWidget(qtypes.Null): def __init__(self, name="spectrometer", include_center=True): super().__init__() self.nargs = 0 @@ -825,8 +809,8 @@ def __init__(self, name="spectrometer", include_center=True): @property def kwargs(self): - device = self.device.read() - method = self.method.read() + device = self.device.get_value() + method = self.method.get_value() if device == "None" or method == "none": return {self.name: None} out = { @@ -834,10 +818,10 @@ def kwargs(self): for k, v in { "device": device, "method": method, - "center": self.center.read(), - "width": self.width.read(), - "units": self.units.read(), - "npts": int(self.npts.read()), + "center": self.center.get_value(), + "width": self.width.get_value(), + "units": self.units.get_value(), + "npts": int(self.npts.get_value()), }.items() if k in self.used[method] or k == "method" } @@ -847,31 +831,31 @@ def kwargs(self): def kwargs(self, value): if value[self.name]: if "device" in value[self.name]: - self.device.write(value[self.name]["device"]) + self.device.set_value(value[self.name]["device"]) if "method" in value[self.name]: - self.method.write([value[self.name]["method"]]) + self.method.set_value([value[self.name]["method"]]) if "center" in value[self.name]: - self.center.write(value[self.name]["center"]) + self.center.set_value(value[self.name]["center"]) if "width" in value[self.name]: - self.width.write(value[self.name]["width"]) + self.width.set_value(value[self.name]["width"]) if "units" in value[self.name]: - self.units.write(value[self.name]["units"]) + self.units.set_value(value[self.name]["units"]) if "npts" in value[self.name]: - self.npts.write(value[self.name]["npts"]) + self.npts.set_value(value[self.name]["npts"]) @property def args(self): return [] def on_device_selected(self): - if self.device.read() == "None": + if self.device.get_value() == "None": for var in ("center", "width", "units", "npts"): getattr(self, var).set_disabled(True) else: self.on_method_selected() def on_method_selected(self): - method = self.method.read() + method = self.method.get_value() for var in ("device", "center", "width", "units", "npts"): getattr(self, var).set_disabled(not var in self.used[method]) @@ -889,6 +873,7 @@ def update_plan_ui(): MvArgsWidget(), ] ) + """ plan_ui_lookup["grid_scan_wp"] = PlanUI( [ MetadataWidget(), @@ -955,6 +940,7 @@ def update_plan_ui(): ConstantWidget(), ] ) + """ plan_ui_lookup["count"] = PlanUI( [ MetadataWidget(), @@ -964,7 +950,7 @@ def update_plan_ui(): ] ) - if devices_with_deps: + if False and devices_with_deps: plan_ui_lookup["run_tune_test"] = PlanUI( [ MetadataWidget(), diff --git a/bluesky_cmds/somatic/queue.py b/bluesky_cmds/somatic/queue.py index fef5872..149e49e 100644 --- a/bluesky_cmds/somatic/queue.py +++ b/bluesky_cmds/somatic/queue.py @@ -5,12 +5,12 @@ import pprint from qtpy import QtCore, QtGui, QtWidgets +import qtypes from .comms import RM from bluesky_queueserver_api import BInst, BPlan import bluesky_cmds.project.project_globals as g -import bluesky_cmds.project.classes as pc import bluesky_cmds.project.widgets as pw from bluesky_cmds.project.colors import colors @@ -104,114 +104,87 @@ def create_frame(self): for i, width in enumerate(self.table_cols.values()): self.table.setColumnWidth(i, width) # controls ------------------------------------------------------------ - settings_container_widget = QtWidgets.QWidget() - settings_scroll_area = pw.scroll_area() - settings_scroll_area.setWidget(settings_container_widget) - settings_scroll_area.setMinimumWidth(300) - settings_scroll_area.setMaximumWidth(300) - settings_container_widget.setLayout(QtWidgets.QVBoxLayout()) - settings_layout = settings_container_widget.layout() - self.settings_layout = settings_layout - settings_layout.setContentsMargins(5, 5, 5, 5) + self.settings_layout = qtypes.Null() # adjust queue label - input_table = pw.InputTable() - input_table.add("Control Queue", None) - settings_layout.addWidget(input_table) + control_queue = qtypes.Null("Control Queue") + self.settings_layout.append(control_queue) # go button - self.queue_start = pw.SetButton("START QUEUE") - self.queue_start.clicked.connect(self.on_queue_start_clicked) - settings_layout.addWidget(self.queue_start) - somatic.signals.queue_relinquishing_control.connect(self.queue_start.show) - somatic.signals.queue_taking_control.connect(self.queue_start.hide) - self.interrupt = pw.SetButton("INTERRUPT", "stop") - self.interrupt.clicked.connect(self.on_interrupt_clicked) - settings_layout.addWidget(self.interrupt) - somatic.signals.queue_relinquishing_control.connect(self.interrupt.hide) - somatic.signals.queue_taking_control.connect(self.interrupt.show) - line = pw.Line("H") - settings_layout.addWidget(line) - self.env_close = pw.SetButton("CLOSE ENVIRONMENT", "stop") - self.env_close.clicked.connect(self.on_env_close_clicked) - settings_layout.addWidget(self.env_close) - line = pw.Line("H") - settings_layout.addWidget(line) - self.clear = pw.SetButton("CLEAR QUEUE", "stop") - self.clear.clicked.connect(self.on_clear_clicked) - settings_layout.addWidget(self.clear) - self.clear_history = pw.SetButton("CLEAR HISTORY", "stop") - self.clear_history.clicked.connect(self.on_clear_history_clicked) - settings_layout.addWidget(self.clear_history) - # horizontal line - line = pw.Line("H") - settings_layout.addWidget(line) + self.queue_start = qtypes.Button("START QUEUE") + self.queue_start.updated_connect(self.on_queue_start_clicked) + control_queue.append(self.queue_start) + #somatic.signals.queue_relinquishing_control.connect(self.queue_start.show) + #somatic.signals.queue_taking_control.connect(self.queue_start.hide) + self.interrupt = qtypes.Button("INTERRUPT") + self.interrupt.updated_connect(self.on_interrupt_clicked) + control_queue.append(self.interrupt) + #somatic.signals.queue_relinquishing_control.connect(self.interrupt.hide) + #somatic.signals.queue_taking_control.connect(self.interrupt.show) + self.env_close = qtypes.Button("CLOSE ENVIRONMENT") + self.env_close.updated_connect(self.on_env_close_clicked) + control_queue.append(self.env_close) + self.clear = qtypes.Button("CLEAR QUEUE") + self.clear.updated_connect(self.on_clear_clicked) + control_queue.append(self.clear) + self.clear_history = qtypes.Button("CLEAR HISTORY") + self.clear_history.updated_connect(self.on_clear_history_clicked) + control_queue.append(self.clear_history) # type combobox - input_table = pw.InputTable() + select_type = qtypes.Null("Add to Queue") allowed_values = ["plan", "instruction", "preset"] - self.type_combo = pc.Combo(allowed_values=allowed_values) - self.type_combo.updated.connect(self.update_type) - input_table.add("Add to Queue", None) - input_table.add("Type", self.type_combo) - settings_layout.addWidget(input_table) + self.type_combo = qtypes.Enum("Type", allowed=allowed_values) + self.settings_layout.append(select_type) # frames self.type_frames = { "plan": self.create_plan_frame(), "instruction": self.create_instruction_frame(), "preset": self.create_preset_frame(), } - for frame in self.type_frames.values(): - settings_layout.addWidget(frame) - frame.hide() + self.type_combo.updated_connect(self.update_type) + select_type.append(self.type_combo) self.update_type() - # finish -------------------------------------------------------------- - settings_layout.addStretch(1) # line ---------------------------------------------------------------- - self.layout.addWidget(settings_scroll_area) + tree_widget = qtypes.TreeWidget(self.settings_layout) + tree_widget.setMinimumWidth(300) + tree_widget.setMaximumWidth(300) + tree_widget[0].expand() + self.layout.addWidget(tree_widget) line = pw.Line("V") self.layout.addWidget(line) self.layout.addWidget(display_container_widget) display_layout.addWidget(self.table) def create_instruction_frame(self): - button = pw.SetButton("Append Queue Stop") - button.clicked.connect(lambda: RM.item_add(BInst("queue_stop"))) - return button + button = qtypes.Button("Append Queue Stop") + button.updated_connect(lambda _: RM.item_add(BInst("queue_stop"))) + return [button] - def update_presets(self): + def update_presets(self, _=None): vals = presets.get_preset_names() self.append_preset_button.setDisabled(False) if not vals: vals = ["No Presets"] self.append_preset_button.setDisabled(True) - self.preset.set_allowed_values(vals) + self.preset.set({"allowed": vals}) def create_preset_frame(self): - frame = QtWidgets.QWidget() - frame.setLayout(QtWidgets.QVBoxLayout()) - layout = frame.layout() - layout.setContentsMargins(0, 0, 0, 0) - input_table = pw.InputTable() vals = presets.get_preset_names() if not vals: vals = ["No Presets"] - self.preset = pc.Combo(allowed_values = vals) - input_table.add("Preset", self.preset) - self.append_preset_button = pw.SetButton("Append Preset Plans") - self.append_preset_button.clicked.connect(self.on_append_preset) - layout.addWidget(input_table) - self.edit_preset_button = pw.SetButton("Edit Preset Plans", color="advanced") - self.edit_preset_button.clicked.connect(self.on_edit_preset) - layout.addWidget(self.edit_preset_button) - layout.addWidget(self.append_preset_button) - return frame - - def on_append_preset(self): - preset = self.preset.read() + self.preset = qtypes.Enum("Preset", allowed=vals) + self.append_preset_button = qtypes.Button("Append Preset Plans") + self.append_preset_button.updated_connect(self.on_append_preset) + self.edit_preset_button = qtypes.Button("Edit Preset Plans") + self.edit_preset_button.updated_connect(self.on_edit_preset) + return [self.preset, self.edit_preset_button, self.append_preset_button] + + def on_append_preset(self, _=None): + preset = self.preset.get_value() for item in presets.get_preset_items(preset): # TODO add metadata here RM.item_add(item) - def on_edit_preset(self): - preset = self.preset.read() + def on_edit_preset(self, _=None): + preset = self.preset.get_value() presets.open_preset_file(preset) def show_preset_dialog(self, item): @@ -228,44 +201,29 @@ def show_preset_dialog(self, item): def create_plan_frame(self): - frame = QtWidgets.QWidget() - frame.setLayout(QtWidgets.QVBoxLayout()) - layout = frame.layout() - layout.setContentsMargins(0, 0, 0, 0) - input_table = pw.InputTable() try: allowed_plans = RM.plans_allowed() except: allowed_plans = {"plans_allowed": {"connecting...": None}} - allowed_values = allowed_plans["plans_allowed"].keys() - self.plan_combo = pc.Combo(allowed_values=allowed_values) - self.plan_combo.updated.connect(self.on_plan_selected) - input_table.add("Plan", self.plan_combo) - layout.addWidget(input_table) + allowed_values = list(allowed_plans["plans_allowed"].keys()) + self.plan_combo = qtypes.Enum("Plan", allowed=allowed_values) + self.plan_combo.updated_connect(self.on_plan_selected) self.plan_widgets = {x: plan_ui.plan_ui_lookup[x] for x in allowed_values} self.on_plan_selected() - for widget in self.plan_widgets.values(): - layout.addWidget(widget.frame) - append_button = pw.SetButton("APPEND TO QUEUE") - append_button.clicked.connect(self.on_append_to_queue) - layout.addWidget(append_button) - return frame + append_button = qtypes.Button("APPEND TO QUEUE") + append_button.updated_connect(self.on_append_to_queue) + return [self.plan_combo, append_button] def rebuild_plan_ui(self): - for frame in self.type_frames.values(): - self.settings_layout.removeWidget(frame) - frame.hide() - frame.close() self.type_frames["plan"] = self.create_plan_frame() - for frame in self.type_frames.values(): - # TODO remove magic number - self.settings_layout.insertWidget(10, frame) - frame.hide() self.on_load_item(self.get_plan().to_dict()) self.update_type() def get_plan(self): - plan_name = self.plan_combo.read() + plan_name = self.plan_combo.get_value() + if not plan_name: + # Happens during startup + return BPlan("sleep", 0) widget = self.plan_widgets[plan_name] kwargs = widget.kwargs meta = kwargs.pop("md", {}) @@ -273,14 +231,14 @@ def get_plan(self): plan.meta = meta return plan - def on_append_to_queue(self): + def on_append_to_queue(self, _=None): plan = self.get_plan() RM.item_add(plan) - def on_queue_start_clicked(self): + def on_queue_start_clicked(self, _=None): RM.queue_start() - def on_interrupt_clicked(self): + def on_interrupt_clicked(self, _=None): RM.re_pause("immediate") self.interrupt_choice_window.set_text("Please choose how to proceed.") index = self.interrupt_choice_window.show() @@ -295,19 +253,19 @@ def on_interrupt_clicked(self): RM.re_abort() # TODO Recover skip behavior... may require upstream change to be sane - def on_clear_clicked(self): + def on_clear_clicked(self, _=None): self.clear_choice_window.set_text("Do you want to clear the queue?") index = self.clear_choice_window.show() if index == 1: RM.queue_clear() - def on_clear_history_clicked(self): + def on_clear_history_clicked(self, _=None): self.clear_choice_window.set_text("Do you want to clear the history?") index = self.clear_choice_window.show() if index == 1: RM.history_clear() - def on_env_close_clicked(self): + def on_env_close_clicked(self, _=None): self.env_close_choice_window.set_text("Do you wish to close the worker environment?") if RM.status().get("manager_state") == "idle": index = self.env_close_choice_window.show() @@ -328,21 +286,21 @@ def on_remove_item(self, row): RM.item_remove(uid=item["item_uid"]) def on_load_item(self, item): - self.plan_combo.write(item["name"]) + self.plan_combo.set_value(item["name"]) kwargs = item.get("kwargs", {}) kwargs["md"] = item.get("meta", {}) self.plan_widgets[item["name"]].args = item.get("args", []) self.plan_widgets[item["name"]].kwargs = kwargs - def update_type(self): - for frame in self.type_frames.values(): - frame.hide() - self.type_frames[self.type_combo.read()].show() + def update_type(self, _=None): + self.type_combo.clear() + if self.type_combo.get_value() in self.type_frames: + self.type_combo.extend(self.type_frames[self.type_combo.get_value()]) - def on_plan_selected(self): - for frame in self.plan_widgets.values(): - frame.frame.hide() - self.plan_widgets[self.plan_combo.read()].frame.show() + def on_plan_selected(self, _=None): + self.plan_combo.clear() + if self.plan_combo.get_value() in self.plan_widgets: + self.plan_combo.extend(self.plan_widgets[self.plan_combo.get_value()].frame) def update_queue(self): queue_get = RM.queue_get()