From ae037596dc469aaf727d23d57f65aecbcd5efba3 Mon Sep 17 00:00:00 2001 From: gao <81c52427-d970-4b21-86dc-fd526913f4c9@localhost> Date: Wed, 10 Aug 2022 16:40:15 +0200 Subject: [PATCH] Finally, achieve the living plotting --- .idea/workspace.xml | 95 +++++++++++--------- HelperClasses/AbsorptionImaging.py | 5 +- HelperClasses/Plotting/DataExtractorLyse.py | 47 +++------- HelperClasses/Plotting/MainPlotPanel.py | 38 ++++++-- HelperClasses/Plotting/WidgetAnalysePanel.py | 3 + HelperClasses/Plotting/WidgetDataSelector.py | 2 +- HelperClasses/Plotting/WidgetPlot.py | 1 + living_plot_class.py | 93 +++++++++++++++++++ living_plot_main.py | 16 ++++ living_plot_starter.py | 31 +++++++ test.py | 13 ++- test_living_plot.py | 34 +++---- text2.py | 14 +++ 13 files changed, 287 insertions(+), 105 deletions(-) create mode 100644 living_plot_class.py create mode 100644 living_plot_main.py create mode 100644 living_plot_starter.py create mode 100644 text2.py diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 12321fd..402f9ec 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,16 +1,19 @@ - - + + + + + - - - + + + - - + + - - - - + + + + + + + - - - @@ -189,7 +192,8 @@ - + + 1658494877565 @@ -226,7 +230,14 @@ - @@ -249,7 +260,8 @@ - @@ -295,9 +307,12 @@ - + + + + \ No newline at end of file diff --git a/HelperClasses/AbsorptionImaging.py b/HelperClasses/AbsorptionImaging.py index 214626a..e6acf8b 100644 --- a/HelperClasses/AbsorptionImaging.py +++ b/HelperClasses/AbsorptionImaging.py @@ -117,9 +117,9 @@ class absorption_imaging: mean += np.average(image[0:int(image.shape[0] * y_fraction), 0:int(image.shape[1] * x_fraction)]) mean += np.average(image[0:int(image.shape[0] * y_fraction), int(image.shape[1] - image.shape[1] * x_fraction):int(image.shape[1])]) - mean += np.average(image[int(image.shape[0] - image.shape[0] * y_fraction):int(image.shape[1]), + mean += np.average(image[int(image.shape[0] - image.shape[0] * y_fraction):int(image.shape[0]), 0:int(image.shape[1] * x_fraction)]) - mean += np.average(image[int(image.shape[0] - image.shape[0] * y_fraction):int(image.shape[1]), + mean += np.average(image[int(image.shape[0] - image.shape[0] * y_fraction):int(image.shape[0]), int(image.shape[1] - image.shape[1] * x_fraction):int(image.shape[1])]) mean = mean / 4 @@ -137,6 +137,7 @@ class absorption_imaging: self.image_absorption_cut = self.image_absorption[self.y_start:self.y_end, self.x_start:self.x_end] back_ground = self.corner_subtract(self.image_absorption_cut, 0.1, 0.1) + self.image_absorption_cut = self.image_absorption_cut - back_ground self.image_absorption_remove_background = self.image_absorption - back_ground diff --git a/HelperClasses/Plotting/DataExtractorLyse.py b/HelperClasses/Plotting/DataExtractorLyse.py index 6fd3438..17ae814 100644 --- a/HelperClasses/Plotting/DataExtractorLyse.py +++ b/HelperClasses/Plotting/DataExtractorLyse.py @@ -23,11 +23,14 @@ class DataExtractorManager: def __init__(self, data_path=None): self.data_extractors = {} - # self.h5_file = None self.data_path = data_path self.local_data_changed = False def update_local_data(self, h5_path): + + h5_path = h5_path.replace('\n', '') + h5_path = os.path.join(h5_path) + with h5py.File(h5_path, 'r') as h5_file: self.local_data_changed = False for key in self.data_extractors: @@ -76,41 +79,15 @@ class DataExtractor: self.data_type = type self.data_label = label - def extract_data(self, h5_path, h5_file=None): + def extract_data(self, h5_file): result = None - data_handle = lyse.Run(h5_path, no_write=True) - - if self.data_type == 'array': - try: - result = data_handle.get_result_array(self.data_path[0], self.data_path[1], - h5_file=h5_file) - result = np.array(result) - except: - result = None - - elif self.data_type == 'single': - try: - result = data_handle.get_result(self.data_path[0], self.data_path[1], - h5_file=h5_file) - except: - result = None - - elif self.data_type == 'global': - try: - result = data_handle.get_globals(self.data_path[0], h5_file=h5_file) - result = result[self.data_path[1]] - except: - result = None - - elif self.data_type == 'image': - try: - result = data_handle.get_image(self.data_path[0], self.data_path[1], - self.data_path[2], h5_file=h5_file) - result = np.array(result) - except: - result = None + try: + result = h5_file[self.data_path][()] + result = np.array(result) + except: + result = None return result @@ -118,7 +95,7 @@ class DataExtractor: if h5_path in self.local_datas and self.local_mtimes[h5_path] == get_mtime(h5_path): self.local_data_changed = False elif self.load_to_ram: - self.local_datas[h5_path] = self.extract_data(h5_path, h5_file=h5_file) + self.local_datas[h5_path] = self.extract_data(h5_file) self.local_mtimes[h5_path] = get_mtime(h5_path) self.local_data_changed = True @@ -138,7 +115,7 @@ class DataExtractor: def clean_memory(self, h5_paths): for key in list(self.local_datas): - if key not in h5_paths.to_list(): + if key not in h5_paths.tolist(): del self.local_datas[key] del self.local_mtimes[key] diff --git a/HelperClasses/Plotting/MainPlotPanel.py b/HelperClasses/Plotting/MainPlotPanel.py index 19fa940..2691677 100644 --- a/HelperClasses/Plotting/MainPlotPanel.py +++ b/HelperClasses/Plotting/MainPlotPanel.py @@ -1,23 +1,38 @@ import pyqtgraph as pg from pyqtgraph.Qt import QtCore, QtGui import numpy as np +import os from pyqtgraph.dockarea import * from PyQt5.QtWidgets import * from PyQt5.QtCore import * -import lyse from .WidgetDataSelector import WidgetDataSelector from .WidgetAnalysePanel import WidgetAnalysePanel +def write_pid(): + with open("living_plot.ini", 'w') as pid_file: + pid = os.getpid() + pid_file.write(str(pid)) + + return pid + + +def clean_pid(): + with open("living_plot.ini", 'w') as pid_file: + pid_file.truncate(0) + + class MainPlotPanel(QtGui.QMainWindow): def __init__(self, h5_paths, n_rows=3, **kwargs): - self.h5_paths = h5_paths - super().__init__(**kwargs) + write_pid() + + self.h5_paths = np.array(h5_paths) + pg.mkQApp() self.n_rows = n_rows @@ -53,7 +68,9 @@ class MainPlotPanel(QtGui.QMainWindow): self.shotselector.valueChanged.connect(self.refresh) self.shotselector.selectionChanged.connect(self.refresh) - self.df = lyse.data() + def closeEvent(self, event): + clean_pid() + event.accept() def add_plot_dock(self, plot_name, plot_widget, overlap=True, **kwargs): if plot_name not in self.plots: @@ -87,27 +104,30 @@ class MainPlotPanel(QtGui.QMainWindow): del self.plots[dock.title()] def update_h5_paths(self, h5_paths): - self.h5_paths = h5_paths + self.h5_paths = np.array(h5_paths) self.shotselector.update_nshots(len(h5_paths)) for plot_name in self.plots: self.plots[plot_name].data_extractor_manager.clean_memory(h5_paths) + def add_h5_path(self, h5_path): + self.h5_paths = np.append(self.h5_paths, h5_path) + + self.shotselector.update_nshots(len(self.h5_paths)) + def refresh(self, h5_path=None): if len(self.h5_paths): - self.h5_paths_selected = self.h5_paths.iloc[self.shotselector.get_selected_indices()] + self.h5_paths_selected = self.h5_paths[np.array(self.shotselector.get_selected_indices())] if h5_path == None: i = self.shotselector.get_current_index() - h5_path = self.h5_paths.iloc[i] + h5_path = self.h5_paths[np.array(i)] for plot_name in self.plots: self.plots[plot_name].data_extractor_manager.update_local_data(h5_path) - # self.data_extractor_manager.update_local_data(h5_path) - for plot_name, plot in self.plots.items(): plot.update_from_h5(h5_path) else: diff --git a/HelperClasses/Plotting/WidgetAnalysePanel.py b/HelperClasses/Plotting/WidgetAnalysePanel.py index 58d6113..06ed446 100644 --- a/HelperClasses/Plotting/WidgetAnalysePanel.py +++ b/HelperClasses/Plotting/WidgetAnalysePanel.py @@ -32,6 +32,9 @@ class WidgetAnalysePanel(QSplitter): x, y = self.absorption_image_plot.roi.pos() x_span, y_span = self.absorption_image_plot.roi.size() + x = x + x_span / 2 + y = y + y_span / 2 + x = int(x) y = int(y) x_span = int(x_span) diff --git a/HelperClasses/Plotting/WidgetDataSelector.py b/HelperClasses/Plotting/WidgetDataSelector.py index a150366..f102416 100644 --- a/HelperClasses/Plotting/WidgetDataSelector.py +++ b/HelperClasses/Plotting/WidgetDataSelector.py @@ -128,4 +128,4 @@ class WidgetDataSelector(pg.LayoutWidget): return int(self.current_idx_le.text()) % self.nshots def get_selected_indices(self): - return (np.array(self.idx_selected),) \ No newline at end of file + return np.array(self.idx_selected) \ No newline at end of file diff --git a/HelperClasses/Plotting/WidgetPlot.py b/HelperClasses/Plotting/WidgetPlot.py index 646e608..1c59dfe 100644 --- a/HelperClasses/Plotting/WidgetPlot.py +++ b/HelperClasses/Plotting/WidgetPlot.py @@ -44,6 +44,7 @@ class WidgetPlot(QSplitter): self.data_extractor_manager = DataExtractorManager() def update_from_h5(self, h5_path): + h5_path = h5_path.replace('\n', '') if self.h5_path_shown != h5_path or self.data_extractor_manager.local_data_changed: self.h5_path_shown = h5_path self.update(h5_path) diff --git a/living_plot_class.py b/living_plot_class.py new file mode 100644 index 0000000..b24c982 --- /dev/null +++ b/living_plot_class.py @@ -0,0 +1,93 @@ +import lyse +import numpy as np +from PyQt5.QtCore import QTimer + +from HelperClasses.Plotting import WidgetFakeColorPlot, MainPlotPanel, Widget1DLivingPlot +from HelperClasses import DyTransition, Camera, AbsorptionImaging + +import cProfile +import pstats + + +class FigureManager: + def __init__(self): + self.MainPlotPanel = None + self.timer = None + self.h5_paths = np.empty(0) + + def refresh_h5_path(self): + with open(r'D:\Jianshun Gao\Simulations\DyLab\publishedPackage\dylab\h5_file_path.ini', 'r') as h5_path_file: + h5_path_new = np.array(h5_path_file.readlines()) + + if len(h5_path_new) == len(self.h5_paths) + 1: + + if len(h5_path_new) == 1 or (h5_path_new[:len(h5_path_new) - 1] == self.h5_paths).any(): + + h5_path = h5_path_new[len(h5_path_new) - 1] + self.MainPlotPanel.add_h5_path(h5_path) + self.h5_paths = np.append(self.h5_paths, h5_path) + self.MainPlotPanel.refresh(h5_path) + + elif len(h5_path_new) == len(self.h5_paths): + + if not (self.h5_paths == h5_path_new).any(): + + self.h5_paths = h5_path_new + self.MainPlotPanel.update_h5_paths(h5_path_new) + self.MainPlotPanel.refresh(h5_path_new[len(h5_path_new) - 1]) + + else: + self.h5_paths = h5_path_new + self.MainPlotPanel.update_h5_paths(h5_path_new) + self.MainPlotPanel.refresh(h5_path_new[len(h5_path_new) - 1]) + + def start_living_plot(self, h5_paths): + + self.MainPlotPanel = MainPlotPanel.MainPlotPanel(h5_paths) + + plot_name = '3D-MOT Absorption Imaging - With Atoms' + if not plot_name in self.MainPlotPanel.plots: + current_plotting = WidgetFakeColorPlot.WidgetFakeColorPlot(plot_name + '1', + data_path=r"images/MOT_3D_Camera/in_situ_absorption/atoms", + Roi=False, colorbarText=False) + self.MainPlotPanel.add_plot_dock(plot_name + '1', current_plotting) + + plot_name = '3D-MOT Absorption Imaging - Without Atoms' + if not plot_name in self.MainPlotPanel.plots: + current_plotting = WidgetFakeColorPlot.WidgetFakeColorPlot(plot_name + '1', + data_path=r"images/MOT_3D_Camera/in_situ_absorption/background", + Roi=False, colorbarText=False) + self.MainPlotPanel.add_plot_dock(plot_name + '1', current_plotting) + + plot_name = '3D-MOT Absorption Imaging - Dark' + if not plot_name in self.MainPlotPanel.plots: + current_plotting = WidgetFakeColorPlot.WidgetFakeColorPlot(plot_name + '1', + data_path=r"images/MOT_3D_Camera/in_situ_absorption/dark", + Roi=False, colorbarText=False) + self.MainPlotPanel.add_plot_dock(plot_name + '1', current_plotting) + + plot_name = r'3D-MOT Absorption Imaging' + if not plot_name in self.MainPlotPanel.plots: + current_plotting = WidgetFakeColorPlot.WidgetFakeColorPlot(plot_name, + data_path=r"results/absorption_imaging/absorption_imaging") + + self.MainPlotPanel.add_plot_dock(plot_name, current_plotting) + + absorption_imaging_transition = DyTransition.creat_Dy421() + mot_3D_camera = Camera.c11440_36u(absorption_imaging_transition['wavelength']) + absorption_image = AbsorptionImaging.absorption_imaging(None, 'MOT_3D_Camera', 'in_situ_absorption', + absorption_imaging_transition, mot_3D_camera, 0, 0) + self.MainPlotPanel.analyse_panel.add_absorption_imaging(absorption_image, current_plotting) + + # Add realtime plotting for atom number + # plot_name = '3D-MOT Atom Number' + # if not plot_name in self.MainPlotPanel.plots: + # current_plotting = Widget1DLivingPlot.Widget1DLivingPlot(plot_name, y_data_path=('absorption_imaging', 'atom_number'), y_in_results=True) + # + # self.MainPlotPanel.add_plot_dock(plot_name, current_plotting) + + self.timer = QTimer() + self.timer.timeout.connect(self.refresh_h5_path) + self.timer.start(1000) + + return self diff --git a/living_plot_main.py b/living_plot_main.py new file mode 100644 index 0000000..efae24b --- /dev/null +++ b/living_plot_main.py @@ -0,0 +1,16 @@ +from living_plot_class import FigureManager +import numpy as np + +import sys +from PyQt5.QtWidgets import QApplication + + +app = QApplication(sys.argv) + +h5_paths = np.empty(0) + +figure_manager = FigureManager() + +run = figure_manager.start_living_plot(h5_paths) + +sys.exit(app.exec_()) diff --git a/living_plot_starter.py b/living_plot_starter.py new file mode 100644 index 0000000..11ef57c --- /dev/null +++ b/living_plot_starter.py @@ -0,0 +1,31 @@ +import os +import time + +import lyse + + +def get_pid(): + with open("living_plot.ini", 'r') as pid_file: + pid_str = pid_file.readline() + + return pid_str + + +def call_living_plot(): + pid_str = get_pid() + if pid_str == "": + start_dire = r"living_plot_main.py" + os.popen("python %s" % start_dire) + + +def update_h5_path_file(): + h5_paths = lyse.h5_paths() + + with open('h5_file_path.ini', 'w') as h5_path_file: + h5_path_file.truncate(0) + s = '\n'.join(h5_paths) + h5_path_file.write(s) + +update_h5_path_file() +call_living_plot() + diff --git a/test.py b/test.py index 996fdac..cd99f34 100644 --- a/test.py +++ b/test.py @@ -1,2 +1,11 @@ -import pyqtgraph.examples -pyqtgraph.examples.run() +# import pyqtgraph.examples +# pyqtgraph.examples.run() + + +import h5py + +h5_path = r"C:/Users/Jianshun Gao/Desktop/2022-07-22_0037_MOT_3D_Imaging_4.h5" +data_path = r"results/absorption_imaging/absorption_imaging" +with h5py.File(h5_path, 'r') as h5_file: + result = h5_file[data_path][()] + print(result) diff --git a/test_living_plot.py b/test_living_plot.py index e8d246a..94bc46a 100644 --- a/test_living_plot.py +++ b/test_living_plot.py @@ -20,6 +20,8 @@ figure_manager = lyse.figure_manager h5_paths = lyse.h5_paths() +print(h5_paths) + if lyse.spinning_top: # If so, use the filepath of the current shot h5_path = lyse.path @@ -41,19 +43,19 @@ if not plot_name in figure_manager.MainPlotPanel.plots: Roi=False, colorbarText=False) figure_manager.MainPlotPanel.add_plot_dock(plot_name + '1', current_plotting) -plot_name = '3D-MOT Absorption Imaging - Without Atoms' -if not plot_name in figure_manager.MainPlotPanel.plots: - current_plotting = WidgetFakeColorPlot.WidgetFakeColorPlot(plot_name + '1', ('in_situ_absorption', 'background'), - data_group='MOT_3D_Camera', - Roi=False, colorbarText=False) - figure_manager.MainPlotPanel.add_plot_dock(plot_name + '1', current_plotting) - -plot_name = '3D-MOT Absorption Imaging - Dark' -if not plot_name in figure_manager.MainPlotPanel.plots: - current_plotting = WidgetFakeColorPlot.WidgetFakeColorPlot(plot_name + '1', ('in_situ_absorption', 'dark'), - data_group='MOT_3D_Camera', - Roi=False, colorbarText=False) - figure_manager.MainPlotPanel.add_plot_dock(plot_name + '1', current_plotting) +# plot_name = '3D-MOT Absorption Imaging - Without Atoms' +# if not plot_name in figure_manager.MainPlotPanel.plots: +# current_plotting = WidgetFakeColorPlot.WidgetFakeColorPlot(plot_name + '1', ('in_situ_absorption', 'background'), +# data_group='MOT_3D_Camera', +# Roi=False, colorbarText=False) +# figure_manager.MainPlotPanel.add_plot_dock(plot_name + '1', current_plotting) +# +# plot_name = '3D-MOT Absorption Imaging - Dark' +# if not plot_name in figure_manager.MainPlotPanel.plots: +# current_plotting = WidgetFakeColorPlot.WidgetFakeColorPlot(plot_name + '1', ('in_situ_absorption', 'dark'), +# data_group='MOT_3D_Camera', +# Roi=False, colorbarText=False) +# figure_manager.MainPlotPanel.add_plot_dock(plot_name + '1', current_plotting) # Add plotting for absorption imaging plot_name = '3D-MOT Absorption Imaging' @@ -74,9 +76,9 @@ if not plot_name in figure_manager.MainPlotPanel.plots: # current_plotting = Widget1DLivingPlot.Widget1DLivingPlot(plot_name, y_data_path=('absorption_imaging', 'atom_number'), y_in_results=True) # # figure_manager.MainPlotPanel.add_plot_dock(plot_name, current_plotting) -# -# figure_manager.MainPlotPanel.update_h5_paths(h5_paths) -# figure_manager.MainPlotPanel.refresh(h5_path) + +figure_manager.MainPlotPanel.update_h5_paths(h5_paths) +figure_manager.MainPlotPanel.refresh(h5_path) profile.disable() ps = pstats.Stats(profile) diff --git a/text2.py b/text2.py new file mode 100644 index 0000000..76f788b --- /dev/null +++ b/text2.py @@ -0,0 +1,14 @@ +import psutil + + +def is_process_running(process_name): + pl = psutil.pids() + for pid in pl: + if psutil.Process(pid).name() == process_name: + print(pid) + print(psutil.Process(pid).cmdline()) + # return True + + return False + +print(is_process_running('python.exe')) \ No newline at end of file