From bb505a3affa69e5ab79c97a8c68fbe17386d8ce3 Mon Sep 17 00:00:00 2001 From: Steve Zeltmann Date: Sun, 23 Jul 2023 08:33:27 -0500 Subject: [PATCH 01/16] fix for filetype parsing --- src/py4D_browser/menu_actions.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/py4D_browser/menu_actions.py b/src/py4D_browser/menu_actions.py index e068838..3989796 100644 --- a/src/py4D_browser/menu_actions.py +++ b/src/py4D_browser/menu_actions.py @@ -1,6 +1,7 @@ import py4DSTEM from PyQt5.QtWidgets import QFileDialog import h5py +import os def load_data_auto(self): @@ -21,9 +22,8 @@ def load_data_bin(self): def load_file(self, filepath, mmap=False, binning=1): print(f"Loading file {filepath}") - - from py4DSTEM.io.parsefiletype import _parse_filetype - if _parse_filetype(filepath) == "H5": + print(f"Type: {os.path.splitext(filepath)[0].lower()}") + if os.path.splitext(filepath)[-1].lower() in (".h5", ".hdf5", ".py4dstem", ".emd"): datacubes = get_4D(h5py.File(filepath, "r")) print(f"Found {len(datacubes)} 4D datasets inside the HDF5 file...") if len(datacubes) >= 1: @@ -50,7 +50,7 @@ def show_file_dialog(self): self, "Open 4D-STEM Data", "", - "4D-STEM Data (*.dm3 *.dm4 *.raw *.mib *.gtg);;Any file (*)", + "4D-STEM Data (*.dm3 *.dm4 *.raw *.mib *.gtg *.h5 *.hdf5 *.emd *.py4dstem);;Any file (*)", ) if filename is not None and len(filename[0]) > 0: return filename[0] From cbb7c0eaa26ec82f13c34eff53ca85fc62a6c61e Mon Sep 17 00:00:00 2001 From: Steve Zeltmann Date: Sun, 23 Jul 2023 08:38:11 -0500 Subject: [PATCH 02/16] fix filetype parsing --- src/py4D_browser/menu_actions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py4D_browser/menu_actions.py b/src/py4D_browser/menu_actions.py index 3989796..e55a668 100644 --- a/src/py4D_browser/menu_actions.py +++ b/src/py4D_browser/menu_actions.py @@ -22,7 +22,7 @@ def load_data_bin(self): def load_file(self, filepath, mmap=False, binning=1): print(f"Loading file {filepath}") - print(f"Type: {os.path.splitext(filepath)[0].lower()}") + print(f"Type: {os.path.splitext(filepath)[-1].lower()}") if os.path.splitext(filepath)[-1].lower() in (".h5", ".hdf5", ".py4dstem", ".emd"): datacubes = get_4D(h5py.File(filepath, "r")) print(f"Found {len(datacubes)} 4D datasets inside the HDF5 file...") From b236c2dfdea3440762b62cb1b53ea2608a63339e Mon Sep 17 00:00:00 2001 From: Steve Zeltmann Date: Sun, 23 Jul 2023 08:38:26 -0500 Subject: [PATCH 03/16] switch to new virtualimage function --- src/py4D_browser/update_views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/py4D_browser/update_views.py b/src/py4D_browser/update_views.py index 8ebb3dd..d40508d 100644 --- a/src/py4D_browser/update_views.py +++ b/src/py4D_browser/update_views.py @@ -64,7 +64,7 @@ def update_real_space_view(self, reset=False): self.diffraction_space_view_text.setText(f"[({x0},{y0}),{R}]") - mask = py4DSTEM.process.virtualimage.make_detector( + mask = py4DSTEM.datacube.virtualimage.DataCubeVirtualImager.make_detector( (self.datacube.Q_Nx, self.datacube.Q_Ny), "circle", ((x0, y0), R) ) elif detector_shape == "Annulus": @@ -85,7 +85,7 @@ def update_real_space_view(self, reset=False): self.diffraction_space_view_text.setText(f"[({x0},{y0}),({R_inner},{R_outer})]") - mask = py4DSTEM.process.virtualimage.make_detector( + mask = py4DSTEM.datacube.virtualimage.DataCubeVirtualImager.make_detector( (self.datacube.Q_Nx, self.datacube.Q_Ny), "annulus", ((x0, y0), (R_inner, R_outer)), From 3bdb58f13ca02416f1d684109a91c6aeac147500 Mon Sep 17 00:00:00 2001 From: Steve Zeltmann Date: Sun, 23 Jul 2023 08:38:51 -0500 Subject: [PATCH 04/16] update py4dstem version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index eb52c87..c3e34e3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ classifiers = [ "Operating System :: OS Independent", ] dependencies = [ - "py4dstem >= 0.14.0", + "py4dstem >= 0.14.3", "numpy >= 1.19", "matplotlib >= 3.2.2", "PyQt5 >= 5.10", From f7c385c5befc71bd47012bb5deb6b3bdd6bb4ebf Mon Sep 17 00:00:00 2001 From: Steve Zeltmann Date: Sun, 23 Jul 2023 08:40:25 -0500 Subject: [PATCH 05/16] update version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c3e34e3..7573393 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "py4D_browser" -version = "0.99" +version = "0.999" authors = [ { name="Steven Zeltmann", email="steven.zeltmann@berkeley.edu" }, ] From 0a0738753e06dbf28176cf08430472ec3de12767 Mon Sep 17 00:00:00 2001 From: Steve Zeltmann Date: Sun, 23 Jul 2023 08:41:28 -0500 Subject: [PATCH 06/16] update readme with conda install --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 603c979..8210e73 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,12 @@ This repository hosts the `pyqt` based graphical 4D--STEM data browser that was originally part of **py4DSTEM** until version 0.13.11. ## Installation -The GUI is available on PyPI: `pip install py4D-browser` -`conda` installation will be available shortly. +The GUI is available on PyPI and conda-forge: + +`pip install py4D-browser` + +`conda install -c conda-forge py4d-browser` + ## Usage Run `py4DGUI` in your terminal to open the GUI. Then just drag and drop a 4D-STEM dataset into the window! From 90d1fc4ed77befd9866a7f6aa58040f4caf56a2e Mon Sep 17 00:00:00 2001 From: Steven Zeltmann Date: Tue, 10 Oct 2023 10:02:06 -0400 Subject: [PATCH 07/16] add vimg FFT --- src/py4D_browser/main_window.py | 24 ++++++++++++++++++++++-- src/py4D_browser/update_views.py | 7 +++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/py4D_browser/main_window.py b/src/py4D_browser/main_window.py index 79a5918..a735575 100644 --- a/src/py4D_browser/main_window.py +++ b/src/py4D_browser/main_window.py @@ -1,4 +1,5 @@ -from PyQt5.QtCore import Qt +from PyQt5 import QtCore +from PyQt5.QtCore import Qt, right from PyQt5.QtWidgets import ( QApplication, QLabel, @@ -18,6 +19,7 @@ QButtonGroup, QDesktopWidget, QMessageBox, + QSplitter, QActionGroup, ) from PyQt5 import QtGui @@ -300,9 +302,27 @@ def setup_views(self): self.diffraction_space_widget.dropEvent = self.dropEvent self.real_space_widget.dropEvent = self.dropEvent + # Set up the FFT window. + self.fft_widget = pg.ImageView() + self.fft_widget.setImage(np.zeros((512, 512))) + + # Name and return + self.fft_widget.setWindowTitle("FFT of Virtual Image") + + self.fft_widget.setAcceptDrops(True) + self.fft_widget.dragEnterEvent = self.dragEnterEvent + self.fft_widget.dropEvent = self.dropEvent + layout = QHBoxLayout() layout.addWidget(self.diffraction_space_widget, 1) - layout.addWidget(self.real_space_widget, 1) + + # add a resizeable layout for the vimg and FFT + rightside = QSplitter() + rightside.addWidget(self.real_space_widget) + rightside.addWidget(self.fft_widget) + rightside.setOrientation(QtCore.Qt.Vertical) + layout.addWidget(rightside, 1) + widget = QWidget() widget.setLayout(layout) self.setCentralWidget(widget) diff --git a/src/py4D_browser/update_views.py b/src/py4D_browser/update_views.py index d40508d..f0bbe36 100644 --- a/src/py4D_browser/update_views.py +++ b/src/py4D_browser/update_views.py @@ -155,6 +155,13 @@ def update_real_space_view(self, reset=False): raise ValueError("Mode not recognized") self.real_space_widget.setImage(new_view.T, autoLevels=True) + # Update FFT view + fft = np.abs(np.fft.fftshift(np.fft.fft2(new_view))) ** 0.5 + levels = (np.min(fft), np.percentile(fft, 99.9)) + self.fft_widget.setImage( + fft.T, autoLevels=False, levels=levels, autoRange=reset + ) + def update_diffraction_space_view(self, reset=False): scaling_mode = self.diff_scaling_group.checkedAction().text().replace("&", "") From 43a52fffb2aa8fd38325233d943801bf3abe101f Mon Sep 17 00:00:00 2001 From: Steven Zeltmann Date: Wed, 11 Oct 2023 10:44:25 -0400 Subject: [PATCH 08/16] pyright venv in prproject.toml --- pyproject.toml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7573393..f2767e7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,4 +28,7 @@ py4DGUI = "py4D_browser.runGUI:launch" [project.urls] "Homepage" = "https://github.com/py4dstem/py4D-browser" -"Bug Tracker" = "https://github.com/py4dstem/py4D-browser/issues" \ No newline at end of file +"Bug Tracker" = "https://github.com/py4dstem/py4D-browser/issues" + +[tool.pyright] +venv = "py4dstem" \ No newline at end of file From 318e09d74500060f43d7b81d4e81bd726b0f6b3b Mon Sep 17 00:00:00 2001 From: Steven Zeltmann Date: Wed, 11 Oct 2023 11:06:18 -0400 Subject: [PATCH 09/16] aesthetic changes to FFT --- src/py4D_browser/main_window.py | 15 +++++++++++---- src/py4D_browser/update_views.py | 27 +++++++++++++++------------ src/py4D_browser/utils.py | 3 ++- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/py4D_browser/main_window.py b/src/py4D_browser/main_window.py index a735575..5d15166 100644 --- a/src/py4D_browser/main_window.py +++ b/src/py4D_browser/main_window.py @@ -83,6 +83,10 @@ def __init__(self, argv): self.show() + # If a file was passed on the command line, open it + if len(argv) > 1: + self.load_file(argv[1]) + def setup_menus(self): self.menu_bar = self.menuBar() @@ -231,7 +235,7 @@ def setup_menus(self): detector_point_action = QAction("&Point", self) detector_point_action.setCheckable(True) - detector_point_action.setChecked(True) # Default + detector_point_action.setChecked(True) # Default detector_point_action.triggered.connect(self.update_diffraction_detector) detector_shape_group.addAction(detector_point_action) self.detector_shape_menu.addAction(detector_point_action) @@ -265,7 +269,9 @@ def setup_views(self): self.diffraction_space_widget.addItem(self.diffraction_space_view_text) # Create virtual detector ROI selector - self.virtual_detector_point = pg_point_roi(self.diffraction_space_widget.getView()) + self.virtual_detector_point = pg_point_roi( + self.diffraction_space_widget.getView() + ) self.virtual_detector_point.sigRegionChanged.connect( self.update_real_space_view ) @@ -308,6 +314,7 @@ def setup_views(self): # Name and return self.fft_widget.setWindowTitle("FFT of Virtual Image") + self.fft_widget.addItem(pg.TextItem("FFT", (200, 200, 200), None, (0, 1))) self.fft_widget.setAcceptDrops(True) self.fft_widget.dragEnterEvent = self.dragEnterEvent @@ -321,8 +328,9 @@ def setup_views(self): rightside.addWidget(self.real_space_widget) rightside.addWidget(self.fft_widget) rightside.setOrientation(QtCore.Qt.Vertical) + rightside.setStretchFactor(0, 2) layout.addWidget(rightside, 1) - + widget = QWidget() widget.setLayout(layout) self.setCentralWidget(widget) @@ -339,4 +347,3 @@ def dropEvent(self, event): if len(files) == 1: print(f"Reieving dropped file: {files[0]}") self.load_file(files[0]) - diff --git a/src/py4D_browser/update_views.py b/src/py4D_browser/update_views.py index f0bbe36..2d697ac 100644 --- a/src/py4D_browser/update_views.py +++ b/src/py4D_browser/update_views.py @@ -10,7 +10,12 @@ def update_real_space_view(self, reset=False): assert scaling_mode in ["Linear", "Log", "Square Root"], scaling_mode detector_shape = self.detector_shape_group.checkedAction().text().replace("&", "") - assert detector_shape in ["Point", "Rectangular", "Circle", "Annulus"], detector_shape + assert detector_shape in [ + "Point", + "Rectangular", + "Circle", + "Annulus", + ], detector_shape detector_mode = self.detector_mode_group.checkedAction().text().replace("&", "") assert detector_mode in [ @@ -99,7 +104,7 @@ def update_real_space_view(self, reset=False): # Normalize coordinates xc = np.clip(xc, 0, self.datacube.Q_Nx - 1) yc = np.clip(yc, 0, self.datacube.Q_Ny - 1) - vimg = self.datacube.data[: ,: , xc, yc] + vimg = self.datacube.data[:, :, xc, yc] self.diffraction_space_view_text.setText(f"[{xc},{yc}]") @@ -158,9 +163,7 @@ def update_real_space_view(self, reset=False): # Update FFT view fft = np.abs(np.fft.fftshift(np.fft.fft2(new_view))) ** 0.5 levels = (np.min(fft), np.percentile(fft, 99.9)) - self.fft_widget.setImage( - fft.T, autoLevels=False, levels=levels, autoRange=reset - ) + self.fft_widget.setImage(fft.T, autoLevels=False, levels=levels, autoRange=reset) def update_diffraction_space_view(self, reset=False): @@ -211,7 +214,9 @@ def update_diffraction_detector(self): # Remove existing detector if hasattr(self, "virtual_detector_point"): - self.diffraction_space_widget.view.scene().removeItem(self.virtual_detector_point) + self.diffraction_space_widget.view.scene().removeItem( + self.virtual_detector_point + ) if hasattr(self, "virtual_detector_roi"): self.diffraction_space_widget.view.scene().removeItem(self.virtual_detector_roi) if hasattr(self, "virtual_detector_roi_inner"): @@ -225,7 +230,9 @@ def update_diffraction_detector(self): # Rectangular detector if detector_shape == "Point": - self.virtual_detector_point = pg_point_roi(self.diffraction_space_widget.getView()) + self.virtual_detector_point = pg_point_roi( + self.diffraction_space_widget.getView() + ) self.virtual_detector_point.sigRegionChanged.connect( self.update_real_space_view ) @@ -286,11 +293,7 @@ def update_diffraction_detector(self): ) else: - raise ValueError( - "Unknown detector shape! Got: {}".format( - detector_shape - ) - ) + raise ValueError("Unknown detector shape! Got: {}".format(detector_shape)) self.update_real_space_view() diff --git a/src/py4D_browser/utils.py b/src/py4D_browser/utils.py index 50bb5b3..8273033 100644 --- a/src/py4D_browser/utils.py +++ b/src/py4D_browser/utils.py @@ -1,5 +1,6 @@ import pyqtgraph as pg + def pg_point_roi(view_box): """ Point selection. Based in pyqtgraph, and returns a pyqtgraph CircleROI object. @@ -11,4 +12,4 @@ def pg_point_roi(view_box): h.update() view_box.addItem(circ_roi) circ_roi.removeHandle(0) - return circ_roi \ No newline at end of file + return circ_roi From c0a4ff947388834cc23e2542d4645bf5b7864b06 Mon Sep 17 00:00:00 2001 From: Steven Zeltmann Date: Wed, 11 Oct 2023 11:08:40 -0400 Subject: [PATCH 10/16] add emdfile dependency --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index f2767e7..7e88e45 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,7 @@ classifiers = [ ] dependencies = [ "py4dstem >= 0.14.3", + "emdfile >= 0.0.11", "numpy >= 1.19", "matplotlib >= 3.2.2", "PyQt5 >= 5.10", From 57a933fea16ba6ce464485bfc80887b50246c92a Mon Sep 17 00:00:00 2001 From: Steven Zeltmann Date: Mon, 4 Dec 2023 15:14:47 -0500 Subject: [PATCH 11/16] use an internal function to generate masks, eliminating a py4DSTEM call --- src/py4D_browser/update_views.py | 45 ++++++++++++++++---------------- src/py4D_browser/utils.py | 37 +++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 23 deletions(-) diff --git a/src/py4D_browser/update_views.py b/src/py4D_browser/update_views.py index 2d697ac..ae094f4 100644 --- a/src/py4D_browser/update_views.py +++ b/src/py4D_browser/update_views.py @@ -2,7 +2,7 @@ import numpy as np import py4DSTEM -from py4D_browser.utils import pg_point_roi +from py4D_browser.utils import pg_point_roi, make_detector def update_real_space_view(self, reset=False): @@ -60,37 +60,33 @@ def update_real_space_view(self, reset=False): mask[slice_x, slice_y] = True elif detector_shape == "Circle": - (slice_x, slice_y), _ = self.virtual_detector_roi.getArraySlice( - self.datacube.data[0, 0, :, :], self.diffraction_space_widget.getImageItem() - ) - x0 = (slice_x.start + slice_x.stop) / 2.0 - y0 = (slice_y.start + slice_y.stop) / 2.0 - R = (slice_y.stop - slice_y.start) / 2.0 + R = self.virtual_detector_roi.size()[0] / 2.0 - self.diffraction_space_view_text.setText(f"[({x0},{y0}),{R}]") + x0 = self.virtual_detector_roi.pos()[0] + R + y0 = self.virtual_detector_roi.pos()[1] + R - mask = py4DSTEM.datacube.virtualimage.DataCubeVirtualImager.make_detector( + self.diffraction_space_view_text.setText(f"[({x0:.0f},{y0:.0f}),{R:.0f}]") + + mask = make_detector( (self.datacube.Q_Nx, self.datacube.Q_Ny), "circle", ((x0, y0), R) ) elif detector_shape == "Annulus": - (slice_x, slice_y), _ = self.virtual_detector_roi_outer.getArraySlice( - self.datacube.data[0, 0, :, :], self.diffraction_space_widget.getImageItem() - ) - x0 = (slice_x.start + slice_x.stop) / 2.0 - y0 = (slice_y.start + slice_y.stop) / 2.0 - R_outer = (slice_y.stop - slice_y.start) / 2.0 + inner_pos = self.virtual_detector_roi_inner.pos() + inner_size = self.virtual_detector_roi_inner.size() + R_inner = inner_size[0] / 2.0 + x0 = inner_pos[0] + R_inner + y0 = inner_pos[1] + R_inner + + outer_size = self.virtual_detector_roi_outer.size() + R_outer = outer_size[0] / 2.0 - (slice_ix, slice_iy), _ = self.virtual_detector_roi_inner.getArraySlice( - self.datacube.data[0, 0, :, :], self.diffraction_space_widget.getImageItem() - ) - R_inner = (slice_iy.stop - slice_iy.start) / 2.0 - if R_inner == R_outer: + if R_inner <= R_outer: R_inner -= 1 - self.diffraction_space_view_text.setText(f"[({x0},{y0}),({R_inner},{R_outer})]") + self.diffraction_space_view_text.setText(f"[({x0:.0f},{y0:.0f}),({R_inner:.0f},{R_outer:.0f})]") - mask = py4DSTEM.datacube.virtualimage.DataCubeVirtualImager.make_detector( + mask = make_detector( (self.datacube.Q_Nx, self.datacube.Q_Ny), "annulus", ((x0, y0), (R_inner, R_outer)), @@ -112,6 +108,11 @@ def update_real_space_view(self, reset=False): raise ValueError("Detector shape not recognized") if mask is not None: + # For debugging masks: + # self.diffraction_space_widget.setImage( + # mask.T, autoLevels=True, autoRange=True + # ) + mask = mask.astype(np.float32) vimg = np.zeros((self.datacube.R_Nx, self.datacube.R_Ny)) iterator = py4DSTEM.tqdmnd(self.datacube.R_Nx, self.datacube.R_Ny, disable=True) diff --git a/src/py4D_browser/utils.py b/src/py4D_browser/utils.py index 8273033..872e3ab 100644 --- a/src/py4D_browser/utils.py +++ b/src/py4D_browser/utils.py @@ -1,5 +1,5 @@ import pyqtgraph as pg - +import numpy as np def pg_point_roi(view_box): """ @@ -13,3 +13,38 @@ def pg_point_roi(view_box): view_box.addItem(circ_roi) circ_roi.removeHandle(0) return circ_roi + +def make_detector(shape:tuple, mode:str, geometry) -> np.ndarray: + match mode, geometry: + case ["point", (qx,qy)]: + mask = np.zeros(shape, dtype=np.bool_) + mask[qx,qy] = True + case ["point", geom]: + raise ValueError(f"Point detector shape must be specified as (qx,qy), not {geom}") + + case [("circle" | "circular"), ((qx,qy),r)]: + ix, iy = np.indices(shape) + mask = np.hypot(ix-qx, iy-qy) <= r + case [("circle" | "circular"), geom]: + raise ValueError(f"Circular detector shape must be specified as ((qx,qy),r), not {geom}") + + case [("annulus" | "annular"), ((qx,qy),(ri,ro))]: + ix, iy = np.indices(shape) + ir = np.hypot(ix-qx,iy-qy) + mask = np.logical_and( ir >= ri, ir <= ro) + case [("annulus" | "annular"), geom]: + raise ValueError(f"Annular detector shape must be specified as ((qx,qy),(ri,ro)), not {geom}") + + case [("rectangle" | "square" | "rectangular"), (xmin,xmax,ymin,ymax)]: + mask = np.zeros(shape, dtype=np.bool_) + mask[xmin:xmax, ymin:ymax] = True + case [("rectangle" | "square" | "rectangular"), geom]: + raise ValueError(f"Rectangular detector shape must be specified as (xmin,xmax,ymin,ymax), not {geom}") + + case ["mask", mask_arr]: + mask = mask_arr + + case unknown: + raise ValueError(f"mode and geometry not understood: {unknown}") + + return mask \ No newline at end of file From 48e1c5e7ed6f224f45baa4949508154b2722d0fb Mon Sep 17 00:00:00 2001 From: Steven Zeltmann Date: Mon, 4 Dec 2023 16:51:33 -0500 Subject: [PATCH 12/16] format with black --- src/py4D_browser/update_views.py | 5 ++-- src/py4D_browser/utils.py | 46 +++++++++++++++++++------------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/py4D_browser/update_views.py b/src/py4D_browser/update_views.py index ae094f4..c4dba23 100644 --- a/src/py4D_browser/update_views.py +++ b/src/py4D_browser/update_views.py @@ -80,11 +80,12 @@ def update_real_space_view(self, reset=False): outer_size = self.virtual_detector_roi_outer.size() R_outer = outer_size[0] / 2.0 - if R_inner <= R_outer: R_inner -= 1 - self.diffraction_space_view_text.setText(f"[({x0:.0f},{y0:.0f}),({R_inner:.0f},{R_outer:.0f})]") + self.diffraction_space_view_text.setText( + f"[({x0:.0f},{y0:.0f}),({R_inner:.0f},{R_outer:.0f})]" + ) mask = make_detector( (self.datacube.Q_Nx, self.datacube.Q_Ny), diff --git a/src/py4D_browser/utils.py b/src/py4D_browser/utils.py index 872e3ab..ed95364 100644 --- a/src/py4D_browser/utils.py +++ b/src/py4D_browser/utils.py @@ -1,6 +1,7 @@ import pyqtgraph as pg import numpy as np + def pg_point_roi(view_box): """ Point selection. Based in pyqtgraph, and returns a pyqtgraph CircleROI object. @@ -14,37 +15,46 @@ def pg_point_roi(view_box): circ_roi.removeHandle(0) return circ_roi -def make_detector(shape:tuple, mode:str, geometry) -> np.ndarray: + +def make_detector(shape: tuple, mode: str, geometry) -> np.ndarray: match mode, geometry: - case ["point", (qx,qy)]: + case ["point", (qx, qy)]: mask = np.zeros(shape, dtype=np.bool_) - mask[qx,qy] = True + mask[qx, qy] = True case ["point", geom]: - raise ValueError(f"Point detector shape must be specified as (qx,qy), not {geom}") - - case [("circle" | "circular"), ((qx,qy),r)]: + raise ValueError( + f"Point detector shape must be specified as (qx,qy), not {geom}" + ) + + case [("circle" | "circular"), ((qx, qy), r)]: ix, iy = np.indices(shape) - mask = np.hypot(ix-qx, iy-qy) <= r + mask = np.hypot(ix - qx, iy - qy) <= r case [("circle" | "circular"), geom]: - raise ValueError(f"Circular detector shape must be specified as ((qx,qy),r), not {geom}") + raise ValueError( + f"Circular detector shape must be specified as ((qx,qy),r), not {geom}" + ) - case [("annulus" | "annular"), ((qx,qy),(ri,ro))]: + case [("annulus" | "annular"), ((qx, qy), (ri, ro))]: ix, iy = np.indices(shape) - ir = np.hypot(ix-qx,iy-qy) - mask = np.logical_and( ir >= ri, ir <= ro) + ir = np.hypot(ix - qx, iy - qy) + mask = np.logical_and(ir >= ri, ir <= ro) case [("annulus" | "annular"), geom]: - raise ValueError(f"Annular detector shape must be specified as ((qx,qy),(ri,ro)), not {geom}") - - case [("rectangle" | "square" | "rectangular"), (xmin,xmax,ymin,ymax)]: + raise ValueError( + f"Annular detector shape must be specified as ((qx,qy),(ri,ro)), not {geom}" + ) + + case [("rectangle" | "square" | "rectangular"), (xmin, xmax, ymin, ymax)]: mask = np.zeros(shape, dtype=np.bool_) mask[xmin:xmax, ymin:ymax] = True case [("rectangle" | "square" | "rectangular"), geom]: - raise ValueError(f"Rectangular detector shape must be specified as (xmin,xmax,ymin,ymax), not {geom}") - + raise ValueError( + f"Rectangular detector shape must be specified as (xmin,xmax,ymin,ymax), not {geom}" + ) + case ["mask", mask_arr]: mask = mask_arr - + case unknown: raise ValueError(f"mode and geometry not understood: {unknown}") - return mask \ No newline at end of file + return mask From 89233dd76cfe18ceac802bfb85a82fadd1663a5b Mon Sep 17 00:00:00 2001 From: Steven Zeltmann Date: Mon, 4 Dec 2023 16:52:57 -0500 Subject: [PATCH 13/16] black CI --- .github/black.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/black.yml diff --git a/.github/black.yml b/.github/black.yml new file mode 100644 index 0000000..09b2a0f --- /dev/null +++ b/.github/black.yml @@ -0,0 +1,14 @@ +name: Check code style + +on: + push: + branches: [ "dev" ] + pull_request: + branches: [ "dev" ] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: psf/black@stable \ No newline at end of file From 90065b073441b561c42b573151d1c4e2c53c4136 Mon Sep 17 00:00:00 2001 From: Steven Zeltmann Date: Mon, 4 Dec 2023 16:56:08 -0500 Subject: [PATCH 14/16] remove unused imports --- src/py4D_browser/main_window.py | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/py4D_browser/main_window.py b/src/py4D_browser/main_window.py index 5d15166..3717388 100644 --- a/src/py4D_browser/main_window.py +++ b/src/py4D_browser/main_window.py @@ -1,28 +1,14 @@ -from PyQt5 import QtCore -from PyQt5.QtCore import Qt, right +from PyQt5 import QtCore, QtGui from PyQt5.QtWidgets import ( QApplication, - QLabel, QMainWindow, QWidget, QMenu, QAction, - QFileDialog, - QVBoxLayout, QHBoxLayout, - QFrame, - QPushButton, - QScrollArea, - QCheckBox, - QLineEdit, - QRadioButton, - QButtonGroup, - QDesktopWidget, - QMessageBox, QSplitter, QActionGroup, ) -from PyQt5 import QtGui import pyqtgraph as pg import numpy as np From d75bc97109b7cb6f0e7a4055c541bd9af1064f63 Mon Sep 17 00:00:00 2001 From: Steven Zeltmann Date: Mon, 4 Dec 2023 17:00:43 -0500 Subject: [PATCH 15/16] move black CI to correct place --- .github/{ => workflows}/black.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/{ => workflows}/black.yml (100%) diff --git a/.github/black.yml b/.github/workflows/black.yml similarity index 100% rename from .github/black.yml rename to .github/workflows/black.yml From 9afcd01ebd1e3c696fac7e7c7771e27e99f6dc07 Mon Sep 17 00:00:00 2001 From: Steven Zeltmann Date: Mon, 4 Dec 2023 17:03:27 -0500 Subject: [PATCH 16/16] bump version number --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7e88e45..a9a409e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "py4D_browser" -version = "0.999" +version = "0.9999" authors = [ { name="Steven Zeltmann", email="steven.zeltmann@berkeley.edu" }, ]