346 lines
9.6 KiB
Python
Executable File
346 lines
9.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("-a", "--all", dest="show_all_settings", action="store_true", help="show all settings")
|
|
clargs = parser.parse_args()
|
|
|
|
|
|
|
|
SHOWN_SETTINGS = {
|
|
"image_background": "Background",
|
|
"threshold": "Threshold",
|
|
"project_axis": "Projection axis",
|
|
"roi_background": "ROI Background",
|
|
"roi_signal": "ROI Signal",
|
|
"roi_radial": "ROI Radial",
|
|
"radial_x0": "Radial x0",
|
|
"radial_y0": "Radial y0"
|
|
}
|
|
|
|
ENFORCED_SETTINGS = [
|
|
"image_background_enable",
|
|
"image_threshold",
|
|
"function"
|
|
]
|
|
|
|
KNOWN_TYPES = {
|
|
"threshold": 0.,
|
|
"project_axis": 0,
|
|
"roi_background": [0]*4,
|
|
"roi_signal": [0]*4,
|
|
"roi_radial": [0]*4,
|
|
"radial_x0": 0,
|
|
"radial_y0": 0
|
|
}
|
|
|
|
SCRIPT_NAME = "spectrometer.py"
|
|
TITLE = "SCam" if not clargs.show_all_settings else "SCam Expert Mode"
|
|
|
|
|
|
GOOD = "✅"
|
|
BAD = "❌"
|
|
|
|
|
|
|
|
import itertools
|
|
import subprocess
|
|
import wx
|
|
|
|
try:
|
|
from cam_server_client import PipelineClient
|
|
except ImportError:
|
|
from fake import PipelineClient
|
|
|
|
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")
|
|
|
|
|
|
class MainFrame(wx.Frame):
|
|
|
|
def __init__(self, parent=None, title=TITLE):
|
|
super().__init__(parent, title=title)
|
|
|
|
panel_main = MainPanel(self)
|
|
|
|
self.sizer = sizer = make_filled_vbox([panel_main])
|
|
self.SetSizerAndFit(sizer)
|
|
|
|
|
|
|
|
class MainPanel(wx.Panel):
|
|
|
|
def __init__(self, parent):
|
|
super().__init__(parent)
|
|
self.instance = None
|
|
self.camera = None
|
|
|
|
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")
|
|
|
|
self.btn_screenpanel = btn_screenpanel = wx.Button(self, label="Open ScreenPanel")
|
|
self.btn_get_roi_bkg = btn_get_roi_bkg = wx.Button(self, label="Get ROI Background from ScreenPanel")
|
|
self.btn_get_roi_sig = btn_get_roi_sig = wx.Button(self, label="Get ROI Signal from ScreenPanel")
|
|
self.btn_get_roi_rad = btn_get_roi_rad = wx.Button(self, label="Get ROI Radial from ScreenPanel")
|
|
|
|
self.entries = entries = SettingsList(self)
|
|
|
|
self.btn_print = btn_print = wx.Button(self, label="Print")
|
|
self.btn_save = btn_save = wx.Button(self, label="Save")
|
|
|
|
eb_bkg.Disable()
|
|
btn_screenpanel.Disable()
|
|
btn_get_roi_bkg.Disable()
|
|
btn_get_roi_sig.Disable()
|
|
btn_get_roi_rad.Disable()
|
|
btn_print.Disable()
|
|
btn_save.Disable()
|
|
|
|
cb_pls.Bind(wx.EVT_COMBOBOX, self.on_select)
|
|
eb_bkg.button.Bind(wx.EVT_BUTTON, self.on_save_bkg)
|
|
btn_screenpanel.Bind(wx.EVT_BUTTON, self.on_screenpanel)
|
|
btn_get_roi_bkg.Bind(wx.EVT_BUTTON, self.on_get_roi_bkg)
|
|
btn_get_roi_sig.Bind(wx.EVT_BUTTON, self.on_get_roi_sig)
|
|
btn_get_roi_rad.Bind(wx.EVT_BUTTON, self.on_get_roi_rad)
|
|
btn_print.Bind(wx.EVT_BUTTON, self.on_print)
|
|
btn_save.Bind(wx.EVT_BUTTON, self.on_save_cfg)
|
|
|
|
widgets = [btn_screenpanel, btn_get_roi_bkg, btn_get_roi_sig, btn_get_roi_rad]
|
|
btns_get_roi = make_filled_vbox(widgets)
|
|
|
|
widgets = [btn_print, btn_save]
|
|
btns_bottom = make_filled_hbox(widgets)
|
|
|
|
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)
|
|
|
|
|
|
def on_save_bkg(self, event):
|
|
num = self.eb_bkg.GetValue()
|
|
bkgname = pc.collect_background(self.camera, num)
|
|
self.entries.set("image_background", bkgname)
|
|
print(bkgname)
|
|
|
|
|
|
def on_select(self, event):
|
|
self.entries.clear()
|
|
|
|
self.instance = instance = self.cb_pls.GetValue().strip(GOOD + BAD)
|
|
|
|
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)
|
|
|
|
# use contents of KNOWN_TYPES to pre-fill cfg
|
|
#TODO use setdefault instead?
|
|
cfg_o = cfg
|
|
cfg_x = KNOWN_TYPES.copy()
|
|
cfg_x.update(cfg)
|
|
cfg = cfg_x
|
|
|
|
self.camera = camera = cfg["camera_name"]
|
|
|
|
self.orig_cfg = cfg
|
|
name_mapping = None
|
|
|
|
if not clargs.show_all_settings:
|
|
self.orig_cfg = filter_dict(cfg, SHOWN_SETTINGS, ENFORCED_SETTINGS)
|
|
name_mapping = SHOWN_SETTINGS
|
|
|
|
check_incoming_cfg(cfg)
|
|
cfg = filter_dict(cfg, SHOWN_SETTINGS)
|
|
|
|
self.entries.update(cfg, name_mapping)
|
|
|
|
# disable and clear lines added only from KNOWN_TYPES
|
|
for i in self.entries.children.values():
|
|
if i.name not in cfg_o:
|
|
i.disable()
|
|
i.clear()
|
|
|
|
# ensure background name is always set unless there is no background at all
|
|
bkg_setting = self.entries["image_background"]
|
|
if not bkg_setting.get_state():
|
|
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()
|
|
self.btn_get_roi_sig.Enable()
|
|
self.btn_get_roi_bkg.Enable()
|
|
self.btn_get_roi_rad.Enable()
|
|
self.btn_print.Enable()
|
|
self.btn_save.Enable()
|
|
|
|
self._adjust_size()
|
|
|
|
|
|
def _adjust_size(self):
|
|
parent = self.GetParent()
|
|
parent.sizer.Layout()
|
|
parent.Fit()
|
|
|
|
|
|
def make_cfg(self):
|
|
cfg = self.entries.get()
|
|
|
|
if not clargs.show_all_settings:
|
|
cfg = check_outgoing_cfg(cfg)
|
|
|
|
return cfg
|
|
|
|
|
|
def on_screenpanel(self, event):
|
|
cam = self.camera
|
|
cmd = f"screen_panel -persist -cam={cam}"
|
|
print(cmd)
|
|
subprocess.Popen(cmd.split(), start_new_session=True)
|
|
|
|
|
|
def on_get_roi_bkg(self, event):
|
|
roi = self._get_roi()
|
|
if roi is None:
|
|
return
|
|
self.entries.set("roi_background", roi)
|
|
|
|
def on_get_roi_sig(self, event):
|
|
roi = self._get_roi()
|
|
if roi is None:
|
|
return
|
|
self.entries.set("roi_signal", roi)
|
|
|
|
def on_get_roi_rad(self, event):
|
|
roi = self._get_roi()
|
|
if roi is None:
|
|
return
|
|
self.entries.set("roi_radial", roi)
|
|
|
|
|
|
def _get_roi(self):
|
|
cam = self.camera
|
|
si = pc.get_server_info()
|
|
all_pls = si["active_instances"]
|
|
cam_pls = [i for i in all_pls if i.startswith(cam)]
|
|
print(cam_pls)
|
|
suffices = ("sp", "sp1")
|
|
sp_pls = [i for i in cam_pls if i.split("_")[1] in suffices]
|
|
|
|
if len(sp_pls) == 0:
|
|
print("no screenpanel found for camera:", cam)
|
|
return None
|
|
|
|
if len(sp_pls) > 1:
|
|
print("several screenpanels found for camera:", cam)
|
|
for sp in sp_pls:
|
|
print("-", sp)
|
|
return None
|
|
|
|
sp = sp_pls[0]
|
|
cfg = pc.get_instance_config(sp)
|
|
roi = cfg["image_region_of_interest"]
|
|
if roi is None:
|
|
print("no roi set in screenpanel:", sp)
|
|
return None
|
|
|
|
xmin, xdelta, ymin, ydelta = roi
|
|
xmax = xmin + xdelta
|
|
ymax = ymin + ydelta
|
|
return ymin, ymax, xmin, xmax
|
|
|
|
|
|
def on_print(self, event):
|
|
old_cfg = self.orig_cfg
|
|
new_cfg = self.make_cfg()
|
|
print("\nold config:\n", old_cfg)
|
|
print("\nnew config:\n", new_cfg)
|
|
print("\nunchanged\n" if old_cfg == new_cfg else "\nchanged\n")
|
|
|
|
|
|
def on_save_cfg(self, event):
|
|
new_cfg = self.make_cfg()
|
|
pipeline = self.pls[self.instance]
|
|
res = pipeline.set(new_cfg)
|
|
print("result config:", res)
|
|
|
|
|
|
|
|
def check_incoming_cfg(cfg):
|
|
bkg_enable = cfg.get("image_background_enable")
|
|
if bkg_enable not in (None, "passive"):
|
|
printable_bkg_enable = printable(bkg_enable)
|
|
print(f"Warning: found: image_background_enable = {printable_bkg_enable}, this will be set to None or \"passive\" upon saving")
|
|
|
|
img_thresh = cfg.get("image_threshold")
|
|
if img_thresh is not None:
|
|
printable_img_thresh = printable(img_thresh)
|
|
print(f"Warning: found: image_threshold = {printable_img_thresh}, this will be set to None upon saving")
|
|
|
|
thresh = cfg.get("threshold")
|
|
if thresh is None:
|
|
print(f"Warning: found: threshold = None, will overwrite with value of image_threshold ({printable_img_thresh})")
|
|
|
|
script = cfg.get("function")
|
|
if script != SCRIPT_NAME:
|
|
printable_script = printable(script)
|
|
print(f"Warning: found: function = {printable_script}, this will be set to \"{SCRIPT_NAME}\" upon saving")
|
|
|
|
|
|
def check_outgoing_cfg(cfg):
|
|
bkg = cfg["image_background"]
|
|
cfg["image_background_enable"] = "passive" if bkg else None
|
|
|
|
cfg["image_threshold"] = None
|
|
cfg["function"] = SCRIPT_NAME
|
|
|
|
return cfg
|
|
|
|
|
|
def printable(val):
|
|
return repr(val).replace("'", '"')
|
|
|
|
|
|
def filter_dict(d, *args):
|
|
allkeys = itertools.chain.from_iterable(args)
|
|
return {k: d.get(k) for k in allkeys}
|
|
|
|
|
|
|
|
|
|
|
|
app = wx.App()
|
|
frame = MainFrame()
|
|
frame.Show()
|
|
app.MainLoop()
|
|
|
|
|
|
|