diff --git a/.github/workflows/conda_build_and_publish.yml b/.github/workflows/conda_build_and_publish.yml index 9985fbe5..4204a9ce 100644 --- a/.github/workflows/conda_build_and_publish.yml +++ b/.github/workflows/conda_build_and_publish.yml @@ -25,7 +25,7 @@ jobs: channels: conda-forge, ccpi conda-remove-defaults: "true" - - run: conda install conda-build conda-verify + - run: conda install conda-build - name: conda build run: > diff --git a/.github/workflows/docker_build_test_publish.yml b/.github/workflows/docker_build_test_publish.yml index 97e25bc1..6cacfb7b 100644 --- a/.github/workflows/docker_build_test_publish.yml +++ b/.github/workflows/docker_build_test_publish.yml @@ -33,5 +33,5 @@ jobs: - name: Run docker container with tests shell: bash -l {0} run: | - docker run --rm --entrypoint /bin/bash -v /home/runner/work/CILViewer/CILViewer:/root/source_code cil-viewer -c "source ./mambaforge/etc/profile.d/conda.sh && conda activate cilviewer_webapp && conda install cil-data pytest pyside2 eqt>=1.0.0 -c ccpi && python -m pytest /root/source_code/Wrappers/Python/test -k 'not test_version and not test_cli_resample and not test_CILViewerBase and not test_CILViewer3D and not test_viewer_main_windows and not test_ui_dialogs and not test_3dtoolbar'" + docker run --rm --entrypoint /bin/bash -v /home/runner/work/CILViewer/CILViewer:/root/source_code cil-viewer -c "source ./mambaforge/etc/profile.d/conda.sh && conda activate cilviewer_webapp && conda install cil-data pytest pyside6 eqt>=2.0.0 -c ccpi && python -m pytest /root/source_code/Wrappers/Python/test -k 'not test_version and not test_cli_resample and not test_CILViewerBase and not test_CILViewer3D and not test_viewer_main_windows and not test_ui_dialogs and not test_3dtoolbar'" # TODO: publish to come later diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d9b0d3b..09eca4bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,10 @@ # Changelog -## v25.1.0 +## v26.0.0 New Functionality: - Added toolbar to control the slice and volume render in QCILViewerWidget (#458) - added methods to access the state of the viewer3D (#479) - + - added buttons to close preview dialog on macos Enhancements: - Update recipe to require eqt Version 2.0.0 #458 - Add a toolbar and settings menus to the 3D viewer #458 @@ -13,6 +13,12 @@ Enhancements: Dependencies: - removed python pinning (#482) - removed importlib_metadata, required for python <3.8 (#482) + - optional dependency on matplotlib >= 3.9 +Bugfixes: + - removes hang on macos with Qt6 (PySide6) + - bugfix for matplotlib >= 3.9 + - bugfix unittests for numpy > 2.2 + - removed conda-verify package in GHA CI: - Created new action for conda build and publish - no longer uses conda-package-publish-action (#486) diff --git a/Wrappers/Python/ccpi/viewer/QCILRenderWindowInteractor.py b/Wrappers/Python/ccpi/viewer/QCILRenderWindowInteractor.py index 4832ba42..4a9b8623 100644 --- a/Wrappers/Python/ccpi/viewer/QCILRenderWindowInteractor.py +++ b/Wrappers/Python/ccpi/viewer/QCILRenderWindowInteractor.py @@ -1,6 +1,7 @@ import vtk from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor from qtpy.QtCore import Qt, QEvent +import platform class QCILRenderWindowInteractor(QVTKRenderWindowInteractor): @@ -22,6 +23,10 @@ def __init__(self, parent=None, **kw): self.__wheelDelta = self._QVTKRenderWindowInteractor__wheelDelta #print ("__saveModifiers should be defined", self.__saveModifiers) + # WA_PaintOnScreen makes the first paintEvent hang with Qt6 on macOS + if platform.system() == 'Darwin' and hasattr(Qt.WidgetAttribute, 'WA_PaintOnScreen'): + self.setAttribute(Qt.WidgetAttribute.WA_PaintOnScreen, False) + def _GetAlt(self, ev): '''Get ALT key modifier''' ctrl = shift = alt = False diff --git a/Wrappers/Python/ccpi/viewer/ui/dialogs.py b/Wrappers/Python/ccpi/viewer/ui/dialogs.py index c5014577..d1cad9e6 100644 --- a/Wrappers/Python/ccpi/viewer/ui/dialogs.py +++ b/Wrappers/Python/ccpi/viewer/ui/dialogs.py @@ -263,6 +263,7 @@ def preview(self): diag = QtWidgets.QDialog(parent=self) diag.setModal(True) + if dimensionality == 3: if pars['is_fortran'] is True: slicing = 'image' @@ -273,6 +274,10 @@ def preview(self): diag.setWindowTitle(f'Preview Image') diag.setWindowFlag(QtCore.Qt.WindowContextHelpButtonHint, False) diag.setWindowFlag(QtCore.Qt.WindowMaximizeButtonHint) + diag.setWindowFlag(QtCore.Qt.WindowCloseButtonHint, True) + + buttonBox = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok) + buttonBox.button(QtWidgets.QDialogButtonBox.Ok).clicked.connect(diag.close) # add a layout verticalLayout = QtWidgets.QVBoxLayout(diag) verticalLayout.setContentsMargins(10, 10, 10, 10) @@ -283,6 +288,7 @@ def preview(self): # add it to the layout of the dialog verticalLayout.addWidget(sc) + verticalLayout.addWidget(buttonBox) # add the layout to the dialog diag.setLayout(verticalLayout) diff --git a/Wrappers/Python/ccpi/viewer/utils/colormaps.py b/Wrappers/Python/ccpi/viewer/utils/colormaps.py index 7b8c8944..9f2046c7 100644 --- a/Wrappers/Python/ccpi/viewer/utils/colormaps.py +++ b/Wrappers/Python/ccpi/viewer/utils/colormaps.py @@ -438,11 +438,11 @@ def get_color_map(cmap): if not cmap in _color_map_dict.keys(): try: - from matplotlib import cm + import matplotlib colors = [] for x in range(0, 255): - color = cm.get_cmap(cmap)(x) + color = matplotlib.colormaps[cmap](x) colors.append([color[0], color[1], color[2]]) except ImportError: print("To use colormaps other than: ", diff --git a/Wrappers/Python/conda-recipe/environment.yml b/Wrappers/Python/conda-recipe/environment.yml index a615d129..c6c642dd 100644 --- a/Wrappers/Python/conda-recipe/environment.yml +++ b/Wrappers/Python/conda-recipe/environment.yml @@ -6,7 +6,7 @@ dependencies: - python - numpy - vtk - - pyside2 + - pyside6 - eqt>=2.0.0 - importlib_metadata # [py<38] - h5py diff --git a/Wrappers/Python/conda-recipe/meta.yaml b/Wrappers/Python/conda-recipe/meta.yaml index aa8e9684..9b2c7016 100644 --- a/Wrappers/Python/conda-recipe/meta.yaml +++ b/Wrappers/Python/conda-recipe/meta.yaml @@ -20,7 +20,7 @@ test: - ccpi::cil-data=22.0.0 - pillow - pytest - - pyside2 + - pyside6 - eqt>=2.0.0 source_files: - ./Wrappers/Python/test diff --git a/Wrappers/Python/test/test_cropped_readers.py b/Wrappers/Python/test/test_cropped_readers.py index 135de68a..b7816b89 100644 --- a/Wrappers/Python/test/test_cropped_readers.py +++ b/Wrappers/Python/test/test_cropped_readers.py @@ -16,7 +16,7 @@ def setUp(self): bits = 8 self.input_3D_array = np.random.randint(10, size=shape, dtype=eval(f"np.uint{bits}")) self.input_3D_array = np.reshape(np.arange(self.input_3D_array.size), - newshape=shape).astype(dtype=eval(f"np.uint{bits}")) + shape).astype(dtype=eval(f"np.uint{bits}")) self.raw_type_code = str(self.input_3D_array.dtype) bytes_3D_array = bytes(self.input_3D_array) self.raw_filename_3D = 'test_3D_data.raw' diff --git a/Wrappers/Python/test/test_resample_readers.py b/Wrappers/Python/test/test_resample_readers.py index 52c79d3b..da833419 100644 --- a/Wrappers/Python/test/test_resample_readers.py +++ b/Wrappers/Python/test/test_resample_readers.py @@ -21,7 +21,7 @@ def setUp(self): self.size_greater_than_input_size = 10000 self.input_3D_array = np.random.randint(10, size=shape, dtype=eval(f"np.uint{bits}")) self.input_3D_array = np.reshape(np.arange(self.input_3D_array.size), - newshape=shape).astype(dtype=eval(f"np.uint{bits}")) + shape).astype(dtype=eval(f"np.uint{bits}")) bytes_3D_array = bytes(self.input_3D_array) self.raw_filename_3D = 'test_3D_data.raw' with open(self.raw_filename_3D, 'wb') as f: