diff --git a/grum/BECAdapter.py b/grum/BECAdapter.py index f609505..13dd181 100644 --- a/grum/BECAdapter.py +++ b/grum/BECAdapter.py @@ -26,7 +26,7 @@ class BECAdapter: self.scan_nr = None self.scan_running = False - self.eaccount = "e20642" # for jeff: 20633 + self.eaccount = "e20633" # for jeff: 20633 # To decide what should be plotted self.monitor = monitor @@ -114,13 +114,17 @@ class BECAdapter: self.grum_client_monitor.append_data( "monitor", point) def plot_img_from_h5(self): + while True: # if self.last_plotted_scan_nr !=0: print('Check for new reconstruction') - self.update_latest_reconstructed() + self.update_latest_reconstructed() # uncomment for it to work properly + # self.latest_reconstructed += 4 + print('latest_reconstructed: ', self.latest_reconstructed) print("last plotted scan nr: ", self.last_plotted_scan_nr) + if self.latest_reconstructed > self.last_plotted_scan_nr: ending_path = self._get_scan_dir(1000, self.latest_reconstructed, leading_zeros = 5) @@ -139,6 +143,8 @@ class BECAdapter: self.last_plotted_scan_nr = self.latest_reconstructed time.sleep(10) + # if self.latest_reconstructed > 9245: + # break def get_recon_file(self, mypath): files = [f for f in listdir(mypath) if isfile(join(mypath, f))] for file in files: diff --git a/grum/mainwin.py b/grum/mainwin.py index 7e1dc87..a4c287e 100644 --- a/grum/mainwin.py +++ b/grum/mainwin.py @@ -4,10 +4,11 @@ import pyqtgraph as pg from . import assets from .dictlist import DictList +from .dictlist.dictlistitem import DictListItem from .exampledata import exampledata from .h5filedlg import open_h5_files_dialog, save_h5_file_dialog from .io import write_dict, read_dict -from .mdi import MDIArea, MDISubMultiPlot, MDISubPlot, MDISubImage, MDIWindowMode +from .mdi import MDIArea, MDISubMultiPlot, MDISubPlot, MDISubImage, MDIWindowMode, MDISubMultiImage from .menus import BarMenu from .plotdesc import PlotDescription from .imgdesc import ImageDescription @@ -93,6 +94,7 @@ class MainWindow(QMainWindow): rst.server.register_function(self.extend_data) rst.server.register_function(self.set_data) rst.server.register_function(self.new_image) + rst.server.register_function(self.plot_images_from_list) # function for CSAXS beamtime self.sig_make_new_plot.connect(self.on_make_new_plot) self.sig_make_new_image.connect(self.on_make_new_image) @@ -116,46 +118,7 @@ class MainWindow(QMainWindow): if not self.mdi.findSubWindow(name): self.sig_make_new_plot.emit(name, desc) - # else: - # print("else") - # if desc.title: - - # print("---------------------------------------------") - # print("self mdi exist, new title:", desc.title) - # sub = self.mdi.findSubWindow(name) - # print(sub.pw.plotItem.titleLabel) - # print(sub.pw.plotItem.titleLabel.text) - # vbox = sub.pw.getViewBox() - # vbox.removeItem(sub.pw.plotItem.titleLabel) - # #maybe add title? or just settitle? - # vbox.addItem(pg.LabelItem(desc.title, size='50pt')) - # # sub.pw.plotItem.titleLabel.setText(desc.title) - # print("------------------------------------") - - # print("clearing") - # if desc.title: - # sub.pw.clear() - # print("setting new title: ", desc.title) - # sub.pw.setTitle(desc.title) - # vbox = sub.pw.getView() - # vbox.addItem(pg.LabelItem(desc.title, size='50pt')) - # vbox.addItem(pg.titel) - - # allchildren = vbox.allChildren() - # for child in allchildren: - # print(child) - # if isinstance(child, pg.graphicsItems.ViewBox.ChildGroup): - # print("Found childGroup") - # allgrandchildren = vbox.allChildren(child) - # for grandchild in allgrandchildren: - # print(grandchild) - # # print("Removing label") - # # vbox.removeItem(child) - # print("-------------done-------------") - # vbox.addItem(pg.LabelItem(desc.title, size='50pt')) - # sub.pw.setTitle(desc.title) - - def append_data(self, name, point): #, title=None): + def append_data(self, name, point): """ Append a new data point to the (existing) plot . The point is forwarded to the append method of PlotDescription. @@ -163,8 +126,6 @@ class MainWindow(QMainWindow): item = self.lst.get(name) desc = item.value desc.append(point) - # if title: - # desc.changeTitle(title) self.sync_item_and_plots(item) def extend_data(self, name, data): @@ -208,6 +169,21 @@ class MainWindow(QMainWindow): else: self.sig_make_new_image.emit(name, desc) + def plot_images_from_list(self, image_desc_list): + """ + Plot images from list + """ + images = [] + i =1 + for img in image_desc_list: + self.new_image(img[0], img[1]) + # desc = ImageDescription(img[0], **img[1]) + # dlistitem = DictListItem(f"Phase: {i}", desc) + # images.append(dlistitem) + # i+=1 + + # self.plot_multiple_images(images) + # Signal callbacks @@ -227,6 +203,8 @@ class MainWindow(QMainWindow): if len(selected) == 1: item = selected[0] self.plot_single_item(item) + elif type(selected[0].value) == ImageDescription: + self.plot_multiple_images(selected) else: self.plot_multiple_items(selected) @@ -310,6 +288,23 @@ class MainWindow(QMainWindow): name = " | ".join(names) self.activate_or_make_subwin(MDISubMultiPlot, name, descs) + def plot_multiple_images(self, images): + if type(images[0]) == list: + print('it is a list') + + else: + print("this is imgdesc now: ", images) + for i in images: + i.timestamps.access.update() + i.set_alarm(False) + + descs = {i.key: i.value for i in images} + + names = descs.keys() + name = " | ".join(names) + print(names) + self.activate_or_make_subwin(MDISubMultiImage, name, descs) + #TODO: the following two could be methods to MDIArea? diff --git a/grum/mdi/__init__.py b/grum/mdi/__init__.py index e754999..b385e76 100644 --- a/grum/mdi/__init__.py +++ b/grum/mdi/__init__.py @@ -1,6 +1,6 @@ from .mdiarea import MDIArea, MDIWindowMode from .mdisubplot import MDISubPlot, MDISubMultiPlot -from .mdisubimg import MDISubImage +from .mdisubimg import MDISubImage, MDISubMultiImage diff --git a/grum/mdi/mdisubimg.py b/grum/mdi/mdisubimg.py index fff0666..0442182 100644 --- a/grum/mdi/mdisubimg.py +++ b/grum/mdi/mdisubimg.py @@ -1,12 +1,19 @@ import pyqtgraph as pg from .mdisubwin import MDISubWindow from ..theme import pg_plot_style +from PyQt5.QtWidgets import QMainWindow, QWidget, QPushButton, QGridLayout, QVBoxLayout, QApplication, QSlider +from PyQt5.QtCore import Qt, QThread, QTimer + +class MDISubImageBase(MDISubWindow): + def __init__(self, name, *args, **kwargs): + super().__init__(name, *args, **kwargs) -class MDISubImage(MDISubWindow): +class MDISubImage(MDISubImageBase): def __init__(self, name, desc, *args, **kwargs): super().__init__(name, *args, **kwargs) + self.pw = pw = pg.ImageView() self.setWidget(pw) @@ -14,7 +21,6 @@ class MDISubImage(MDISubWindow): pw.scene.sigMouseMoved.connect(self.on_hover) style = pg_plot_style() - # cm = pg.colormap.get('CET-C1') # pw.setColorMap(cm) @@ -23,7 +29,6 @@ class MDISubImage(MDISubWindow): self.image = desc.data - def on_hover(self, event): coord = self.pw.imageItem.mapFromScene(event) x = coord.x() @@ -38,4 +43,52 @@ class MDISubImage(MDISubWindow): self.setToolTip(f"x = {x}\ny = {y}\nz = {z}") +class MDISubMultiImage(MDISubImageBase): + def __init__(self, name, descs, *args, **kwargs): + super().__init__(name, *args, **kwargs) + self.central_widget = QWidget() + + # self.layout = QGridLayout() + + self.button_next = QPushButton('Next', self.central_widget) + self.button_previous = QPushButton('Previous', self.central_widget) + self.pw = pw = pg.ImageView() + self.slider = QSlider(Qt.Horizontal) + self.slider.setRange(0,len(descs)-1) + + self.layout = QGridLayout(self.central_widget) + self.layout.addWidget(self.button_next,1,2) + self.layout.addWidget(self.button_previous, 1,0) + self.layout.addWidget(self.pw, 0,0, 1,3) + self.layout.addWidget(self.slider, 1,1) + self.setWidget(self.central_widget) + + self.button_next.clicked.connect(self.update_img_next) + self.button_previous.clicked.connect(self.update_img_previous) + self.slider.valueChanged.connect(self.update_img) + + names = [names for names, _ in descs.items()] + self.descriptions = [desc for _, desc in descs.items()] + + desc = self.descriptions[0] + + style = pg_plot_style() + plot = desc.make_plot(self.pw, style) + self.plots = {name: plot} + self.image = desc.data + + + # self.update_timer = QTimer() + # self.update_timer.timeout.connect(self.update_movie) + + def update_img_next(self): + self.pw.setImage(self.descriptions[1].data) + self.slider.setValue(self.slider.value()+1) + + def update_img_previous(self): + self.pw.setImage(self.descriptions[0].data) + self.slider.setValue(self.slider.value()-1) + + def update_img(self, value): + self.pw.setImage(self.descriptions[value].data) diff --git a/grum/plot_multiple_phases.py b/grum/plot_multiple_phases.py new file mode 100644 index 0000000..0853f47 --- /dev/null +++ b/grum/plot_multiple_phases.py @@ -0,0 +1,76 @@ +from grum.rpc import RPCClient +from os import listdir +from os.path import isfile, join +import h5py +import numpy as np + +class plotPhases: + def __init__(self, start, end, step=1): + self.start = start + self.end = end + self.step =step + self.eaccount = "e20633" # for jeff: 20633 + self.grum_client = RPCClient("localhost", 8000) # this is outgoing + self.image_description_list = [] + + + def plot_all_phases(self): + + for scan_nr in range(self.start, self.end + 1, self.step): + print("retrieving data for scan: ", scan_nr) + ending_path = self._get_scan_dir(1000, scan_nr, leading_zeros = 5) + mypath = "/sls/X12SA/data/" + self.eaccount + "/Data10/analysis/" + ending_path + recon_file = self.get_recon_file(mypath) + with h5py.File(mypath + '/' + recon_file, 'r') as hf: + recon_img_phase = self.get_recon_phase(hf) + + xlab = str(scan_nr) + self.image_description_list.append([f"Phase: {scan_nr}", {'image': recon_img_phase, "xlabel": xlab}]) + + print("calling plot images from list") + self.grum_client.plot_images_from_list(self.image_description_list) + + def get_recon_phase(self, hf): + + recon = hf.get('reconstruction') + recon_object = hf.get('reconstruction/object') + # recon_probes = hf.get('reconstruction/probes') + + # recon_probes_1 = recon_probes[0] + # recon_probes_2 = recon_probes[1] + + recon_object = np.array(recon_object) + # recon_object_abs = np.abs(recon_object) + recon_object_angle = np.angle(recon_object) + + # recon_object_abs = np.rot90(recon_object_abs,3) + recon_object_angle = np.rot90(recon_object_angle, 3) + + # recon_img_abs = recon_object_abs.tolist() + recon_img_angle = recon_object_angle.tolist() + # return recon_img_abs, recon_img_angle + return recon_img_angle + + def get_recon_file(self, mypath): + files = [f for f in listdir(mypath) if isfile(join(mypath, f))] + for file in files: + if file.endswith("recons.h5"): + return file + print("no file fro this scan nr") + return None + + def _get_scan_dir(self, scan_bundle, scan_number, leading_zeros=None): + if leading_zeros is None: + leading_zeros = len(str(scan_bundle)) + floor_dir = scan_number // scan_bundle * scan_bundle + return f"S{floor_dir:0{leading_zeros}d}-{floor_dir+scan_bundle-1:0{leading_zeros}d}/S{scan_number:0{leading_zeros}d}" + + +if __name__ == "__main__": + start = 10296 + end = 10300 + step = 1 + print('starts plotting phase for scans: ',start, ' to ', end) + + pp = plotPhases(start, end) + pp.plot_all_phases() \ No newline at end of file diff --git a/setup.py b/setup.py index bdf4a69..06fa014 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ if __name__ == "__main__": # subprocess.run(f"pip install -e {bec_utils}", shell=True, check=True) setup( - install_requires=["pyqt5==5.12", "pyqtgraph", "h5py", "PyQtWebEngine==5.12"], #this version works for comp1 CSAXS, no later version + install_requires=["pyqt5==5.12", "pyqtgraph", "h5py", "PyQtWebEngine==5.12", "Pillow"], #this version works for comp1 CSAXS, no later version entry_points={"console_scripts": ["grum=grum:main"]}, )