diff --git a/pipelines.py b/pipelines.py new file mode 100644 index 0000000..5056634 --- /dev/null +++ b/pipelines.py @@ -0,0 +1,96 @@ +try: + from cam_server_client import PipelineClient +except ImportError: + from fake import PipelineClient + + + +class Pipelines: + + def __init__(self, addr="http://sf-daqsync-01:8889"): + self.pc = PipelineClient(addr) + self.refresh() + + + def refresh(self): + pc = self.pc + + all_pls = pc.get_pipelines() + + si = pc.get_server_info() + active_pls = si["active_instances"] + + offline_pls = set(all_pls) - set(active_pls) + +# spec_pls = (i for i in pls if "spec_db" in i) + + self.all = sorted(all_pls) + self.active = sorted(active_pls) + self.offline = sorted(offline_pls) + + + def __iter__(self): + return (Pipeline(n, self) for n in self.all) + + def __getitem__(self, name): + if name not in self.all: + raise RuntimeError(f"pipeline \"{name}\" does not exist") + return Pipeline(name, self) + + + +class Pipeline: + + def __init__(self, name, pls): + self.name = name + self.pls = pls + + def __repr__(self): + return f"\"{self.name}\" is \"{self.state}\"" + + + @property + def state(self): + pls = self.pls + name = self.name + pls.refresh() + + if name not in pls.all: + raise RuntimeError(f"pipeline \"{name}\" does not exist") + if name in pls.active: + return "active" + if name in pls.offline: + return "offline" + + raise RuntimeError(f"existing pipeline \"{name}\" is neither active nor offline") + + + def get(self): + pc = self.pls.pc + name = self.name + state = self.state + + if state == "active": + return pc.get_instance_config(name) + if state == "offline": + return pc.get_config(name) + + raise ValueError(f"state \"{state}\" for pipeline \"{name}\" not understood") + + + def set(self, cfg): + pc = self.pls.pc + name = self.name + state = self.state + + if state == "active": + return pc.set_instance_config(name, cfg) + if state == "offline": + current = pc.get_config(name) + current.update(cfg) + return pc.set_config(name, current) + + raise ValueError(f"state \"{state}\" for pipeline \"{name}\" not understood") + + + diff --git a/scam.py b/scam.py index a099841..71df664 100755 --- a/scam.py +++ b/scam.py @@ -4,7 +4,6 @@ import argparse parser = argparse.ArgumentParser() parser.add_argument("-a", "--all", dest="show_all_settings", action="store_true", help="show all settings") -parser.add_argument("-o", "--offline", dest="show_offline_pipelines", action="store_true", help="show offline pipelines") clargs = parser.parse_args() @@ -27,6 +26,10 @@ SCRIPT_NAME = "spectrometer.py" TITLE = "SCam" if not clargs.show_all_settings else "SCam Expert Mode" +GOOD = "✅" +BAD = "❌" + + import itertools import subprocess @@ -40,22 +43,10 @@ except ImportError: from tools import EXPANDING, STRETCH, make_filled_vbox, make_filled_hbox from entrybutton import EntryButton from settings import SettingsList +from pipelines import Pipelines pc = PipelineClient("http://sf-daqsync-01:8889") -si = pc.get_server_info() -pls = si["active_instances"] - -if clargs.show_offline_pipelines: - all_pls = pc.get_pipelines() - pls = set(all_pls) - set(pls) - -if not clargs.show_all_settings: - pls = (i for i in pls if "spec_db" in i) - -pls = sorted(pls) -print("found:", pls) - class MainFrame(wx.Frame): @@ -77,7 +68,19 @@ class MainPanel(wx.Panel): self.instance = None self.camera = None - self.cb_pls = cb_pls = wx.ComboBox(self, choices=pls) + self.pls = pls = Pipelines() + + pl_names = [GOOD + n for n in pls.active] + pl_names += [BAD + n for n in pls.offline] + pl_names.sort(key=lambda x: x[1:]) + +# pl_names = pls.all + if not clargs.show_all_settings: + pl_names = sorted(i for i in pl_names if "spec_db" in i) + + self.cb_pls = cb_pls = wx.ComboBox(self, choices=pl_names) + + self.st_status = st_status = wx.StaticText(self) self.eb_bkg = eb_bkg = EntryButton(self, label="Background Images", value=100, button="Record Background") @@ -111,7 +114,7 @@ class MainPanel(wx.Panel): widgets = [btn_print, btn_save] btns_bottom = make_filled_hbox(widgets) - widgets = [cb_pls, STRETCH, eb_bkg, btns_get_roi, STRETCH, entries, btns_bottom] + widgets = [cb_pls, st_status, STRETCH, eb_bkg, btns_get_roi, STRETCH, entries, btns_bottom] sizer = make_filled_vbox(widgets, border=10) self.SetSizer(sizer) @@ -126,14 +129,16 @@ class MainPanel(wx.Panel): def on_select(self, event): self.entries.clear() - self.instance = instance = self.cb_pls.GetValue() + self.instance = instance = self.cb_pls.GetValue().strip(GOOD + BAD) - if clargs.show_offline_pipelines: - cfg = pc.get_config(instance) - print("pipeline config:", cfg) - else: - cfg = pc.get_instance_config(instance) - print("instance config:", cfg) + pipeline = self.pls[instance] + state = pipeline.state + print(f"{instance} is {state}") + symbol = GOOD if state == "active" else BAD + self.st_status.SetLabel(f"status: {state} {symbol}") + + cfg = pipeline.get() + print("current config:", cfg) self.camera = camera = cfg["camera_name"] @@ -152,8 +157,12 @@ class MainPanel(wx.Panel): # ensure background name is always set bkg_setting = self.entries["image_background"] if not bkg_setting.get_state(): - latest_bkg = pc.get_latest_background(camera) - bkg_setting.set_value(latest_bkg) + try: + latest_bkg = pc.get_latest_background(camera) + except ValueError: + pass + else: + bkg_setting.set_value(latest_bkg) self.eb_bkg.Enable() self.btn_screenpanel.Enable() @@ -242,14 +251,9 @@ class MainPanel(wx.Panel): def on_save_cfg(self, event): new_cfg = self.make_cfg() - if clargs.show_offline_pipelines: - cfg = pc.get_config(self.instance) - cfg.update(new_cfg) # need to send a full config, a delta is not enough - res = pc.set_config(self.instance, cfg) - print("pipeline config:", res) - else: - res = pc.set_instance_config(self.instance, new_cfg) - print("instance config:", res) + pipeline = self.pls[self.instance] + res = pipeline.set(new_cfg) + print("result config:", res)