diff --git a/.github/workflows/build_installer.yml b/.github/workflows/build_installer.yml index 9df576e3..cd3192f6 100644 --- a/.github/workflows/build_installer.yml +++ b/.github/workflows/build_installer.yml @@ -48,14 +48,13 @@ jobs: else ./build_installer.sh --remote --tag $GITHUB_REF_NAME fi - ./build_installer.sh --remote - name: Upload installer uses: actions/upload-artifact@v4 with: name: linux installer path: installer/linux/*.run MacOS-installer: - runs-on: macos-13 + runs-on: macos-latest steps: - uses: actions/checkout@v4 - uses: conda-incubator/setup-miniconda@v3 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index dc1bd130..e672a978 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -15,7 +15,7 @@ jobs: strategy: fail-fast: false matrix: - platform: [windows-latest, ubuntu-latest, macos-13] + platform: [windows-latest, ubuntu-latest, macos-latest] runs-on: ${{ matrix.platform }} steps: @@ -49,7 +49,6 @@ jobs: run: | conda init bash conda activate sscanss - conda install -y -c conda-forge numpy==1.23.5 python make.py --build-all - name: Upload coverage files uses: actions/upload-artifact@v4 diff --git a/.github/workflows/publish_docs.yml b/.github/workflows/publish_docs.yml index e9c598c1..f71ab233 100644 --- a/.github/workflows/publish_docs.yml +++ b/.github/workflows/publish_docs.yml @@ -19,10 +19,10 @@ jobs: with: ref: gh-pages path: docs/_web - - name: Set up Python 3.10 + - name: Set up Python 3.12 uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.12' - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/README.md b/README.md index ee323311..0dcfefe2 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Installation ------------ Installers are available on the [release](https://github.com/ISISNeutronMuon/SScanSS-2/releases) page. It should be noted that while the code is Python 3 compatible, a single version will be tested for each release to ensure a consistent experience for all users. -The supported version for the next release is Python 3.10. +The supported version for the next release is Python 3.12. Citing SScanSS 2 ---------------- diff --git a/environment.yaml b/environment.yaml index fc2b9b32..75afc4a6 100644 --- a/environment.yaml +++ b/environment.yaml @@ -2,7 +2,7 @@ name: sscanss channels: - defaults dependencies: - - python=3.10 + - python=3.12 - pip - pip: - -r requirements.txt diff --git a/installer/linux/build_installer.sh b/installer/linux/build_installer.sh index 533687b6..c9339482 100644 --- a/installer/linux/build_installer.sh +++ b/installer/linux/build_installer.sh @@ -115,7 +115,7 @@ echo "" wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O "$TMP_DIR/miniconda.sh" bash ./miniconda.sh -b -p ./miniconda -./miniconda/bin/conda create -n sscanss -y python=3.10 +./miniconda/bin/conda create -n sscanss -y python=3.12 echo "" echo "Downloading Dependencies" @@ -123,8 +123,6 @@ echo "" python_exec="./miniconda/envs/sscanss/bin/python" mkdir "$TMP_DIR/packages" $python_exec -m pip download -r "./sscanss/requirements.txt" --dest "$TMP_DIR/packages" -# workaround for centos 7 -$python_exec -m pip download --only-binary=":all:" --platform="manylinux_2_17_x86_64" --dest "$TMP_DIR/packages" pillow==9.2 echo "" echo "Compressing Package.tar.gz ..." diff --git a/installer/linux/install.sh b/installer/linux/install.sh index 4a42dcaf..4cef5761 100644 --- a/installer/linux/install.sh +++ b/installer/linux/install.sh @@ -119,7 +119,7 @@ python_exec="./envs/sscanss/bin/python" CFLAGS=$(./envs/sscanss/bin/python3-config --includes) export CFLAGS=$CFLAGS $python_exec -m pip install --no-cache-dir --no-index --no-build-isolation --find-links packages -r "./sscanss/requirements.txt" >/dev/null -chmod 777 -R "./envs/sscanss/lib/python3.10/site-packages/PyQt6/" +chmod 777 -R "./envs/sscanss/lib/python3.12/site-packages/PyQt6/" if [ "$INSTALL_EDITOR" = y ]; then $python_exec "./sscanss/make.py" --build-sscanss --build-editor >/dev/null else diff --git a/installer/linux/readme.txt b/installer/linux/readme.txt index 4347c0db..15796822 100644 --- a/installer/linux/readme.txt +++ b/installer/linux/readme.txt @@ -1,26 +1,3 @@ -Before Installation -------------------- -SScanSS 2 requires OpenSSL CA certificates when checking for updates. If you want to -use this feature, install OpenSSL if not installed (Most linux distros have OpenSSL -pre-installed.) - - > sudo apt-get install openssl - -Add environment variable "SSL_CERT_DIR" and set its value to the path of the -CA certificate directory. The OpenSSL install directory can be found by typing - - > openssl version -d - -The "SSL_CERT_DIR" variable should be set to the path of the "certs" folder in the -OpenSSL install directory e.g. - - SSL_CERT_DIR=/usr/lib/ssl/certs - -Ensure the variable is permanent, i.e. close and reopen the terminal and check that -the variable is still available. You may need to write the variable to a file e.g. -"etc/environment" on Ubuntu. - - Installation ------------ Run the install script in a terminal as below and follow the prompts to continue diff --git a/make.py b/make.py index e60ebaed..a3acbad0 100644 --- a/make.py +++ b/make.py @@ -28,7 +28,7 @@ ] HIDDEN_IMPORT = ['--hidden-import', 'OpenGL.platform.egl'] IS_WINDOWS = sys.platform.startswith('win') -IS_MAC = True if sys.platform == 'darwin' else False +IS_MAC = sys.platform == 'darwin' def format_code(check=False): diff --git a/requirements-dev.txt b/requirements-dev.txt index 970d321c..cd325999 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,5 +1,5 @@ -coverage==7.0.5 -pylint==2.16.2 -Sphinx==5.3.0 +coverage==7.9.2 +pylint==3.3.7 +Sphinx==8.1.3 sphinx-bootstrap-theme==0.8.1 yapf==0.31.0 diff --git a/requirements.txt b/requirements.txt index fb7368a3..53720974 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,19 +1,18 @@ -bitarray==2.6.2 -cython==0.29.33 -h5py==3.7.0 -jsbeautifier==1.14.7 -jsonschema==4.16.0 -matplotlib==3.6.3 -NLopt==2.7.1 -numpy==1.23.5 -gimpact==1.0.1 -Pillow==9.2.0 +bitarray==3.5.2 +cython==3.0.12 +h5py==3.13.0 +jsbeautifier==1.15.4 +jsonschema==4.24.1 +matplotlib==3.9.4 +NLopt==2.8.0 +numpy==2.2.6 +gimpact==1.0.2 PyInstaller==6.11.1 -PyOpenGL==3.1.6 -PyQt6==6.3.1 -PyQt6-Qt6==6.5.2 -pystache==0.6.0 -PyQt6-QScintilla==2.13.4 -scipy==1.9.3 -tifffile==2022.10.10 -psutil==5.9.4 +PyOpenGL==3.1.9 +PyQt6==6.6.1 +PyQt6-Qt6==6.6.3 +pystache==0.6.7 +PyQt6-QScintilla==2.14.1 +scipy==1.15.3 +tifffile==2025.5.24 +psutil==7.0.0 diff --git a/setup.py b/setup.py index 24359bd2..363c0e64 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ 'tifffile', 'psutil', ], - classifiers=['Programming Language :: Python :: 3.10', + classifiers=['Programming Language :: Python :: 3.12', 'License :: OSI Approved :: BSD License', 'Natural Language :: English', 'Intended Audience :: Science/Research', diff --git a/sscanss/app/dialogs/misc.py b/sscanss/app/dialogs/misc.py index b9872821..33226707 100644 --- a/sscanss/app/dialogs/misc.py +++ b/sscanss/app/dialogs/misc.py @@ -1383,7 +1383,7 @@ def plot(self): if self.simulation.args['align_first_order']: path_length = np.column_stack(np.dsplit(path_length, path_length.shape[2])).reshape(-1, len(names)) else: - path_length = np.row_stack(np.dsplit(path_length, path_length.shape[2])).reshape(-1, len(names)) + path_length = np.vstack(np.dsplit(path_length, path_length.shape[2])).reshape(-1, len(names)) title = 'Path lengths for measurements' label = np.arange(1, path_length.shape[0] + 1) diff --git a/sscanss/core/geometry/intersection.py b/sscanss/core/geometry/intersection.py index 44e6e7ff..4ae18755 100644 --- a/sscanss/core/geometry/intersection.py +++ b/sscanss/core/geometry/intersection.py @@ -393,7 +393,7 @@ def volume_plane_intersection(volume, plane, resolution=1024): matrix[:3, :3] = view_matrix.transpose() matrix = np.linalg.inv(matrix @ volume.transform_matrix @ np.diag([*volume.voxel_size, 1])) - rotated_segments = np.row_stack(segments) @ view_matrix + rotated_segments = np.vstack(segments) @ view_matrix min_limits = rotated_segments.min(axis=0) max_limits = rotated_segments.max(axis=0) diff --git a/sscanss/core/instrument/simulation.py b/sscanss/core/instrument/simulation.py index da723bb6..2f75eb2c 100644 --- a/sscanss/core/instrument/simulation.py +++ b/sscanss/core/instrument/simulation.py @@ -88,7 +88,7 @@ def __init__(self, instrument): self.size = len(entity.transforms) self.vertices = SharedArray.fromNumpyArray(entity.vertices) self.indices = SharedArray.fromNumpyArray(entity.indices) - self.transforms = SharedArray.fromNumpyArray(np.row_stack(entity.transforms)) + self.transforms = SharedArray.fromNumpyArray(np.vstack(entity.transforms)) self.offsets = entity.offsets self.keys = entity.keys diff --git a/sscanss/core/io/reader.py b/sscanss/core/io/reader.py index 10237793..801d6c3a 100644 --- a/sscanss/core/io/reader.py +++ b/sscanss/core/io/reader.py @@ -771,7 +771,7 @@ def file_walker(filepath, extension=(".tiff", ".tif")): return list_of_files -def filename_sorting_key(string, regex=re.compile('(\d+)')): +def filename_sorting_key(string, regex=re.compile(r'(\d+)')): """Returns a key for sorting filenames containing numbers in a natural way. :param string: input string diff --git a/sscanss/core/math/matrix.py b/sscanss/core/math/matrix.py index fbeb24a6..fb423a5b 100644 --- a/sscanss/core/math/matrix.py +++ b/sscanss/core/math/matrix.py @@ -37,7 +37,7 @@ def __init__(self, rows, cols, values=None, dtype=None): super().__setattr__("_data", data) super().__setattr__("_keys", {}) - def __array__(self, _dtype=None): + def __array__(self, dtype=None, copy=None): return self._data def __getattr__(self, attr): diff --git a/sscanss/core/math/quaternion.py b/sscanss/core/math/quaternion.py index d98ba112..8b3a7f56 100644 --- a/sscanss/core/math/quaternion.py +++ b/sscanss/core/math/quaternion.py @@ -22,7 +22,7 @@ class Quaternion: def __init__(self, w=0.0, x=0.0, y=0.0, z=0.0): self._data = Vector4([x, y, z, w]) - def __array__(self, _dtype=None): + def __array__(self, dtype=None, copy=None): return self._data[:] @classmethod diff --git a/sscanss/core/math/vector.py b/sscanss/core/math/vector.py index 0a67d909..186fc246 100644 --- a/sscanss/core/math/vector.py +++ b/sscanss/core/math/vector.py @@ -33,7 +33,7 @@ def __init__(self, size, values=None, dtype=None): super().__setattr__("_data", data) super().__setattr__("_keys", {}) - def __array__(self, _dtype=None): + def __array__(self, dtype=None, copy=None): return self._data def __getattr__(self, attr): diff --git a/sscanss/core/scene/entity.py b/sscanss/core/scene/entity.py index e4433097..4983be69 100644 --- a/sscanss/core/scene/entity.py +++ b/sscanss/core/scene/entity.py @@ -200,7 +200,7 @@ def __init__(self, points, vectors, alignment, visible=True): ranges.append(count) self.colours = colour self.offsets = ranges - self.vertices.append(np.array(np.row_stack(vertices), dtype=np.float32)) + self.vertices.append(np.array(np.vstack(vertices), dtype=np.float32)) self.indices = np.arange(0, len(self.vertices[-1]), dtype=np.uint32) def node(self): @@ -267,9 +267,9 @@ def __init__(self, instrument): self._updateParams(mesh, Matrix44.identity()) self.keys[f'{Attributes.Fixture.value}_{name}'] = len(self.offsets) - self.vertices = np.row_stack(self._vertices) + self.vertices = np.vstack(self._vertices) self.indices = np.concatenate(self._indices) - self.normals = np.row_stack(self._normals) + self.normals = np.vstack(self._normals) def _updateParams(self, mesh, transform): self._vertices.append(mesh.vertices) @@ -359,9 +359,9 @@ def addReferencePlane(self, plane, size): """ mesh = create_plane(plane, size[0], size[1]) count = len(self.reference_plane_vertices) - self.reference_plane_vertices = np.row_stack((self.reference_plane_vertices, mesh.vertices)) + self.reference_plane_vertices = np.vstack((self.reference_plane_vertices, mesh.vertices)) self.reference_plane_indices = np.concatenate((self.reference_plane_indices, mesh.indices + count)) - self.reference_plane_normals = np.row_stack((self.reference_plane_normals, mesh.normals)) + self.reference_plane_normals = np.vstack((self.reference_plane_normals, mesh.normals)) self.reference_plane_offsets.append(len(self.reference_plane_indices)) def clearReferencePlanes(self): diff --git a/tests/test_io.py b/tests/test_io.py index 8b516d9b..8ab126d0 100644 --- a/tests/test_io.py +++ b/tests/test_io.py @@ -207,8 +207,8 @@ def testHDFReadWrite(self, visual_fn, setting_cls): group['indices'] = mesh_to_write.indices result, _ = reader.read_project_hdf(filename) - vertices = np.row_stack((mesh_to_write.vertices, mesh_to_write.vertices + 2)) - normals = np.row_stack((mesh_to_write.normals, mesh_to_write.normals)) + vertices = np.vstack((mesh_to_write.vertices, mesh_to_write.vertices + 2)) + normals = np.vstack((mesh_to_write.normals, mesh_to_write.normals)) np.testing.assert_array_almost_equal(result["sample"].vertices, vertices, decimal=5) np.testing.assert_array_almost_equal(result["sample"].normals, normals, decimal=5) np.testing.assert_array_almost_equal(result["sample"].indices, np.arange(6, dtype=int)) diff --git a/tests/test_main_model.py b/tests/test_main_model.py index 158586d3..fa14cff5 100644 --- a/tests/test_main_model.py +++ b/tests/test_main_model.py @@ -102,8 +102,8 @@ def testAddMesh(self): self.assertIs(self.model.sample, self.mesh) mesh_2 = self.mesh.copy() mesh_2.vertices += 2 - vertices = np.row_stack((self.mesh.vertices, mesh_2.vertices)) - normals = np.row_stack((self.mesh.normals, mesh_2.normals)) + vertices = np.vstack((self.mesh.vertices, mesh_2.vertices)) + normals = np.vstack((self.mesh.normals, mesh_2.normals)) self.model.addMeshToProject(mesh_2, InsertSampleOptions.Combine) np.testing.assert_array_almost_equal(self.model.sample.vertices, vertices, decimal=5) np.testing.assert_array_almost_equal(self.model.sample.normals, normals, decimal=5) @@ -269,7 +269,7 @@ def testLoadAndSaveVectors(self): decimal=5, ) np.testing.assert_array_almost_equal(new_vectors[:3, :, 1], - np.row_stack((vectors[3, :], np.zeros((2, 3)))), + np.vstack((vectors[3, :], np.zeros((2, 3)))), decimal=5) vectors[0, 0] = 10