get list names, thoughts about multiplotting
This commit is contained in:
108
grum/mainwin.py
108
grum/mainwin.py
@ -14,17 +14,16 @@ from .plotdesc import PlotDescription
|
|||||||
from .imgdesc import ImageDescription
|
from .imgdesc import ImageDescription
|
||||||
from .rpc import RPCServerThread
|
from .rpc import RPCServerThread
|
||||||
from .shortcut import shortcut
|
from .shortcut import shortcut
|
||||||
# from .webview import WebView # doesnt work for CSAXS version of pyqtWebEngine
|
# from .webview import WebView # doesnt work for CSAXS version of pyqtWebEngine
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(QMainWindow):
|
class MainWindow(QMainWindow):
|
||||||
|
|
||||||
sig_make_new_plot = pyqtSignal(str, PlotDescription)
|
sig_make_new_plot = pyqtSignal(str, PlotDescription)
|
||||||
sig_make_new_image = pyqtSignal(str, ImageDescription)
|
sig_make_new_image = pyqtSignal(str, ImageDescription)
|
||||||
|
|
||||||
def __init__(self, *args, title="grum", host="localhost", port=8000, offline=False, add_examples=False, window_mode=MDIWindowMode.MULTI, **kwargs):
|
def __init__(self, *args, title="grum", host="localhost", port=8000, offline=False, add_examples=False, window_mode=MDIWindowMode.MULTI, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
if offline:
|
if offline:
|
||||||
title = f"{title} (offline)"
|
title = f"{title} (offline)"
|
||||||
@ -33,7 +32,7 @@ class MainWindow(QMainWindow):
|
|||||||
self.setWindowIcon(assets.icon())
|
self.setWindowIcon(assets.icon())
|
||||||
|
|
||||||
url = f"http://{host}:{port}/"
|
url = f"http://{host}:{port}/"
|
||||||
# self.webdoc = WebView(url, title=title) # doesnt work for CSAXS version of pyqtWebEngine
|
# self.webdoc = WebView(url, title=title) # doesnt work for CSAXS version of pyqtWebEngine
|
||||||
|
|
||||||
self.lst = lst = DictList()
|
self.lst = lst = DictList()
|
||||||
lst.setAlternatingRowColors(True)
|
lst.setAlternatingRowColors(True)
|
||||||
@ -46,16 +45,21 @@ class MainWindow(QMainWindow):
|
|||||||
lst_menu.addSeparator()
|
lst_menu.addSeparator()
|
||||||
lst_menu.addAction("Plot selected", self.on_plot_selected)
|
lst_menu.addAction("Plot selected", self.on_plot_selected)
|
||||||
lst_menu.addSeparator()
|
lst_menu.addSeparator()
|
||||||
lst_menu.addAction("Mark selected as seen", self.on_mark_selected_as_seen)
|
lst_menu.addAction("Mark selected as seen",
|
||||||
lst_menu.addAction("Mark selected as not seen", self.on_mark_selected_as_not_seen)
|
self.on_mark_selected_as_seen)
|
||||||
|
lst_menu.addAction("Mark selected as not seen",
|
||||||
|
self.on_mark_selected_as_not_seen)
|
||||||
lst_menu.addSeparator()
|
lst_menu.addSeparator()
|
||||||
sort_group = lst_menu.addGroup()
|
sort_group = lst_menu.addGroup()
|
||||||
sort_group.addCheckbox("Sort by insertion order", triggered=self.on_sort_by_insertion_order, state=True)
|
sort_group.addCheckbox(
|
||||||
|
"Sort by insertion order", triggered=self.on_sort_by_insertion_order, state=True)
|
||||||
sort_group.addCheckbox("Sort by name", triggered=self.on_sort_by_name)
|
sort_group.addCheckbox("Sort by name", triggered=self.on_sort_by_name)
|
||||||
sort_group.addCheckbox("Sort by timestamp", triggered=self.on_sort_by_timestamp)
|
sort_group.addCheckbox("Sort by timestamp",
|
||||||
sort_group.addCheckbox("Sorting disabled", triggered=self.on_sorting_disabled)
|
triggered=self.on_sort_by_timestamp)
|
||||||
|
sort_group.addCheckbox(
|
||||||
|
"Sorting disabled", triggered=self.on_sorting_disabled)
|
||||||
|
|
||||||
#TODO: clean up
|
# TODO: clean up
|
||||||
def on_item_about_to_be_moved():
|
def on_item_about_to_be_moved():
|
||||||
sort_group.checkboxes["Sorting disabled"].setChecked(True)
|
sort_group.checkboxes["Sorting disabled"].setChecked(True)
|
||||||
self.on_sorting_disabled()
|
self.on_sorting_disabled()
|
||||||
@ -75,7 +79,8 @@ class MainWindow(QMainWindow):
|
|||||||
self.menu_settings = menu = BarMenu(bar, "&Settings")
|
self.menu_settings = menu = BarMenu(bar, "&Settings")
|
||||||
menu.addCheckbox("Open new plots", state=True)
|
menu.addCheckbox("Open new plots", state=True)
|
||||||
menu.addSeparator()
|
menu.addSeparator()
|
||||||
menu.addEntrybox("Limit number of entries", placeholder="Maximum number of entries", triggered=lst.set_nkeep)
|
menu.addEntrybox("Limit number of entries",
|
||||||
|
placeholder="Maximum number of entries", triggered=lst.set_nkeep)
|
||||||
|
|
||||||
self.mdi = mdi = MDIArea(bar, window_mode=window_mode)
|
self.mdi = mdi = MDIArea(bar, window_mode=window_mode)
|
||||||
|
|
||||||
@ -87,25 +92,28 @@ class MainWindow(QMainWindow):
|
|||||||
self.setCentralWidget(splitter)
|
self.setCentralWidget(splitter)
|
||||||
|
|
||||||
if not offline:
|
if not offline:
|
||||||
self.rst = rst = RPCServerThread(host, port, doc_title_suffix=title)
|
self.rst = rst = RPCServerThread(
|
||||||
|
host, port, doc_title_suffix=title)
|
||||||
rst.start()
|
rst.start()
|
||||||
rst.server.register_function(self.new_plot)
|
rst.server.register_function(self.new_plot)
|
||||||
rst.server.register_function(self.append_data)
|
rst.server.register_function(self.append_data)
|
||||||
rst.server.register_function(self.extend_data)
|
rst.server.register_function(self.extend_data)
|
||||||
rst.server.register_function(self.set_data)
|
rst.server.register_function(self.set_data)
|
||||||
rst.server.register_function(self.new_image)
|
rst.server.register_function(self.new_image)
|
||||||
rst.server.register_function(self.append_image_to_list) # function for CSAXS beamtime
|
# function for CSAXS beamtime
|
||||||
|
rst.server.register_function(self.append_image_to_list)
|
||||||
|
# new function to get list of names from current grum session
|
||||||
|
rst.server.register_function(self.get_list_names)
|
||||||
|
# rst.server.register_function(self.plot_multiple_plots)
|
||||||
|
|
||||||
self.sig_make_new_plot.connect(self.on_make_new_plot)
|
self.sig_make_new_plot.connect(self.on_make_new_plot)
|
||||||
self.sig_make_new_image.connect(self.on_make_new_image)
|
self.sig_make_new_image.connect(self.on_make_new_image)
|
||||||
|
|
||||||
|
|
||||||
def keyPressEvent(self, event):
|
def keyPressEvent(self, event):
|
||||||
if event.key() == Qt.Key_F1:
|
if event.key() == Qt.Key_F1:
|
||||||
# self.webdoc.show() # doesnt work for CSAXS version of pyqtWebEngine
|
# self.webdoc.show() # doesnt work for CSAXS version of pyqtWebEngine
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
# Remote API calls
|
# Remote API calls
|
||||||
|
|
||||||
def new_plot(self, name, cfg):
|
def new_plot(self, name, cfg):
|
||||||
@ -155,14 +163,15 @@ class MainWindow(QMainWindow):
|
|||||||
The configuration is forwarded to the constructor of ImageDescription.
|
The configuration is forwarded to the constructor of ImageDescription.
|
||||||
Allowed keys are: title, xlabel, ylabel, image.
|
Allowed keys are: title, xlabel, ylabel, image.
|
||||||
"""
|
"""
|
||||||
desc = self.add_new_desc_to_list(name, cfg, Desc=ImageDescription) #TODO: clean up Desc argument
|
desc = self.add_new_desc_to_list(
|
||||||
|
name, cfg, Desc=ImageDescription) # TODO: clean up Desc argument
|
||||||
if self.menu_settings.checkboxes["Open new plots"].isChecked():
|
if self.menu_settings.checkboxes["Open new plots"].isChecked():
|
||||||
sub = self.mdi.findSubWindow(name)
|
sub = self.mdi.findSubWindow(name)
|
||||||
if sub:
|
if sub:
|
||||||
sub.pw.setImage(desc.data) #TODO lacks the list sync
|
sub.pw.setImage(desc.data) # TODO lacks the list sync
|
||||||
vbox = sub.pw.getView()
|
vbox = sub.pw.getView()
|
||||||
allchildren = vbox.allChildren()
|
allchildren = vbox.allChildren()
|
||||||
for child in allchildren:
|
for child in allchildren:
|
||||||
if isinstance(child, pg.LabelItem):
|
if isinstance(child, pg.LabelItem):
|
||||||
vbox.removeItem(child)
|
vbox.removeItem(child)
|
||||||
vbox.addItem(pg.LabelItem(desc.xlabel, size='50pt'))
|
vbox.addItem(pg.LabelItem(desc.xlabel, size='50pt'))
|
||||||
@ -171,7 +180,41 @@ class MainWindow(QMainWindow):
|
|||||||
self.sig_make_new_image.emit(name, desc)
|
self.sig_make_new_image.emit(name, desc)
|
||||||
|
|
||||||
def append_image_to_list(self, img):
|
def append_image_to_list(self, img):
|
||||||
desc = self.add_new_desc_to_list(img[0], img[1], Desc=ImageDescription)
|
desc = self.add_new_desc_to_list(img[0], img[1], Desc=ImageDescription)
|
||||||
|
|
||||||
|
def get_list_names(self):
|
||||||
|
return [key for key in self.lst.lst.items.keys()]
|
||||||
|
|
||||||
|
# def plot_multiple_plots(self, aa):
|
||||||
|
|
||||||
|
# name = "plot 1"
|
||||||
|
# cfg = {"xs": [0, 1], "ys": [3, 7]}
|
||||||
|
# desc = self.add_new_desc_to_list(name, cfg)
|
||||||
|
# name = "plot 2"
|
||||||
|
# cfg = {"xs": [0, 3], "ys": [2,0]}
|
||||||
|
# desc2 = self.add_new_desc_to_list(name, cfg)
|
||||||
|
# items = [self.lst.get("plot 1"), self.lst.get("plot 2")]
|
||||||
|
# self.plot_multiple_items(items)
|
||||||
|
|
||||||
|
|
||||||
|
# descs = {i.name: i for i in items}
|
||||||
|
# names = descs.keys()
|
||||||
|
# name = " | ".join(names)
|
||||||
|
|
||||||
|
# self.activate_or_make_subwin(MDISubMultiPlot, name, descs)
|
||||||
|
|
||||||
|
# if self.menu_settings.checkboxes["Open new plots"].isChecked():
|
||||||
|
# if not self.mdi.findSubWindow(name):
|
||||||
|
# self.sig_make_new_plot.emit(name, desc)
|
||||||
|
|
||||||
|
# self.make_subwin(MDISubMultiPlot, name, **descs)
|
||||||
|
# if not self.mdi.findSubWindow(name):
|
||||||
|
# sub = MDISubMultiPlot(name, descs)
|
||||||
|
# print("multi name", name)
|
||||||
|
# print("multi descs", descs, *descs)
|
||||||
|
# print("MULTI sub", sub)
|
||||||
|
# print("multi mdi", self.mdi)
|
||||||
|
# self.mdi.add(sub)
|
||||||
|
|
||||||
# Signal callbacks
|
# Signal callbacks
|
||||||
|
|
||||||
@ -191,19 +234,18 @@ class MainWindow(QMainWindow):
|
|||||||
if len(selected) == 1:
|
if len(selected) == 1:
|
||||||
item = selected[0]
|
item = selected[0]
|
||||||
self.plot_single_item(item)
|
self.plot_single_item(item)
|
||||||
elif type(selected[0].value) == ImageDescription: #TODO: what should be the typecheck?
|
# TODO: what should be the typecheck?
|
||||||
|
elif type(selected[0].value) == ImageDescription:
|
||||||
self.plot_multiple_images(selected)
|
self.plot_multiple_images(selected)
|
||||||
else:
|
else:
|
||||||
self.plot_multiple_items(selected)
|
self.plot_multiple_items(selected)
|
||||||
|
|
||||||
|
|
||||||
def on_mark_selected_as_seen(self):
|
def on_mark_selected_as_seen(self):
|
||||||
self.lst.set_alarm_for_selected(False)
|
self.lst.set_alarm_for_selected(False)
|
||||||
|
|
||||||
def on_mark_selected_as_not_seen(self):
|
def on_mark_selected_as_not_seen(self):
|
||||||
self.lst.set_alarm_for_selected(True)
|
self.lst.set_alarm_for_selected(True)
|
||||||
|
|
||||||
|
|
||||||
def on_sort_by_insertion_order(self):
|
def on_sort_by_insertion_order(self):
|
||||||
self.lst.enable_sort_by_insertion_order()
|
self.lst.enable_sort_by_insertion_order()
|
||||||
|
|
||||||
@ -216,7 +258,6 @@ class MainWindow(QMainWindow):
|
|||||||
def on_sorting_disabled(self):
|
def on_sorting_disabled(self):
|
||||||
self.lst.disable_sorting()
|
self.lst.disable_sorting()
|
||||||
|
|
||||||
|
|
||||||
def on_file_open(self):
|
def on_file_open(self):
|
||||||
fns = open_h5_files_dialog(self)
|
fns = open_h5_files_dialog(self)
|
||||||
if not fns:
|
if not fns:
|
||||||
@ -225,10 +266,9 @@ class MainWindow(QMainWindow):
|
|||||||
for fn in fns:
|
for fn in fns:
|
||||||
data = read_dict(fn)
|
data = read_dict(fn)
|
||||||
for k, v in data.items():
|
for k, v in data.items():
|
||||||
Desc = ImageDescription if "image" in v else PlotDescription #TODO
|
Desc = ImageDescription if "image" in v else PlotDescription # TODO
|
||||||
self.add_new_desc_to_list(k, v, Desc=Desc)
|
self.add_new_desc_to_list(k, v, Desc=Desc)
|
||||||
|
|
||||||
|
|
||||||
def on_file_save(self):
|
def on_file_save(self):
|
||||||
fn = save_h5_file_dialog(self)
|
fn = save_h5_file_dialog(self)
|
||||||
if not fn:
|
if not fn:
|
||||||
@ -241,10 +281,9 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
write_dict(fn, data)
|
write_dict(fn, data)
|
||||||
|
|
||||||
|
|
||||||
# Plumbing
|
# Plumbing
|
||||||
|
|
||||||
def add_new_desc_to_list(self, name, cfg, Desc=PlotDescription): #TODO
|
def add_new_desc_to_list(self, name, cfg, Desc=PlotDescription): # TODO
|
||||||
desc = Desc(name, **cfg)
|
desc = Desc(name, **cfg)
|
||||||
self.lst.set(name, desc)
|
self.lst.set(name, desc)
|
||||||
return desc
|
return desc
|
||||||
@ -264,7 +303,8 @@ class MainWindow(QMainWindow):
|
|||||||
item.timestamps.access.update()
|
item.timestamps.access.update()
|
||||||
item.set_alarm(False)
|
item.set_alarm(False)
|
||||||
name, desc = item.key, item.value
|
name, desc = item.key, item.value
|
||||||
MDISubType = MDISubImage if isinstance(desc, ImageDescription) else MDISubPlot #TODO
|
MDISubType = MDISubImage if isinstance(
|
||||||
|
desc, ImageDescription) else MDISubPlot # TODO
|
||||||
self.activate_or_make_subwin(MDISubType, name, desc)
|
self.activate_or_make_subwin(MDISubType, name, desc)
|
||||||
|
|
||||||
def plot_multiple_items(self, items):
|
def plot_multiple_items(self, items):
|
||||||
@ -277,20 +317,19 @@ class MainWindow(QMainWindow):
|
|||||||
self.activate_or_make_subwin(MDISubMultiPlot, name, descs)
|
self.activate_or_make_subwin(MDISubMultiPlot, name, descs)
|
||||||
|
|
||||||
def plot_multiple_images(self, images):
|
def plot_multiple_images(self, images):
|
||||||
|
|
||||||
for i in images:
|
for i in images:
|
||||||
i.timestamps.access.update()
|
i.timestamps.access.update()
|
||||||
i.set_alarm(False)
|
i.set_alarm(False)
|
||||||
descs = {i.key: i.value for i in images}
|
descs = {i.key: i.value for i in images}
|
||||||
names = descs.keys()
|
names = descs.keys()
|
||||||
name = " | ".join(names)
|
name = " | ".join(names)
|
||||||
self.activate_or_make_subwin(MDISubMultiImage, name, descs)
|
self.activate_or_make_subwin(MDISubMultiImage, name, descs)
|
||||||
|
|
||||||
#TODO: the following two could be methods to MDIArea?
|
# TODO: the following two could be methods to MDIArea?
|
||||||
|
|
||||||
def activate_or_make_subwin(self, MDISubType, name, *args, **kwargs):
|
def activate_or_make_subwin(self, MDISubType, name, *args, **kwargs):
|
||||||
sub = self.mdi.findSubWindow(name)
|
sub = self.mdi.findSubWindow(name)
|
||||||
if sub: #TODO check type? what to do for mismatches?
|
if sub: # TODO check type? what to do for mismatches?
|
||||||
self.mdi.setActiveSubWindow(sub)
|
self.mdi.setActiveSubWindow(sub)
|
||||||
else:
|
else:
|
||||||
self.make_subwin(MDISubType, name, *args, **kwargs)
|
self.make_subwin(MDISubType, name, *args, **kwargs)
|
||||||
@ -298,6 +337,3 @@ class MainWindow(QMainWindow):
|
|||||||
def make_subwin(self, MDISubType, name, *args, **kwargs):
|
def make_subwin(self, MDISubType, name, *args, **kwargs):
|
||||||
sub = MDISubType(name, *args, **kwargs)
|
sub = MDISubType(name, *args, **kwargs)
|
||||||
self.mdi.add(sub)
|
self.mdi.add(sub)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ class PlotDescription:
|
|||||||
|
|
||||||
def make_plot(self, plotwidget, style):
|
def make_plot(self, plotwidget, style):
|
||||||
if self.format:
|
if self.format:
|
||||||
res = plot_with_format()
|
res = self.plot_with_format(plotwidget, style)
|
||||||
else:
|
else:
|
||||||
res = plotwidget.plot(self.xs, self.ys, name=self.name, **style)
|
res = plotwidget.plot(self.xs, self.ys, name=self.name, **style)
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ class PlotDescription:
|
|||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
return {k: v for k, v in self.__dict__.items() if not k.startswith("_") and k != "name" and v is not None}
|
return {k: v for k, v in self.__dict__.items() if not k.startswith("_") and k != "name" and v is not None}
|
||||||
|
|
||||||
def plot_with_format():
|
def plot_with_format(self, plotwidget, style):
|
||||||
if self.format == "Line":
|
if self.format == "Line":
|
||||||
res = plotwidget.plot(self.xs, self.ys, name=self.name, pen="w")
|
res = plotwidget.plot(self.xs, self.ys, name=self.name, pen="w")
|
||||||
elif self.format == "Dots":
|
elif self.format == "Dots":
|
||||||
|
Reference in New Issue
Block a user