diff --git a/.github/workflows/test_and_deploy.yml b/.github/workflows/test_and_deploy.yml index 5fb4065..0d0b2b9 100644 --- a/.github/workflows/test_and_deploy.yml +++ b/.github/workflows/test_and_deploy.yml @@ -2,22 +2,38 @@ name: Run tests on: push: - branches: [ main ] + branches: + - "main" + tags: + - "v**" pull_request: + workflow_dispatch: + +concurrency: + # Cancel this workflow if it is running, + # and then changes are applied on top of the HEAD of the branch, + # triggering another run of the workflow + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: - lint: + linting: + name: Check Linting runs-on: ubuntu-latest steps: - - uses: neuroinformatics-unit/actions/lint@v1 + - uses: neuroinformatics-unit/actions/lint@v2 + + manifest: + name: Check Manifest + runs-on: ubuntu-latest + steps: + - uses: neuroinformatics-unit/actions/lint@v2 test: - needs: lint - name: ${{ matrix.os }} py${{ matrix.python-version }} + name: Run package tests runs-on: ${{ matrix.os }} strategy: matrix: - # Run across a mixture of Python versions and operating systems include: - os: ubuntu-latest python-version: "3.11" @@ -25,10 +41,23 @@ jobs: python-version: "3.10" - os: windows-latest python-version: "3.9" - - os: ubuntu-latest - python-version: "3.8" steps: - uses: neuroinformatics-unit/actions/test@v1 with: python-version: ${{ matrix.python-version }} + + build_sdist_wheel: + name: Build source distribution and wheel + needs: [test, linting, manifest] + if: github.event_name == 'push' && github.ref_type == 'tag' + runs-on: ubuntu-latest + steps: + - uses: actions/download-artifact@v3 + with: + name: artifact + path: dist + - uses: pypa/gh-action-pypi-publish@v1.5.0 + with: + user: __token__ + password: ${{ secrets.TWINE_API_KEY }} diff --git a/MANIFEST.in b/MANIFEST.in index c1a7121..10f45ec 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,10 @@ include LICENSE include README.md + +exclude .pre-commit-config.yaml +exclude .codecov.yml + +graft brainglobe_space + +prune tests +prune docs diff --git a/README.md b/README.md index d76624c..958c3c6 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,27 @@ -# `bg-space` has become `brainglobe-space` - -To continue receiving updates, please switch to using [`brainglobe-space`](https://github.com/brainglobe/brainglobe-space) instead of this package. -`bg-space` will no longer be receiving updates, and has been replaced by `brainglobe-space` in all other aspects of the BrainGlobe tool suite. - -Old README.md contents are below. - -# BG-Space - -Anatomical space conventions made easy. - -[![Python Version](https://img.shields.io/pypi/pyversions/bg-space.svg)](https://pypi.org/project/bg-space) -[![PyPI](https://img.shields.io/pypi/v/bg-space.svg)](https://pypi.org/project/bg-space) -[![Build Status](https://travis-ci.com/brainglobe/bg-space.svg?branch=master)](https://travis-ci.com/brainglobe/bg-space) +[![Python Version](https://img.shields.io/pypi/pyversions/brainglobe-space.svg)](https://pypi.org/project/brainglobe-space) +[![PyPI](https://img.shields.io/pypi/v/brainglobe-space.svg)](https://pypi.org/project/brainglobe-space) +[![Build Status](https://travis-ci.com/brainglobe/brainglobe-space.svg?branch=master)](https://travis-ci.com/brainglobe/brainglobe-space) [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) -[![Coverage Status](https://coveralls.io/repos/github/brainglobe/bg-space/badge.svg)](https://coveralls.io/github/brainglobe/bg-space) +[![Coverage Status](https://coveralls.io/repos/github/brainglobe/brainglobe-space/badge.svg)](https://coveralls.io/github/brainglobe/brainglobe-space) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/python/black) [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.4552537.svg)](https://doi.org/10.5281/zenodo.4552537) +# brainglobe-space + +Anatomical space conventions made easy. + Working with anatomical images, one often encounters the problem of matching the orientation of stacks with different conventions about axes orientation and order. Moreover, when multiple swaps and flips are involved, it can be annoying to map the same transformations to volumes and points (e.g., coordinates or meshes). -`bg-space` provides a neat way of defining an anatomical space, and of operating stacks and point transformations between spaces. +`brainglobe-space` provides a neat way of defining an anatomical space, and of operating stacks and point transformations between spaces. -If you use `bg-space` for your analyses, please cite its Zenodo DOI https://zenodo.org/record/4552537#.YDAFzi1Q2Rs! +If you use `brainglobe-space` for your analyses, please cite its [Zenodo DOI](https://zenodo.org/record/4552537#.YDAFzi1Q2Rs!) ## Installation -You can install `bg-space` with: +You can install `brainglobe-space` with: ```bash -pip install bg-space +pip install brainglobe-space ``` ## Usage @@ -43,7 +36,7 @@ target_origin = ("Inferior", "Posterior", "Right") A stack can be then easily transformed from the source to the target space: ```python -import bg_space as bg +import brainglobe_space as bg import numpy as np stack = np.random.rand(3, 2, 4) @@ -60,7 +53,8 @@ mapped_stack = bg.map_stack_to("lsa", "ipr", stack) ``` --- -**NOTE** + +## NOTE When you work with a stack, the origin is the upper left corner when you show the first element `stack[0, :, :]` with matplotlib or when you open the stack with ImageJ. First dimension is the one that you are slicing, the second the height of the image, and the third the width of the image. @@ -84,7 +78,6 @@ mapped_stack = source_space.map_stack_to("ipr", stack) # transform the stack mapped_annotations = source_space.map_points_to("ipr", annotations) # transform the points ``` - The points are transformed through the generation of a transformation matrix. Finally, if we want to log this matrix (e.g., to reconstruct the full transformations sequence of a registration), we can get it: @@ -98,6 +91,7 @@ transformation_matrix = source_space.transformation_matrix_to("ipr", stack.shape The target get always be defined as a `bg.AnatomicalSpace` object, or a valid origin specification plus a shape (the shape is required only if axes flips are required). ## Matching space resolutions and offsets + The `AnatomicalSpace` class can deal also with stack resampling/padding/cropping. This requires simply specifying values for resolutions and offsets when instantiating a `AnatomicalSpace` object. Once that is done, using `AnatomicalSpace.transformation_matrix_to` creating affine transformation matrices from one space to the other will be a piece of cake! ```python @@ -114,7 +108,6 @@ target_space = bgs.AnatomicalSpace("asl", resolution=(1, 1, 1), shape=(5, 4, 2)) source_space.transformation_matrix_to(target_space, stack, to_target_shape=True) ``` - ## Easy iteration over projections Finally, another convenient feature of BGSpace is the possibility of iterating easily through the projections of the stack and generate section names and axes labels: @@ -130,7 +123,8 @@ for i, (plane, labels) in enumerate(zip(sc.sections, sc.axis_labels)): axs[i].set_xlabel(labels[1]) ``` -![](/docs/img/projections.png) +![Projection illustrations](/docs/img/projections.png) ## Contributing + Contributions are very welcome. Please see the [developers guide](https://brainglobe.info/developers/index.html). diff --git a/bg_space/__init__.py b/bg_space/__init__.py deleted file mode 100644 index 0cd2fec..0000000 --- a/bg_space/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -from warnings import warn - -warn( - "bg-space has been renamed to brainglobe-space. To continue receiving updates, we recommend you uninstall this package and install brainglobe-space instead: https://github.com/brainglobe/brainglobe-space", - DeprecationWarning, -) - -__author__ = """Luigi Petrucco @brainglobe""" -__version__ = "0.6.0" - -from bg_space.core import AnatomicalSpace, SpaceConvention -from bg_space.functions import ( - map_to, - map_stack_to, - transformation_matrix_to, - transform_points_to, -) diff --git a/brainglobe_space/__init__.py b/brainglobe_space/__init__.py new file mode 100644 index 0000000..04eb581 --- /dev/null +++ b/brainglobe_space/__init__.py @@ -0,0 +1,10 @@ +__author__ = """Luigi Petrucco @brainglobe""" +__version__ = "0.6.0" + +from brainglobe_space.core import AnatomicalSpace, SpaceConvention +from brainglobe_space.functions import ( + map_to, + map_stack_to, + transformation_matrix_to, + transform_points_to, +) diff --git a/bg_space/core.py b/brainglobe_space/core.py similarity index 99% rename from bg_space/core.py rename to brainglobe_space/core.py index 8c289f2..71356e2 100644 --- a/bg_space/core.py +++ b/brainglobe_space/core.py @@ -4,7 +4,7 @@ import numpy as np from scipy import ndimage as nd -from bg_space.utils import deprecated, ordered_list_from_set +from brainglobe_space.utils import deprecated, ordered_list_from_set def to_target(method): @@ -486,7 +486,7 @@ def __eq__(self, other): @deprecated( "SpaceConvention will be removed from v0.6. " - "Use bg_space.AnatomicalSpace instead" + "Use brainglobe_space.AnatomicalSpace instead" ) class SpaceConvention(AnatomicalSpace): pass diff --git a/bg_space/functions.py b/brainglobe_space/functions.py similarity index 97% rename from bg_space/functions.py rename to brainglobe_space/functions.py index 3955dd2..22bee17 100644 --- a/bg_space/functions.py +++ b/brainglobe_space/functions.py @@ -1,4 +1,4 @@ -from bg_space.core import AnatomicalSpace +from brainglobe_space.core import AnatomicalSpace # TODO convert to a smarter way to generate those parsing class' methods: diff --git a/bg_space/utils.py b/brainglobe_space/utils.py similarity index 100% rename from bg_space/utils.py rename to brainglobe_space/utils.py diff --git a/pyproject.toml b/pyproject.toml index f3ee290..3afd415 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,66 +1,67 @@ [project] -name = "bg_space" +name = "brainglobe_space" description = "Anatomical space conventions made easy" readme = "README.md" -authors = [ - {name = "Luigi Petrucco", email = "luigi.petrucco@gmail.com"}, -] +authors = [{ name = "Luigi Petrucco", email = "luigi.petrucco@gmail.com" }] classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Science/Research", "Operating System :: OS Independent", "Programming Language :: Python", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", ] -requires-python = ">=3.8" -dependencies = [ - "numpy", - "scipy", -] +requires-python = ">=3.9" +dependencies = ["numpy", "scipy"] dynamic = ["version"] [project.urls] -Homepage = "https://github.com/brainglobe/bg-space" +Homepage = "https://github.com/brainglobe/brainglobe-space" [project.optional-dependencies] -dev = [ - "gitpython", - "pre-commit", - "pytest", - "pytest-cov", -] +dev = ["gitpython", "pre-commit", "pytest", "pytest-cov"] [build-system] -requires = [ - "setuptools>=45", - "wheel", - "setuptools_scm[toml]>=6.2", -] +requires = ["setuptools>=45", "wheel", "setuptools_scm[toml]>=6.2"] build-backend = "setuptools.build_meta" [tool.setuptools] include-package-data = true [tool.setuptools.packages.find] -include = ["bg_space*"] +include = ["brainglobe_space*"] [tool.setuptools_scm] [tool.pytest.ini_options] -filterwarnings = [ - "error", -] +filterwarnings = ["error"] [tool.black] -target-version = ['py38', 'py39', 'py310', 'py311'] +target-version = ['py39', 'py310', 'py311'] skip-string-normalization = false line-length = 79 [tool.ruff] line-length = 79 -exclude = ["__init__.py","build",".eggs"] +exclude = ["__init__.py", "build", ".eggs"] select = ["I", "E", "F"] fix = true + +[tool.tox] +legacy_tox_ini = """ +[tox] +envlist = py{39,310,311} + +[gh-actions] +python = + 3.9: py39 + 3.10: py310 + 3.11: py311 + +[testenv] +extras = + dev +commands = + pytest -v --color=yes --cov=brainglobe_space --cov-report=xml +""" diff --git a/tests/test_core.py b/tests/test_core.py index 5df31ad..b390de4 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -4,7 +4,7 @@ import numpy as np import pytest -from bg_space import AnatomicalSpace, SpaceConvention +from brainglobe_space import AnatomicalSpace, SpaceConvention from .utils import create_label_array diff --git a/tests/test_functions.py b/tests/test_functions.py index 2a1327f..f80fe4d 100644 --- a/tests/test_functions.py +++ b/tests/test_functions.py @@ -1,8 +1,8 @@ import numpy as np import pytest -from bg_space.core import AnatomicalSpace -from bg_space.functions import ( +from brainglobe_space.core import AnatomicalSpace +from brainglobe_space.functions import ( map_stack_to, map_to, transform_points_to, diff --git a/tests/utils.py b/tests/utils.py index ff0a42e..046a7a9 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,6 +1,6 @@ import numpy as np -from bg_space import AnatomicalSpace +from brainglobe_space import AnatomicalSpace char_add = np.core.defchararray.add diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 3c97c59..0000000 --- a/tox.ini +++ /dev/null @@ -1,15 +0,0 @@ -[tox] -envlist = py{38,39,310,311} - -[gh-actions] -python = - 3.8: py38 - 3.9: py39 - 3.10: py310 - 3.11: py311 - -[testenv] -extras = - dev -commands = - pytest -v --color=yes --cov=bg_space --cov-report=xml -W ignore::DeprecationWarning