diff --git a/.github/workflows/test_and_deploy.yml b/.github/workflows/test_and_deploy.yml new file mode 100644 index 00000000..3105dc00 --- /dev/null +++ b/.github/workflows/test_and_deploy.yml @@ -0,0 +1,107 @@ +name: tests + +on: + push: + branches: + - "main" + tags: + - "*" + pull_request: + workflow_dispatch: + inputs: + coredev: + description: 'Tests with development version of cellfinder-core?' + required: true + default: 'false' + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + linting: + name: Linting + runs-on: ubuntu-latest + steps: + - uses: neuroinformatics-unit/actions/lint@v2 + + manifest: + name: Check manifest + runs-on: ubuntu-latest + steps: + - uses: neuroinformatics-unit/actions/check_manifest@v2 + + test: + needs: [linting,manifest] + runs-on: ${{ matrix.os }} + env: + INPUT_COREDEV: ${{ github.event.inputs.coredev }} + strategy: + fail-fast: false + matrix: + # Run across a mixture of Python versions and operating systems + include: + - os: macos-latest + python-version: "3.10" + - os: windows-latest + python-version: "3.9" + - os: ubuntu-latest + python-version: "3.8" + steps: + - uses: neuroinformatics-unit/actions/test@v2 + with: + python-version: ${{ matrix.python-version }} + + build_sdist_wheels: + name: Build source distribution + needs: [test] + if: github.event_name == 'push' && github.ref_type == 'tag' + runs-on: ubuntu-latest + steps: + - uses: neuroinformatics-unit/actions/build_sdist_wheels@v2 + + deploy: + needs: [build_sdist_wheels] + runs-on: ubuntu-latest + if: github.event_name == 'push' && github.ref_type == 'tag' + 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 }} + + build-and-push-docker: + needs: deploy + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Log in to the Container registry + uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Build and push Docker image + uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..8c1f8334 --- /dev/null +++ b/.gitignore @@ -0,0 +1,126 @@ +# Custom config files +*.conf.custom + +# Byte-compiled / optimized / DLL files +**/__pycache__/** +*.py[cod] +*$py.class + +# Cython +*.c +*.cpp + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +doc/build/ + +# pydocmd +_build/ +mkdocs.yml + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +.envrc + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +.idea/ + +*.~lock.* + +pip-wheel-metadata/ + +*.DS_Store + +*.vscode/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..f60812bd --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,32 @@ +# Configuring https://pre-commit.ci/ +ci: + autoupdate_schedule: monthly + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: check-docstring-first + - id: check-executables-have-shebangs + - id: check-merge-conflict + - id: check-toml + - id: end-of-file-fixer + - id: mixed-line-ending + args: [--fix=lf] + - id: requirements-txt-fixer + - id: trailing-whitespace + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.0.286 + hooks: + - id: ruff + - repo: https://github.com/psf/black + rev: 23.7.0 + hooks: + - id: black + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.5.1 + hooks: + - id: mypy + additional_dependencies: + - types-setuptools + - types-requests diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..f8393006 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,4 @@ +FROM tensorflow/tensorflow:latest-gpu +LABEL maintainer="code@adamltyson.com" +RUN pip install cellfinder +CMD ["bash"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..3e221c2a --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2020, University College London +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 00000000..c7354c00 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,18 @@ +include README.md +include LICENSE + +exclude *.yaml +exclude *.yml +exclude Dockerfile +exclude *.ini + +recursive-include cellfinder *.py +include cellfinder/config/* + +global-include *.pxd + +prune tests +prune resources + +prune .github +prune .tox diff --git a/README.md b/README.md index e69de29b..b831d0dc 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,150 @@ +[![Python Version](https://img.shields.io/pypi/pyversions/cellfinder.svg)](https://pypi.org/project/cellfinder) +[![PyPI](https://img.shields.io/pypi/v/cellfinder.svg)](https://pypi.org/project/cellfinder) +[![Downloads](https://pepy.tech/badge/cellfinder)](https://pepy.tech/project/cellfinder) +[![Wheel](https://img.shields.io/pypi/wheel/cellfinder.svg)](https://pypi.org/project/cellfinder) +[![Development Status](https://img.shields.io/pypi/status/cellfinder.svg)](https://github.com/brainglobe/cellfinder) +[![Tests](https://img.shields.io/github/workflow/status/brainglobe/cellfinder/tests)]( + https://github.com/brainglobe/cellfinder/actions) +[![codecov](https://codecov.io/gh/brainglobe/cellfinder/branch/master/graph/badge.svg?token=s3MweEFPhl)](https://codecov.io/gh/brainglobe/cellfinder) +[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/python/black) +[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/) +[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit) +[![Contributions](https://img.shields.io/badge/Contributions-Welcome-brightgreen.svg)](https://docs.brainglobe.info/cellfinder/contributing) +[![Website](https://img.shields.io/website?up_message=online&url=https%3A%2F%2Fbrainglobe.info)](https://brainglobe.info/documentation/cellfinder/index.html) +[![Twitter](https://img.shields.io/twitter/follow/brain_globe?style=social)](https://twitter.com/brain_globe) + +# Cellfinder +Whole-brain cell detection, registration and analysis. + +**N.B. If you want to just use the cell detection part of cellfinder, please +see the standalone [cellfinder-core](https://github.com/brainglobe/cellfinder-core) +package, or the [cellfinder plugin](https://github.com/brainglobe/cellfinder-napari) +for [napari](https://napari.org/).** + +--- +`cellfinder` is a collection of tools developed by [Adam Tyson](https://github.com/adamltyson), [Charly Rousseau](https://github.com/crousseau) and [Christian Niedworok](https://github.com/cniedwor) in the [Margrie Lab](https://www.sainsburywellcome.org/web/groups/margrie-lab), generously supported by the [Sainsbury Wellcome Centre](https://www.sainsburywellcome.org/web/). + +`cellfinder` is a designed for the analysis of whole-brain imaging data such as + [serial-section imaging](https://sainsburywellcomecentre.github.io/OpenSerialSection/) + and lightsheet imaging in cleared tissue. The aim is to provide a single solution for: + + * Cell detection (initial cell candidate detection and refinement using + deep learning) (using [cellfinder-core](https://github.com/brainglobe/cellfinder-core)) + * Atlas registration (using [brainreg](https://github.com/brainglobe/brainreg)) + * Analysis of cell positions in a common space + + --- +Installation is with +`pip install cellfinder` + +--- +Basic usage: +```bash +cellfinder -s signal_images -b background_images -o output_dir --metadata metadata +``` +Full documentation can be +found [here](https://brainglobe.info/documentation/cellfinder/index.html). + +This software is at a very early stage, and was written with our data in mind. +Over time we hope to support other data types/formats. If you have any issues, please get in touch [on the forum](https://forum.image.sc/tag/brainglobe) or by +[raising an issue](https://github.com/brainglobe/cellfinder/issues/new/choose). + + +--- +## Illustration + +### Introduction +cellfinder takes a stitched, but otherwise raw whole-brain dataset with at least +two channels: + * Background channel (i.e. autofluorescence) + * Signal channel, the one with the cells to be detected: + +![raw](https://raw.githubusercontent.com/brainglobe/cellfinder/master/resources/raw.png) +**Raw coronal serial two-photon mouse brain image showing labelled cells** + + +### Cell candidate detection +Classical image analysis (e.g. filters, thresholding) is used to find +cell-like objects (with false positives): + +![raw](https://raw.githubusercontent.com/brainglobe/cellfinder/master/resources/detect.png) +**Candidate cells (including many artefacts)** + + +### Cell candidate classification +A deep-learning network (ResNet) is used to classify cell candidates as true +cells or artefacts: + +![raw](https://raw.githubusercontent.com/brainglobe/cellfinder/master/resources/classify.png) +**Cassified cell candidates. Yellow - cells, Blue - artefacts** + +### Registration and segmentation (brainreg) +Using [brainreg](https://github.com/brainglobe/brainreg), +cellfinder aligns a template brain and atlas annotations (e.g. +the Allen Reference Atlas, ARA) to the sample allowing detected cells to be assigned +a brain region. + +This transformation can be inverted, allowing detected cells to be +transformed to a standard anatomical space. + +![raw](https://raw.githubusercontent.com/brainglobe/cellfinder/master/resources/register.png) +**ARA overlaid on sample image** + +### Analysis of cell positions in a common anatomical space +Registration to a template allows for powerful group-level analysis of cellular +disributions. *(Example to come)* + +## Examples +*(more to come)* + +### Tracing of inputs to retrosplenial cortex (RSP) +Input cell somas detected by cellfinder, aligned to the Allen Reference Atlas, +and visualised in [brainrender](https://github.com/brainglobe/brainrender) along +with RSP. + +![brainrender](https://raw.githubusercontent.com/brainglobe/cellfinder/master/resources/brainrender.png) + +Data courtesy of Sepiedeh Keshavarzi and Chryssanthi Tsitoura. [Details here](https://www.youtube.com/watch?v=pMHP0o-KsoQ) + +## Visualisation + +cellfinder comes with a plugin ([brainglobe-napari-io](https://github.com/brainglobe/brainglobe-napari-io)) for [napari](https://github.com/napari/napari) to view your data + +#### Usage +* Open napari (however you normally do it, but typically just type `napari` into your terminal, or click on your desktop icon) + +#### Load cellfinder XML file +* Load your raw data (drag and drop the data directories into napari, one at a time) +* Drag and drop your cellfinder XML file (e.g. `cell_classification.xml`) into napari. + +#### Load cellfinder directory +* Load your raw data (drag and drop the data directories into napari, one at a time) +* Drag and drop your cellfinder output directory into napari. + +The plugin will then load your detected cells (in yellow) and the rejected cell +candidates (in blue). If you carried out registration, then these results will be +overlaid (similarly to the loading brainreg data, but transformed to the +coordinate space of your raw data). + +![load_data](https://raw.githubusercontent.com/brainglobe/brainglobe-napari-io/master/resources/load_data.gif) +**Loading raw data** + +![load_data](https://raw.githubusercontent.com/brainglobe/brainglobe-napari-io/master/resources/load_results.gif) +**Loading cellfinder results** + + +## Contributing +Contributions to cellfinder are more than welcome. Please see the [developers guide](https://brainglobe.info/developers/index.html). + + +## Citing cellfinder + +If you find cellfinder useful, and use it in your research, please cite the paper outlining the cell detection algorithm: +> Tyson, A. L., Rousseau, C. V., Niedworok, C. J., Keshavarzi, S., Tsitoura, C., Cossell, L., Strom, M. and Margrie, T. W. (2021) “A deep learning algorithm for 3D cell detection in whole mouse brain image datasets’ PLOS Computational Biology, 17(5), e1009074 +[https://doi.org/10.1371/journal.pcbi.1009074](https://doi.org/10.1371/journal.pcbi.1009074) +> +If you use any of the image registration functions in cellfinder, please also cite [brainreg](https://github.com/brainglobe/brainreg#citing-brainreg). + +**If you use this, or any other tools in the brainglobe suite, please + [let us know](mailto:code@adamltyson.com?subject=cellfinder), and + we'd be happy to promote your paper/talk etc.** diff --git a/cellfinder/__init__.py b/cellfinder/__init__.py new file mode 100644 index 00000000..dece5176 --- /dev/null +++ b/cellfinder/__init__.py @@ -0,0 +1,7 @@ +from importlib.metadata import metadata + +__version__ = metadata("cellfinder")["version"] +__author__ = metadata("cellfinder")["author-email"] +__license__ = metadata("cellfinder")["license"] + +del metadata diff --git a/cellfinder/analyse/__init__.py b/cellfinder/analyse/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/cellfinder/analyse/analyse.py b/cellfinder/analyse/analyse.py new file mode 100644 index 00000000..17133241 --- /dev/null +++ b/cellfinder/analyse/analyse.py @@ -0,0 +1,368 @@ +""" +Cell position analysis (based on atlas registration). + +Based on https://github.com/SainsburyWellcomeCentre/cell_count_analysis by +Charly Rousseau (https://github.com/crousseau). +""" +import logging +import os +from pathlib import Path +from typing import List, Optional + +import bg_space as bgs +import imio +import numpy as np +import pandas as pd +import tifffile +from bg_atlasapi import BrainGlobeAtlas +from brainglobe_utils.general.system import ensure_directory_exists +from brainglobe_utils.pandas.misc import sanitise_df + +from cellfinder.export.export import export_points + + +class Point: + def __init__( + self, + raw_coordinate, + atlas_coordinate, + structure, + structure_id, + hemisphere, + ): + self.raw_coordinate = raw_coordinate + self.atlas_coordinate = atlas_coordinate + self.structure = structure + self.structure_id = structure_id + self.hemisphere = hemisphere + + +def calculate_densities(counts, volume_csv_path): + """ + Use the region volume information from registration to calculate cell + densities. Based on the atlas names, which must be exactly equal. + :param counts: dataframe with cell counts + :param volume_csv_path: path of the volumes of each brain region + :return: + """ + volumes = pd.read_csv(volume_csv_path, sep=",", header=0, quotechar='"') + df = pd.merge(counts, volumes, on="structure_name", how="outer") + df = df.fillna(0) + df["left_cells_per_mm3"] = df.left_cell_count / df.left_volume_mm3 + df["right_cells_per_mm3"] = df.right_cell_count / df.right_volume_mm3 + return df + + +def combine_df_hemispheres(df): + """ + Combine left and right hemisphere data onto a single row + :param df: + :return: + """ + left = df[df["hemisphere"] == "left"] + right = df[df["hemisphere"] == "right"] + left = left.drop(["hemisphere"], axis=1) + right = right.drop(["hemisphere"], axis=1) + left.rename(columns={"cell_count": "left_cell_count"}, inplace=True) + right.rename(columns={"cell_count": "right_cell_count"}, inplace=True) + both = pd.merge(left, right, on="structure_name", how="outer") + both = both.fillna(0) + both["total_cells"] = both.left_cell_count + both.right_cell_count + both = both.sort_values("total_cells", ascending=False) + return both + + +def summarise_points( + raw_points, + transformed_points, + atlas, + volume_csv_path, + all_points_filename, + summary_filename, +): + points = [] + structures_with_points = set() + for idx, point in enumerate(transformed_points): + try: + structure_id = atlas.structure_from_coords(point) + structure = atlas.structures[structure_id]["name"] + hemisphere = atlas.hemisphere_from_coords(point, as_string=True) + points.append( + Point( + raw_points[idx], point, structure, structure_id, hemisphere + ) + ) + structures_with_points.add(structure) + except Exception: + continue + + logging.debug("Ensuring output directory exists") + ensure_directory_exists(Path(all_points_filename).parent) + create_all_cell_csv(points, all_points_filename) + + get_region_totals( + points, structures_with_points, volume_csv_path, summary_filename + ) + + return points + + +def create_all_cell_csv(points, all_points_filename): + df = pd.DataFrame( + columns=( + "coordinate_raw_axis_0", + "coordinate_raw_axis_1", + "coordinate_raw_axis_2", + "coordinate_atlas_axis_0", + "coordinate_atlas_axis_1", + "coordinate_atlas_axis_2", + "structure_name", + "hemisphere", + ) + ) + + temp_matrix = [[] for i in range(len(points))] + for i, point in enumerate(points): + temp_matrix[i].append(point.raw_coordinate[0]) + temp_matrix[i].append(point.raw_coordinate[1]) + temp_matrix[i].append(point.raw_coordinate[2]) + temp_matrix[i].append(point.atlas_coordinate[0]) + temp_matrix[i].append(point.atlas_coordinate[1]) + temp_matrix[i].append(point.atlas_coordinate[2]) + temp_matrix[i].append(point.structure) + temp_matrix[i].append(point.hemisphere) + + df = pd.DataFrame(temp_matrix, columns=df.columns, index=None) + df.to_csv(all_points_filename, index=False) + + +def get_region_totals( + points, structures_with_points, volume_csv_path, output_filename +): + structures_with_points = list(structures_with_points) + + point_numbers = pd.DataFrame( + columns=("structure_name", "hemisphere", "cell_count") + ) + for structure in structures_with_points: + for hemisphere in ("left", "right"): + n_points = len( + [ + point + for point in points + if point.structure == structure + and point.hemisphere == hemisphere + ] + ) + if n_points: + point_numbers = point_numbers.append( + { + "structure_name": structure, + "hemisphere": hemisphere, + "cell_count": n_points, + }, + ignore_index=True, + ) + sorted_point_numbers = point_numbers.sort_values( + by=["cell_count"], ascending=False + ) + + combined_hemispheres = combine_df_hemispheres(sorted_point_numbers) + df = calculate_densities(combined_hemispheres, volume_csv_path) + df = sanitise_df(df) + + df.to_csv(output_filename, index=False) + + +def transform_points_to_downsampled_space( + points: np.ndarray, + target_space: bgs.AnatomicalSpace, + source_space: bgs.AnatomicalSpace, + output_filename: Optional[os.PathLike] = None, +) -> np.ndarray: + """ + Parameters + ---------- + points : + Points in the original space. + target_space : + Target anatomical space. + source_space : + Source anatomical space of ``points``. + output_filename : + File to save downsampled points to. Points are saved as a HDF file + using pandas. + + Returns + ------- + downsampled_points + Points transformed to the downsampled space. + """ + points = source_space.map_points_to(target_space, points) + if output_filename is not None: + df = pd.DataFrame(points) + df.to_hdf(output_filename, key="df", mode="w") + return points + + +def transform_points_to_atlas_space( + points: np.ndarray, + source_space: bgs.AnatomicalSpace, + atlas: BrainGlobeAtlas, + deformation_field_paths: List[os.PathLike], + downsampled_space: bgs.AnatomicalSpace, + downsampled_points_path: Optional[os.PathLike] = None, + atlas_points_path: Optional[os.PathLike] = None, +) -> np.ndarray: + """ + Transform points to an atlas space. + + The points are first downsampled to the atlas resolution, and then + transformed to the atlas space. + """ + downsampled_points = transform_points_to_downsampled_space( + points, + downsampled_space, + source_space, + output_filename=downsampled_points_path, + ) + return transform_points_downsampled_to_atlas_space( + downsampled_points, + atlas, + deformation_field_paths, + output_filename=atlas_points_path, + ) + + +def transform_points_downsampled_to_atlas_space( + downsampled_points: np.ndarray, + atlas: BrainGlobeAtlas, + deformation_field_paths: List[os.PathLike], + output_filename: Optional[os.PathLike] = None, +) -> np.ndarray: + """ + Parameters + ---------- + downsampled_points : + Points already downsampled to the atlas resolution. + atlas : + Target atlas. + deformation_field_paths : + File paths to the deformation fields. + output_filename : + File to save transformed points to. Points are saved as a HDF file + using pandas. + + Returns + ------- + transformed_points + Points transformed to the atlas space. + """ + field_scales = [int(1000 / resolution) for resolution in atlas.resolution] + points: List[List] = [[], [], []] + for axis, deformation_field_path in enumerate(deformation_field_paths): + deformation_field = tifffile.imread(deformation_field_path) + for point in downsampled_points: + point = [int(round(p)) for p in point] + points[axis].append( + int( + round( + field_scales[axis] + * deformation_field[point[0], point[1], point[2]] + ) + ) + ) + + transformed_points = np.array(points).T + + if output_filename is not None: + df = pd.DataFrame(transformed_points) + df.to_hdf(output_filename, key="df", mode="w") + + return transformed_points + + +def run(args, cells, atlas, downsampled_space): + deformation_field_paths = [ + args.brainreg_paths.deformation_field_0, + args.brainreg_paths.deformation_field_1, + args.brainreg_paths.deformation_field_2, + ] + + cell_list = [] + for cell in cells: + cell_list.append([cell.z, cell.y, cell.x]) + cells = np.array(cell_list) + + run_analysis( + cells, + args.signal_planes_paths[0], + args.orientation, + args.voxel_sizes, + atlas, + deformation_field_paths, + downsampled_space, + args.paths.downsampled_points, + args.paths.atlas_points, + args.paths.brainrender_points, + args.paths.abc4d_points, + args.brainreg_paths.volume_csv_path, + args.paths.all_points_csv, + args.paths.summary_csv, + ) + + +def run_analysis( + cells, + signal_planes, + orientation, + voxel_sizes, + atlas, + deformation_field_paths, + downsampled_space, + downsampled_points_path, + atlas_points_path, + brainrender_points_path, + abc4d_points_path, + volume_csv_path, + all_points_csv_path, + summary_csv_path, +): + source_shape = tuple( + imio.get_size_image_from_file_paths(signal_planes).values() + ) + source_shape = (source_shape[2], source_shape[1], source_shape[0]) + + source_space = bgs.AnatomicalSpace( + orientation, + shape=source_shape, + resolution=[float(i) for i in voxel_sizes], + ) + + transformed_cells = transform_points_to_atlas_space( + cells, + source_space, + atlas, + deformation_field_paths, + downsampled_space, + downsampled_points_path=downsampled_points_path, + atlas_points_path=atlas_points_path, + ) + + logging.info("Summarising cell positions") + points = summarise_points( + cells, + transformed_cells, + atlas, + volume_csv_path, + all_points_csv_path, + summary_csv_path, + ) + logging.info("Exporting data") + export_points( + points, + transformed_cells, + atlas.resolution[0], + brainrender_points_path, + abc4d_points_path, + ) diff --git a/cellfinder/export/__init__.py b/cellfinder/export/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/cellfinder/export/abc4d.py b/cellfinder/export/abc4d.py new file mode 100644 index 00000000..ff24f526 --- /dev/null +++ b/cellfinder/export/abc4d.py @@ -0,0 +1,20 @@ +import logging + +import numpy as np + + +def export_points( + point_info, + resolution, + output_filename, +): + logging.info("Exporting to abc4d") + + point_arrays = [] + for point in point_info: + point.atlas_coordinate = point.atlas_coordinate * resolution + point_arrays.append( + np.append(point.atlas_coordinate, point.structure_id) + ) + + np.save(output_filename, np.vstack(point_arrays).astype(np.float64)) diff --git a/cellfinder/export/brainrender.py b/cellfinder/export/brainrender.py new file mode 100644 index 00000000..cb3421ba --- /dev/null +++ b/cellfinder/export/brainrender.py @@ -0,0 +1,12 @@ +import logging + +import numpy as np + + +def export_points( + points, + resolution, + output_filename, +): + logging.info("Exporting to brainrender") + np.save(output_filename, points * resolution) diff --git a/cellfinder/export/export.py b/cellfinder/export/export.py new file mode 100644 index 00000000..1701f8a5 --- /dev/null +++ b/cellfinder/export/export.py @@ -0,0 +1,9 @@ +from cellfinder.export.abc4d import export_points as abc4d_export +from cellfinder.export.brainrender import export_points as brainrender_export + + +def export_points( + point_info, points, resolution, brainrender_points_path, abc4d_points_path +): + brainrender_export(points, resolution, brainrender_points_path) + abc4d_export(point_info, resolution, abc4d_points_path) diff --git a/cellfinder/extract/__init__.py b/cellfinder/extract/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/cellfinder/extract/extract_cubes.py b/cellfinder/extract/extract_cubes.py new file mode 100644 index 00000000..54a0b8b3 --- /dev/null +++ b/cellfinder/extract/extract_cubes.py @@ -0,0 +1,492 @@ +""" +Cube extraction for CNN-based classification. + +Based on, and mostly copied from, +https://github.com/SainsburyWellcomeCentre/cell_count_analysis by +Charly Rousseau (https://github.com/crousseau). +""" + +import logging +import os +from collections import deque +from concurrent.futures import ProcessPoolExecutor +from datetime import datetime +from math import floor + +import numpy as np +from brainglobe_utils.cells.cells import group_cells_by_z +from brainglobe_utils.general.numerical import is_even +from brainglobe_utils.general.system import get_num_processes +from numpy.linalg.linalg import LinAlgError +from skimage import transform +from tifffile import tifffile +from tqdm import tqdm + +from cellfinder.tools import image_processing as img_tools +from cellfinder.tools import system + + +class StackSizeError(Exception): + pass + + +class Cube(object): + class CubeBoundaryError(Exception): + pass + + def __init__( + self, + cell, + channel, + stacks, + x_pix_um=1, + y_pix_um=1, + x_pix_um_network=1, + y_pix_um_network=1, + final_depth=20, + width=50, + height=50, + depth=20, + interpolation_order=0, + ): + self.cell = cell + self.channel = channel + self.stack = stacks[self.channel] + self.scale_cubes = False + self.scale_cubes_in_z = False + self.interpolation_order = interpolation_order + self.rescaling_factor_x = 1 + self.rescaling_factor_y = 1 + + if x_pix_um != x_pix_um_network: + self.rescaling_factor_x = float(x_pix_um_network) / float(x_pix_um) + self.scale_cubes = True + if y_pix_um != y_pix_um_network: + self.rescaling_factor_y = float(y_pix_um_network) / float(y_pix_um) + self.scale_cubes = True + + # This should be decided earlier + if depth != final_depth: + self.rescaling_factor_z = final_depth / depth + self.scale_cubes_in_z = True + + self.width = width + self.height = height + self.depth = depth + self.final_depth = depth + + self.empty = False + self.data = self.extract_cube(self.stack) + + def __str__(self): # TODO: 0 pad (when changing classification) + prefix = "pCell" + return "{}z{}y{}x{}Ch{}.tif".format( + prefix, self.z, self.y, self.x, self.channel + ) + + @property + def x(self): + return self.cell.x + + @property + def y(self): + return self.cell.y + + @property + def z(self): + return self.cell.z + + @property + def stack_x_max(self): + return self.stack.shape[1] + + @property + def stack_y_max(self): + return self.stack.shape[0] + + @property + def stack_z_max(self): + return self.stack.shape[2] + + def extract_cube(self, stack): + """ + + :param np.array stack: + :return: + """ + try: + self.check_boundaries() + except Cube.CubeBoundaryError: + return self.make_blank_data() + + half_width, half_height, x0, x1, y0, y1 = self.get_boundaries() + data = stack[y0:y1, x0:x1, :] + if data.ndim < 3: + logging.error( + "Error occurred during extraction of cube {}, " + "original shape: {}, dtype: {}".format( + self, data.shape, data.dtype + ) + ) + return self.make_blank_data() + + out = [] + # TODO: combine these scalings + for i in range(self.depth): + if self.scale_cubes: + try: + # To match classification 1um rescaling + inv_rescale_x = 1 / self.rescaling_factor_x + inv_rescale_y = 1 / self.rescaling_factor_y + plane = transform.rescale( + data[:, :, i], + scale=(inv_rescale_y, inv_rescale_x), + order=self.interpolation_order, + preserve_range=True, + multichannel=False, + mode="constant", + anti_aliasing=False, + ) + except LinAlgError as err: + logging.error( + f"Error occurred during rescale of cube {self}, " + f"original shape: {data[:, :, i].shape}, dtype: " + f"{data[:, :, i].dtype}; {err}." + ) + + return self.make_blank_data() + else: + plane = data[:, :, i] + + plane = self.adjust_size(plane) + + out.append(plane) + out = np.array(out, dtype=np.uint16) + + if self.scale_cubes_in_z: + try: + # To match classification cube scaling in z + # TODO: presumably this will have rounding errors + out = transform.rescale( + out, + scale=(self.rescaling_factor_z, 1, 1), + order=self.interpolation_order, + preserve_range=True, + multichannel=False, + mode="constant", + anti_aliasing=False, + ) + out = out.astype(np.uint16) + except LinAlgError as err: + logging.error( + f"Error occurred during z-rescale of cube {self}, " + f"from depth: {self.depth} to final depth " + f"{self.final_depth} ; {err}" + ) + print.error( + f"Error occurred during z-rescale of cube {self}, " + f"from depth: {self.depth} to final depth " + f"{self.final_depth} ; {err}" + ) + return self.make_blank_data() + return out + + def adjust_size(self, plane): + plane = self.crop_to_correct_size(plane) + plane = self.pad_to_correct_size(plane) + return plane + + def pad_to_correct_size(self, plane): + return img_tools.pad_center_2d( + plane, x_size=self.width, y_size=self.height + ) + + def crop_to_correct_size(self, plane): + return img_tools.crop_center_2d( + plane, crop_x=self.width, crop_y=self.height + ) + + def get_boundaries(self): + if self.scale_cubes: + half_width = int(round(self.width / 2 * self.rescaling_factor_x)) + half_height = int(round(self.height / 2 * self.rescaling_factor_y)) + else: + half_width = int(round(self.width / 2)) + half_height = int(round(self.height / 2)) + + x0 = int(self.x - half_width) + x1 = int(self.x + half_width) + y0 = int(self.y - half_height) + y1 = int(self.y + half_height) + return half_width, half_height, x0, x1, y0, y1 + + def make_blank_data(self): + self.empty = True + return np.zeros((self.depth, self.width, self.height), dtype=np.uint16) + + def check_boundaries(self): + out_bounds_message = ( + "Cell candidate (x:{}, y:{}, z:{}) too close to the edge of the" + " image for cube extraction." + ).format(self.x, self.y, self.z) + + if self.stack_z_max < self.depth: + error_msg = "Stack has {} planes but cube needs {}".format( + self.stack_z_max, self.depth + ) + logging.error(error_msg) + + raise Cube.CubeBoundaryError(error_msg) + boundaries = self.get_boundaries() + half_height, half_width, x0, x1, y0, y1 = boundaries + if x0 < 0 or y0 < 0: + logging.warning(out_bounds_message) + raise Cube.CubeBoundaryError(out_bounds_message) + + # WARNING: dimensions inverted (numpy y=dim0, x=dim1) + elif x1 > self.stack_x_max or y1 > self.stack_y_max: + logging.warning(out_bounds_message) + raise Cube.CubeBoundaryError(out_bounds_message) + + +def save_cubes( + cells, + planes_paths, + planes_to_read, + planes_shape, + voxel_sizes, + network_voxel_sizes, + num_planes_for_cube=20, + cube_width=50, + cube_height=50, + cube_depth=20, + thread_id=0, + output_dir="", + save_empty_cubes=False, +): + """ + + :param cells: + :param planes_paths: + :param planes_to_read: + :param planes_shape: + :param x_pix_um: + :param y_pix_um: + :param x_pix_um_network: + :param y_pix_um_network: + :param num_planes_for_cube: + :param cube_width: + :param cube_height: + :param cube_depth: + :param thread_id: + :param output_dir: + :param save_empty_cubes: + :return: + """ + channels = list(planes_paths.keys()) + stack_shape = planes_shape + (num_planes_for_cube,) + stacks = {} + planes_queues = {} + for ch in channels: + stacks[ch] = np.zeros(stack_shape, dtype=np.uint16) + planes_queues[ch] = deque(maxlen=num_planes_for_cube) + for plane_idx in tqdm(planes_to_read, desc="Thread: {}".format(thread_id)): + for ch in channels: + plane_path = planes_paths[ch][plane_idx] + planes_queues[ch].append(tifffile.imread(plane_path)) + if len(planes_queues[ch]) == num_planes_for_cube: + if is_even(num_planes_for_cube): + cell_z = int(plane_idx - num_planes_for_cube / 2 + 1) + else: + cell_z = int( + plane_idx - floor(num_planes_for_cube) / 2 + 1 + ) + + for j, plane in enumerate(planes_queues[ch]): + stacks[ch][:, :, j] = plane + + # ensures no cube_depth planes at the end + planes_queues[ch].popleft() + # required since we provide all cells + # TODO: if len(planes_queues[ch]) + # < num_planes_for_cube -1: break + for cell in cells[cell_z]: + cube = Cube( + cell, + ch, + stacks, + x_pix_um=voxel_sizes[2], + y_pix_um=voxel_sizes[1], + x_pix_um_network=network_voxel_sizes[2], + y_pix_um_network=network_voxel_sizes[1], + final_depth=cube_depth, + width=cube_width, + height=cube_height, + depth=num_planes_for_cube, + ) + if not cube.empty or (cube.empty and save_empty_cubes): + tifffile.imsave( + os.path.join(output_dir, str(cube)), cube.data + ) + + +def get_ram_requirement_per_process( + single_image_path, cube_depth, num_channels=2, copies=2 +): + """ + Calculates how much RAM is needed per CPU core for cube extraction. Used + later to set the number of CPU cores to be used. + + RAM requirement is currently: + image_size x n_cores x n_channels x cube_depth x copies + + :param single_image_path: A single 2D image, used to find the size. + :param num_channels: Number of channels to be extracted + :param cube_depth: Depth of the cube to be extracted (z-planes) + to use. + :param int copies: How many copies of the data are loaded at any time + :return int: memory requirement for one CPU core + """ + + logging.debug( + "Determining how much RAM is needed for each CPU for cube extraction" + ) + file_size = os.path.getsize(single_image_path) + total_mem_need = file_size * num_channels * cube_depth * copies + + logging.debug( + "File size: {:.2f} GB, " + "number of channels: {}, " + "cube depth: {}, " + "Therefore theoretically {:.2f} GB is needed per CPU core." + "".format( + (file_size / (1024**3)), + num_channels, + cube_depth, + (total_mem_need / (1024**3)), + ) + ) + + return total_mem_need + + +def main( + cells, + cubes_output_dir, + planes_paths, + cube_depth, + cube_width, + cube_height, + voxel_sizes, + network_voxel_sizes, + max_ram, + n_free_cpus=4, + save_empty_cubes=False, +): + start_time = datetime.now() + + if voxel_sizes[0] != network_voxel_sizes[0]: + plane_scaling_factor = float(network_voxel_sizes[0]) / float( + voxel_sizes[0] + ) + num_planes_needed_for_cube = round(cube_depth * plane_scaling_factor) + else: + num_planes_needed_for_cube = cube_depth + + if num_planes_needed_for_cube > len(planes_paths[0]): + raise StackSizeError( + "The number of planes provided is not sufficient " + "for any cubes to be extracted. Please check the " + "input data" + ) + + first_plane = tifffile.imread(list(planes_paths.values())[0][0]) + + planes_shape = first_plane.shape + brain_depth = len(list(planes_paths.values())[0]) + + # TODO: use to assert all centre planes processed + center_planes = sorted(list(set([cell.z for cell in cells]))) + + # REFACTOR: rename (clashes with different meaning of planes_to_read below) + planes_to_read = np.zeros(brain_depth, dtype=bool) + + if is_even(num_planes_needed_for_cube): + half_nz = num_planes_needed_for_cube // 2 + # WARNING: not centered because even + for p in center_planes: + planes_to_read[p - half_nz : p + half_nz] = 1 + else: + half_nz = num_planes_needed_for_cube // 2 + # centered + for p in center_planes: + planes_to_read[p - half_nz : p + half_nz + 1] = 1 + + planes_to_read = np.where(planes_to_read)[0] + + if not planes_to_read.size: + logging.error( + f"No planes found, you need at the very least " + f"{num_planes_needed_for_cube} " + f"planes to proceed (i.e. cube z size)" + f"Brain z dimension is {brain_depth}.", + stack_info=True, + ) + raise ValueError( + f"No planes found, you need at the very least " + f"{num_planes_needed_for_cube} " + f"planes to proceed (i.e. cube z size)" + f"Brain z dimension is {brain_depth}." + ) + # TODO: check if needs to flip args.cube_width and args.cube_height + cells_groups = group_cells_by_z(cells) + + # copies=2 is set because at all times there is a plane queue (deque) + # and an array passed to `Cube` + ram_per_process = get_ram_requirement_per_process( + planes_paths[0][0], + num_planes_needed_for_cube, + copies=2, + ) + n_processes = get_num_processes( + min_free_cpu_cores=n_free_cpus, + ram_needed_per_process=ram_per_process, + n_max_processes=len(planes_to_read), + fraction_free_ram=0.2, + max_ram_usage=system.memory_in_bytes(max_ram, "GB"), + ) + # TODO: don't need to extract cubes from all channels if + # n_signal_channels>1 + with ProcessPoolExecutor(max_workers=n_processes) as executor: + n_planes_per_chunk = len(planes_to_read) // n_processes + for i in range(n_processes): + start_idx = i * n_planes_per_chunk + end_idx = ( + start_idx + n_planes_per_chunk + num_planes_needed_for_cube - 1 + ) + if end_idx > planes_to_read[-1]: + end_idx = None + sub_planes_to_read = planes_to_read[start_idx:end_idx] + + executor.submit( + save_cubes, + cells_groups, + planes_paths, + sub_planes_to_read, + planes_shape, + voxel_sizes, + network_voxel_sizes, + num_planes_for_cube=num_planes_needed_for_cube, + cube_width=cube_width, + cube_height=cube_height, + cube_depth=cube_depth, + thread_id=i, + output_dir=cubes_output_dir, + save_empty_cubes=save_empty_cubes, + ) + + total_cubes = system.get_number_of_files_in_dir(cubes_output_dir) + time_taken = datetime.now() - start_time + logging.info( + "All cubes ({}) extracted in: {}".format(total_cubes, time_taken) + ) diff --git a/cellfinder/figures/__init__.py b/cellfinder/figures/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/cellfinder/figures/figures.py b/cellfinder/figures/figures.py new file mode 100644 index 00000000..59380542 --- /dev/null +++ b/cellfinder/figures/figures.py @@ -0,0 +1,16 @@ +import logging + +from cellfinder.figures import heatmap + + +def run(args, atlas, downsampled_shape): + logging.info("Generating heatmap") + heatmap.run( + args.paths.downsampled_points, + atlas, + downsampled_shape, + args.brainreg_paths.registered_atlas, + args.paths.heatmap, + smoothing=args.heatmap_smooth, + mask=args.mask_figures, + ) diff --git a/cellfinder/figures/heatmap.py b/cellfinder/figures/heatmap.py new file mode 100644 index 00000000..18af4a09 --- /dev/null +++ b/cellfinder/figures/heatmap.py @@ -0,0 +1,62 @@ +import logging +from pathlib import Path + +import imio +import numpy as np +import pandas as pd +import tifffile +from brainglobe_utils.general.system import ensure_directory_exists +from brainglobe_utils.image.masking import mask_image_threshold +from brainglobe_utils.image.scale import scale_and_convert_to_16_bits +from skimage.filters import gaussian + + +def get_bins(image_size, bin_sizes): + """ + Given an image size, and bin size, return a list of the bin boundaries + :param image_size: Size of the final image (tuple/list) + :param bin_sizes: Bin sizes corresponding to the dimensions of + "image_size" (tuple/list) + :return: List of arrays of bin boundaries + """ + bins = [] + for dim in range(0, len(image_size)): + bins.append(np.arange(0, image_size[dim] + 1, bin_sizes[dim])) + return bins + + +def run( + downsampled_points, + atlas, + downsampled_shape, + registered_atlas_path, + output_filename, + smoothing=None, + mask=True, +): + points = pd.read_hdf(downsampled_points).values + + bins = get_bins(downsampled_shape, (1, 1, 1)) + heatmap_array, _ = np.histogramdd(points, bins=bins) + heatmap_array = heatmap_array.astype(np.uint16) + + if smoothing is not None: + logging.debug("Smoothing heatmap") + # assume isotropic atlas + smoothing = int(round(smoothing / atlas.resolution[0])) + heatmap_array = gaussian(heatmap_array, sigma=smoothing) + + if mask: + logging.debug("Masking image based on registered atlas") + atlas = tifffile.imread(registered_atlas_path) + heatmap_array = mask_image_threshold(heatmap_array, atlas) + del atlas + + logging.debug("Saving heatmap") + heatmap_array = scale_and_convert_to_16_bits(heatmap_array) + + logging.debug("Ensuring output directory exists") + ensure_directory_exists(Path(output_filename).parent) + + logging.debug("Saving heatmap image") + imio.to_tiff(heatmap_array, output_filename) diff --git a/cellfinder/main.py b/cellfinder/main.py new file mode 100644 index 00000000..42046e39 --- /dev/null +++ b/cellfinder/main.py @@ -0,0 +1,232 @@ +""" +main +=============== + +Runs each part of the cellfinder pipeline in turn. + +N.B imports are within functions to prevent tensorflow being imported before +it's warnings are silenced +""" + +import logging +import os +from datetime import datetime + +import bg_space as bgs +import tifffile +from brainglobe_utils.cells.cells import MissingCellsError +from brainglobe_utils.general.system import ensure_directory_exists +from brainglobe_utils.IO.cells import get_cells, save_cells +from cellfinder_core.main import suppress_tf_logging, tf_suppress_log_messages + +BRAINREG_PRE_PROCESSING_ARGS = None + + +def get_downsampled_space(atlas, downsampled_image_path): + target_shape = tifffile.imread(downsampled_image_path).shape + downsampled_space = bgs.AnatomicalSpace( + atlas.metadata["orientation"], + shape=target_shape, + resolution=atlas.resolution, + ) + return downsampled_space + + +def cells_exist(points_file): + try: + get_cells(points_file, cells_only=True) + return True + except MissingCellsError: + return False + + +def main(): + suppress_tf_logging(tf_suppress_log_messages) + from brainreg.main import main as register + + from cellfinder.tools import prep + + start_time = datetime.now() + args, arg_groups, what_to_run, atlas = prep.prep_cellfinder_general() + + if what_to_run.register: + # TODO: add register_part_brain option + logging.info("Registering to atlas") + args, additional_images_downsample = prep.prep_registration(args) + register( + args.atlas, + args.orientation, + args.target_brain_path, + args.brainreg_paths, + args.voxel_sizes, + arg_groups["NiftyReg registration backend options"], + BRAINREG_PRE_PROCESSING_ARGS, + sort_input_file=args.sort_input_file, + n_free_cpus=args.n_free_cpus, + additional_images_downsample=additional_images_downsample, + backend=args.backend, + debug=args.debug, + ) + + else: + logging.info("Skipping registration") + + if len(args.signal_planes_paths) > 1: + base_directory = args.output_dir + + for idx, signal_paths in enumerate(args.signal_planes_paths): + channel = args.signal_ch_ids[idx] + logging.info("Processing channel: " + str(channel)) + channel_directory = os.path.join( + base_directory, "channel_" + str(channel) + ) + if not os.path.exists(channel_directory): + os.makedirs(channel_directory) + + # prep signal channel specific args + args.signal_planes_paths[0] = signal_paths + # TODO: don't overwrite args.output_dir - use Paths instead + args.output_dir = channel_directory + args.signal_channel = channel + # Run for each channel + run_all(args, what_to_run, atlas) + + else: + args.signal_channel = args.signal_ch_ids[0] + run_all(args, what_to_run, atlas) + logging.info( + "Finished. Total time taken: {}".format(datetime.now() - start_time) + ) + + +def run_all(args, what_to_run, atlas): + from cellfinder_core.classify import classify + from cellfinder_core.detect import detect + from cellfinder_core.tools import prep + from cellfinder_core.tools.IO import read_with_dask + + from cellfinder.analyse import analyse + from cellfinder.figures import figures + from cellfinder.tools.prep import ( + prep_candidate_detection, + prep_channel_specific_general, + ) + + points = None + signal_array = None + args, what_to_run = prep_channel_specific_general(args, what_to_run) + + if what_to_run.detect: + logging.info("Detecting cell candidates") + args = prep_candidate_detection(args) + signal_array = read_with_dask( + args.signal_planes_paths[args.signal_channel] + ) + + points = detect.main( + signal_array, + args.start_plane, + args.end_plane, + args.voxel_sizes, + args.soma_diameter, + args.max_cluster_size, + args.ball_xy_size, + args.ball_z_size, + args.ball_overlap_fraction, + args.soma_spread_factor, + args.n_free_cpus, + args.log_sigma_size, + args.n_sds_above_mean_thresh, + save_planes=args.save_planes, + plane_directory=args.plane_directory, + ) + ensure_directory_exists(args.paths.points_directory) + + save_cells( + points, + args.paths.detected_points, + save_csv=args.save_csv, + artifact_keep=args.artifact_keep, + ) + + else: + logging.info("Skipping cell detection") + points = get_cells(args.paths.detected_points) + + if what_to_run.classify: + model_weights = prep.prep_classification( + args.trained_model, + args.model_weights, + args.install_path, + args.model, + args.n_free_cpus, + ) + if what_to_run.classify: + if points is None: + points = get_cells(args.paths.detected_points) + if signal_array is None: + signal_array = read_with_dask( + args.signal_planes_paths[args.signal_channel] + ) + logging.info("Running cell classification") + background_array = read_with_dask(args.background_planes_path[0]) + + points = classify.main( + points, + signal_array, + background_array, + args.n_free_cpus, + args.voxel_sizes, + args.network_voxel_sizes, + args.batch_size, + args.cube_height, + args.cube_width, + args.cube_depth, + args.trained_model, + model_weights, + args.network_depth, + ) + save_cells( + points, + args.paths.classified_points, + save_csv=args.save_csv, + ) + + what_to_run.cells_exist = cells_exist(args.paths.classified_points) + + else: + logging.info("No cells were detected, skipping classification.") + + else: + logging.info("Skipping cell classification") + + what_to_run.update_if_cells_required() + + if what_to_run.analyse or what_to_run.figures: + downsampled_space = get_downsampled_space( + atlas, args.brainreg_paths.boundaries_file_path + ) + + if what_to_run.analyse: + points = get_cells(args.paths.classified_points, cells_only=True) + if len(points) == 0: + logging.info("No cells detected, skipping cell position analysis") + else: + logging.info("Analysing cell positions") + analyse.run(args, points, atlas, downsampled_space) + else: + logging.info("Skipping cell position analysis") + + if what_to_run.figures: + points = get_cells(args.paths.classified_points, cells_only=True) + if len(points) == 0: + logging.info("No cells detected, skipping") + else: + logging.info("Generating figures") + figures.run(args, atlas, downsampled_space.shape) + else: + logging.info("Skipping figure generation") + + +if __name__ == "__main__": + main() diff --git a/cellfinder/tools/__init__.py b/cellfinder/tools/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/cellfinder/tools/image_processing.py b/cellfinder/tools/image_processing.py new file mode 100644 index 00000000..742220d6 --- /dev/null +++ b/cellfinder/tools/image_processing.py @@ -0,0 +1,87 @@ +import numpy as np +from brainglobe_utils.general.numerical import is_even + + +def crop_center_2d(img, crop_x=None, crop_y=None): + """ + Crops the centre of a 2D image, and returns a smaller array. If the desired + dimension is larger than the original dimension, nothing is changed. + :param img: 2D input image + :param crop_x: New length in x (default: None, which does nothing) + :param crop_y: New length in y (default: None, which does nothing) + :return: New, smaller array + """ + + y, x = img.shape + + # TODO: simplify + if crop_x is not None: + if crop_x >= x: + start_x = 0 + crop_x = x + else: + start_x = x // 2 - (crop_x // 2) + else: + start_x = 0 + crop_x = x + + if crop_y is not None: + if crop_y >= y: + start_y = 0 + crop_y = y + else: + start_y = y // 2 - (crop_y // 2) + else: + start_y = 0 + crop_y = y + + return img[start_y : start_y + crop_y, start_x : start_x + crop_x] + + +def pad_center_2d(img, x_size=None, y_size=None, pad_mode="edge"): + """ + Pads the edges of a 2D image, and returns a larger image. If the desired + dimension is smaller than the original dimension, nothing is changed. + :param img: 2D input image + :param x_size: New length in x (default: None, which does nothing) + :param y_size: New length in y (default: None, which does nothing) + :return: New, larger array + """ + + y, x = img.shape + + # TODO: simplify + + if x_size is None: + x_pad = 0 + elif x_size <= x: + x_pad = 0 + else: + x_pad = x_size - x + + if y_size is None: + y_pad = 0 + elif y_size <= y: + y_pad = 0 + else: + y_pad = y_size - y + + if x_pad > 0: + if is_even(x_pad): + x_front = x_back = int(x_pad / 2) + else: + x_front = int(x_pad // 2) + x_back = int(x_front + 1) + else: + x_front = x_back = 0 + + if y_pad > 0: + if is_even(y_pad): + y_front = y_back = int(y_pad / 2) + else: + y_front = int(y_pad // 2) + y_back = int(y_front + 1) + else: + y_front = y_back = 0 + + return np.pad(img, ((y_front, y_back), (x_front, x_back)), pad_mode) diff --git a/cellfinder/tools/parser.py b/cellfinder/tools/parser.py new file mode 100644 index 00000000..e44f9162 --- /dev/null +++ b/cellfinder/tools/parser.py @@ -0,0 +1,460 @@ +""" +parser +======== +All the various arguments that may be needed by the various submodules. +Defined together so they can also be called by any other entry points. +""" + + +from argparse import ( + ArgumentDefaultsHelpFormatter, + ArgumentParser, + ArgumentTypeError, +) + +from brainglobe_utils.general.numerical import ( + check_positive_float, + check_positive_int, +) +from brainreg.cli import atlas_parse, geometry_parser, niftyreg_parse +from brainreg.cli import backend_parse as brainreg_backend_parse +from cellfinder_core.download.cli import ( + download_directory_parser, + model_parser, +) +from cellfinder_core.tools.source_files import source_custom_config_cellfinder + +from cellfinder import __version__ + +# TODO: Gradually move all paths as strings to Path objects + +models = { + "18": "18-layer", + "34": "34-layer", + "50": "50-layer", + "101": "101-layer", + "152": "152-layer", +} + + +def valid_model_depth(depth): + """ + Ensures a correct existing_model is chosen + :param value: Input value + :param models: Dict of allowed models + :return: Input value, if it corresponds to a valid existing_model + """ + + if depth in models.keys(): + return depth + else: + raise ArgumentTypeError( + f"Model depth: {depth} is not valid. Please " + f"choose one of: {list(models.keys())}" + ) + + +def cellfinder_parser(): + parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter) + parser = main_parse(parser) + parser = config_parse(parser) + parser = pixel_parser(parser) + parser = run_parse(parser) + parser = io_parse(parser) + parser = cell_detect_parse(parser) + parser = classification_parse(parser) + parser = cube_extract_parse(parser) + parser = misc_parse(parser) + parser = model_parser(parser) + parser = figures_parse(parser) + parser = download_directory_parser(parser) + + # brainreg options + parser = atlas_parse(parser) + parser = geometry_parser(parser) + parser = brainreg_backend_parse(parser) + # This needs to be abstracted away into brainreg for multiple backends + parser = niftyreg_parse(parser) + + return parser + + +def main_parse(parser): + main_parser = parser.add_argument_group("General options") + + main_parser.add_argument( + "-s", + "--signal-planes-paths", + dest="signal_planes_paths", + type=str, + nargs="+", + required=True, + help="Path to the directory of the signal files. Can also be a text" + "file pointing to the files.", + ) + main_parser.add_argument( + "-b", + "--background-planes-path", + dest="background_planes_path", + type=str, + nargs=1, + required=True, + help="Path to the directory of the background files. Can also be a " + "text file pointing to the files.", + ) + main_parser.add_argument( + "-o", + "--output-dir", + dest="output_dir", + type=str, + required=True, + help="Output directory for all intermediate and final results.", + ) + main_parser.add_argument( + "--signal-channel-ids", + dest="signal_ch_ids", + type=check_positive_int, + nargs="+", + help="Channel ID numbers, in the same order as 'signal-planes-paths'." + " Will default to '0, 1, 2' etc, but maybe useful to specify.", + ) + main_parser.add_argument( + "--background-channel-id", + dest="background_ch_id", + type=check_positive_int, + help="Channel ID number, corresponding to 'background-planes-path'.", + ) + main_parser.add_argument( + "--version", + action="version", + version="%(prog)s {version}".format(version=__version__), + ) + return parser + + +def pixel_parser(parser): + # TODO: separate the two groups. Image pixel sizes are needed in lots of + # places that the network pixel sizes are not + pixel_opt_parser = parser.add_argument_group( + "Options to define pixel sizes of raw data" + ) + pixel_opt_parser.add_argument( + "-v", + "--voxel-sizes", + dest="voxel_sizes", + required=True, + nargs="+", + help="Voxel sizes in microns, in the order of data orientation. " + "e.g. '5 2 2'", + ) + pixel_opt_parser.add_argument( + "--network-voxel-sizes", + dest="network_voxel_sizes", + nargs="+", + default=[5, 1, 1], + help="Voxel sizes in microns that the machine learning network was " + "trained on, in the order of data orientation. e.g. '5 2 2'." + "Set this to adjust the pixel sizes of the extracted cubes", + ) + return parser + + +def run_parse(parser): + run_parser = parser.add_argument_group( + "Options to disable part of cellfinder" + ) + run_parser.add_argument( + "--no-detection", + dest="no_detection", + action="store_true", + help="Dont run cell candidate detection", + ) + + run_parser.add_argument( + "--no-classification", + dest="no_classification", + action="store_true", + help="Do not run cell classification", + ) + run_parser.add_argument( + "--no-register", + dest="no_register", + action="store_true", + help="Do not perform registration", + ) + run_parser.add_argument( + "--no-analyse", + dest="no_analyse", + action="store_true", + help="Do not analyse and export cell positions", + ) + run_parser.add_argument( + "--no-figures", + dest="no_figures", + action="store_true", + help="Do not create figures (e.g. heatmap)", + ) + + return parser + + +def io_parse(parser): + io_parser = parser.add_argument_group("Input & output options") + io_parser.add_argument( + "--start-plane", + dest="start_plane", + type=check_positive_int, + default=0, + help="The first plane to process in the Z dimension.", + ) + io_parser.add_argument( + "--end-plane", + dest="end_plane", + type=int, + default=-1, + help="The last plane to process in the Z dimension.", + ) + return parser + + +def cell_detect_parse(parser): + # TODO: improve the help on these files + cell_detect_parser = parser.add_argument_group( + "Detection options", description="Cell detection options" + ) + cell_detect_parser.add_argument( + "--save-planes", + dest="save_planes", + action="store_true", + help="Whether to save the individual planes after " + "processing and thresholding. Useful for debugging.", + ) + + cell_detect_parser.add_argument( + "--outlier-keep", + dest="outlier_keep", + action="store_true", + help="Dont remove putative cells that fall outside initial clusters", + ) + + cell_detect_parser.add_argument( + "--artifact-keep", + dest="artifact_keep", + action="store_true", + help="Save artifacts into the initial xml file", + ) + + cell_detect_parser.add_argument( + "--max-cluster-size", + dest="max_cluster_size", + type=check_positive_int, + default=100000, + help="Largest putative cell cluster (in cubic um) where " + "splitting should be attempted", + ) + + cell_detect_parser.add_argument( + "--soma-diameter", + dest="soma_diameter", + type=check_positive_float, + default=16, + help="The expected soma size in um in the x/y dimensions", + ) + + cell_detect_parser.add_argument( + "--ball-xy-size", + dest="ball_xy_size", + type=check_positive_int, + default=6, + help="The size in um of the ball used " + "for the morphological filter in the x/y dimensions", + ) + cell_detect_parser.add_argument( + "--ball-z-size", + dest="ball_z_size", + type=check_positive_int, + default=15, + help="The size in um of the ball used " + "for the morphological filter in the z dimension", + ) + cell_detect_parser.add_argument( + "--ball-overlap-fraction", + dest="ball_overlap_fraction", + type=check_positive_float, + default=0.6, + help="The fraction of the ball that has to cover thresholded pixels " + "for the centre pixel to be considered a nucleus pixel", + ) + + cell_detect_parser.add_argument( + "--log-sigma-size", + dest="log_sigma_size", + type=check_positive_float, + default=0.2, + help="The filter size used in the Laplacian of Gaussian filter to " + "enhance the cell intensities. Given as a fraction of the " + "soma-diameter.", + ) + cell_detect_parser.add_argument( + "--threshold", + dest="n_sds_above_mean_thresh", + type=check_positive_float, + default=10, + help="The cell threshold, in multiples of the standard deviation" + "above the mean", + ) + cell_detect_parser.add_argument( + "--soma-spread-factor", + dest="soma_spread_factor", + type=check_positive_float, + default=1.4, + help="Soma size spread factor (for splitting up cell clusters)", + ) + + return parser + + +def classification_parse(parser): + classification_parser = parser.add_argument_group( + "Cell classification options" + ) + classification_parser.add_argument( + "--trained-model", + dest="trained_model", + type=str, + help="Path to the trained model", + ) + classification_parser.add_argument( + "--model-weights", + dest="model_weights", + type=str, + help="Path to existing model weights", + ) + classification_parser.add_argument( + "--network-depth", + dest="network_depth", + type=valid_model_depth, + default="50", + help="Resnet depth (based on He et al. (2015)", + ) + classification_parser.add_argument( + "--batch-size", + dest="batch_size", + type=check_positive_int, + default=32, + help="Batch size for classification. Can be adjusted depending on " + "GPU memory.", + ) + return parser + + +def cube_extract_parse(parser): + cube_extract_parser = parser.add_argument_group("Cube extraction options") + cube_extract_parser.add_argument( + "--cube-width", + dest="cube_width", + type=check_positive_int, + default=50, + help="The width of the cubes to extract (must be even)", + ) + cube_extract_parser.add_argument( + "--cube-height", + dest="cube_height", + type=check_positive_int, + default=50, + help="The height of the cubes to extract (must be even)", + ) + cube_extract_parser.add_argument( + "--cube-depth", + dest="cube_depth", + type=check_positive_int, + default=20, + help="The depth (z) of the cubes to extract", + ) + cube_extract_parser.add_argument( + "--save-empty-cubes", + dest="save_empty_cubes", + action="store_true", + help="If a cube cannot be extracted (e.g. to close to the edge of" + "the image), save an empty cube instead. Useful to keep track" + "of all cell candidates.", + ) + return parser + + +def config_parse(parser): + config_opt_parser = parser.add_argument_group("Config options") + config_opt_parser.add_argument( + "--config", + dest="registration_config", + type=str, + default=source_custom_config_cellfinder(), + help="To supply your own, custom configuration file.", + ) + + return parser + + +def figures_parse(parser): + figure_parser = parser.add_argument_group( + "Figure generation specific parameters" + ) + figure_parser.add_argument( + "--heatmap-smoothing", + dest="heatmap_smooth", + type=check_positive_float, + default=100, + help="Gaussian smoothing sigma, in um.", + ) + figure_parser.add_argument( + "--no-mask-figs", + dest="mask_figures", + action="store_false", + help="Don't mask the figures (removing any areas outside the brain," + "from e.g. smoothing)", + ) + return parser + + +def misc_parse(parser): + misc_parser = parser.add_argument_group("Misc options") + misc_parser.add_argument( + "--n-free-cpus", + dest="n_free_cpus", + type=check_positive_int, + default=2, + help="The number of CPU cores on the machine to leave " + "unused by the program to spare resources.", + ) + misc_parser.add_argument( + "--max-ram", + dest="max_ram", + type=check_positive_float, + default=None, + help="Maximum amount of RAM to use (in GB) - not currently fully " + "implemented for all parts of cellfinder", + ) + misc_parser.add_argument( + "--save-csv", + dest="save_csv", + action="store_true", + help="Save .csv files of cell locations (in addition to xml)." + "Useful for importing into other software.", + ) + misc_parser.add_argument( + "--debug", + dest="debug", + action="store_true", + help="Debug mode. Will increase verbosity of logging and save all " + "intermediate files for diagnosis of software issues.", + ) + misc_parser.add_argument( + "--sort-input-file", + dest="sort_input_file", + action="store_true", + help="If set to true, the input text file will be sorted using " + "natural sorting. This means that the file paths will be " + "sorted as would be expected by a human and " + "not purely alphabetically", + ) + return parser diff --git a/cellfinder/tools/prep.py b/cellfinder/tools/prep.py new file mode 100644 index 00000000..f52b5368 --- /dev/null +++ b/cellfinder/tools/prep.py @@ -0,0 +1,331 @@ +""" +prep +================== +Functions to prepare files and directories needed for other functions +""" + + +import json +import logging +import os +from argparse import Namespace +from pathlib import PurePath + +from bg_atlasapi import BrainGlobeAtlas +from brainglobe_utils.general.exceptions import CommandLineInputError +from brainglobe_utils.general.system import ensure_directory_exists +from brainreg.paths import Paths as BrainRegPaths +from fancylog import fancylog + +import cellfinder as program_for_log +import cellfinder.tools.parser as parser +from cellfinder.tools import system, tools +from cellfinder.tools.parser import cellfinder_parser + + +def get_arg_groups(args, parser): + arg_groups = {} + for group in parser._action_groups: + group_dict = { + a.dest: getattr(args, a.dest, None) for a in group._group_actions + } + arg_groups[group.title] = Namespace(**group_dict) + + return arg_groups + + +def check_input_arg_existance(args): + """ + Does a simple check to ensure that input files/paths exist. Prevents a typo + from causing cellfinder to only run partway. Doesn't check for validity + etc, just existance. + :param args: Cellfinder input arguments + """ + check_list = [args.background_planes_path[0]] + check_list = check_list + args.signal_planes_paths + + for path in check_list: + if path is not None: + system.catch_input_file_error(path) + + +class Paths: + """ + A single class to hold all file paths that cellfinder may need. Any paths + prefixed with "tmp__" refer to internal intermediate steps, and will be + deleted if "--debug" is not used. + """ + + def __init__(self, output_dir): + self.output_dir = output_dir + self.registration_output_folder = os.path.join( + self.output_dir, "registration" + ) + self.metadata_path = os.path.join(self.output_dir, "cellfinder.json") + self.registration_metadata_path = os.path.join( + self.registration_output_folder, "brainreg.json" + ) + + def make_channel_specific_paths(self): + self.points_directory = os.path.join(self.output_dir, "points") + self.detected_points = os.path.join(self.points_directory, "cells.xml") + self.classified_points = os.path.join( + self.points_directory, "cell_classification.xml" + ) + self.downsampled_points = os.path.join( + self.points_directory, "downsampled.points" + ) + self.atlas_points = os.path.join(self.points_directory, "atlas.points") + self.brainrender_points = os.path.join( + self.points_directory, "points.npy" + ) + self.abc4d_points = os.path.join(self.points_directory, "abc4d.npy") + + self.tmp__cubes_output_dir = os.path.join(self.output_dir, "cubes") + + self.figures_directory = os.path.join(self.output_dir, "figures") + self.heatmap = os.path.join(self.figures_directory, "heatmap.tiff") + + self.analysis_directory = os.path.join(self.output_dir, "analysis") + self.summary_csv = os.path.join(self.analysis_directory, "summary.csv") + self.all_points_csv = os.path.join( + self.analysis_directory, "all_points.csv" + ) + + +def serialise(obj): + if isinstance(obj, PurePath): + return str(obj) + else: + return obj.__dict__ + + +def log_metadata(file_path, args): + with open(file_path, "w") as f: + json.dump(args, f, default=serialise) + + +def prep_cellfinder_general(): + args = parser.cellfinder_parser().parse_args() + arg_groups = get_arg_groups(args, cellfinder_parser()) + + check_input_arg_existance(args) + + if not os.path.exists(args.output_dir): + os.makedirs(args.output_dir) + + args.paths = Paths(args.output_dir) + + fancylog.start_logging( + args.output_dir, + program_for_log, + variables=[args, args.paths], + verbose=args.debug, + log_header="CELLFINDER LOG", + multiprocessing_aware=True, + ) + + log_metadata(args.paths.metadata_path, args) + + what_to_run = CalcWhatToRun(args) + args.signal_ch_ids, args.background_ch_id = check_and_return_ch_ids( + args.signal_ch_ids, args.background_ch_id, args.signal_planes_paths + ) + args.brainreg_paths = BrainRegPaths(args.paths.registration_output_folder) + atlas = BrainGlobeAtlas(args.atlas) + return args, arg_groups, what_to_run, atlas + + +def check_and_return_ch_ids(signal_ids, background_id, signal_channel_list): + """ + If channel IDs are provided (via CLI), then they are checked for + suitability (i.e. they are unique). + If channel IDs are not given, then unique IDs will be generated + + Assumes only 1 background channel (for registration) + + :param list signal_ids: List of ID ints, or None. + :param int background_id: ID int, or None. + :param list signal_channel_list: Input files + :return: list of signal channel IDs, and background channel ID + """ + + # TODO: make this more general, so it gives informative error messages + # when called from cellfinder.extract.cli + + num_signal_channels = len(signal_channel_list) + + if signal_ids is None: + if background_id is None: + signal_ids = list(range(num_signal_channels)) + background_id = num_signal_channels # max(signal_ids) + 1 + pass + else: + signal_start = background_id + 1 + signal_end = signal_start + num_signal_channels + signal_ids = list(range(signal_start, signal_end)) + pass + else: + check_correct_number_signal_channels(signal_ids, num_signal_channels) + check_signal_overlap(signal_ids) + if background_id is None: + background_id = max(signal_ids) + 1 + pass + else: + # N.B. check_id_overlap needs bg_ch to be iterable (e.g. a list) + check_sig_bg_id_overlap(signal_ids, [background_id]) + return signal_ids, background_id + + +def check_correct_number_signal_channels(signal_ids, num_signal_channels): + num_signal_ids = len(signal_ids) + if num_signal_channels != num_signal_ids: + logging.error( + "Number of signal channel IDs ({}) does not match the number of " + "signal channels ({})".format(num_signal_ids, num_signal_channels) + ) + + raise CommandLineInputError( + "Number of signal channel IDs ({}) does not match the number of " + "signal channels ({})".format(num_signal_ids, num_signal_channels) + ) + + +def check_signal_overlap(signal_ids): + signal_unique, repeated_signal_ch = tools.check_unique_list(signal_ids) + if not signal_unique: + logging.error( + "Non-unique values for '--signal-channel-ids' ({}) given. ID:" + " {} given more than once.".format(signal_ids, repeated_signal_ch) + ) + raise CommandLineInputError( + "Non-unique values for '--signal-channel-ids' ({}) given. ID:" + " {} given more than once.".format(signal_ids, repeated_signal_ch) + ) + + +def check_sig_bg_id_overlap(signal_ids, background_id): + common_id_result, intersection = tools.common_member( + signal_ids, background_id + ) + + if common_id_result: + logging.error( + "Non-unique values for '--signal-channel-ids' ({}) and for " + "'--background-channel-id' ({}) given. ID: {} was given in" + " both.".format(signal_ids, background_id, intersection) + ) + raise CommandLineInputError( + "Non-unique values for '--signal-channel-ids' ({}) and for " + "'--background-channel-id' ({}) given. ID: {} was given in" + " both.".format(signal_ids, background_id, intersection) + ) + + +class CalcWhatToRun: + """ + Class to (hopefully) simplify what should and shouldn't be run + """ + + def __init__(self, args): + self.detect = True + self.classify = True + self.register = True + self.analyse = True + self.figures = True + self.candidates_exist = True + self.cells_exist = True + + self.atlas_image = os.path.join( + args.paths.registration_output_folder, "registered_atlas.tiff" + ) + # order is important + self.cli_options(args) + self.existence() + + def update(self, args): + self.cli_options(args) + self.existence() + self.channel_specific_update(args) + + def cli_options(self, args): + self.detect = not args.no_detection + self.classify = not args.no_classification + self.register = not args.no_register + self.analyse = not args.no_analyse + self.figures = not args.no_figures + + def existence(self): + if os.path.exists(self.atlas_image): + logging.warning( + "Registered atlas exists, assuming " "already run. Skipping." + ) + self.register = False + + def channel_specific_update(self, args): + if os.path.exists(args.paths.detected_points): + logging.warning( + "Initial detection file exists (cells.xml), " + "assuming already run. Skipping." + ) + self.detect = False + + if os.path.exists(args.paths.classified_points): + logging.warning( + "Cell classification file " + "(cell_classification.xml)" + " exists, assuming already run. Skipping cell detection, " + "and classification" + ) + self.classify = False + self.detect = False + + if not os.path.exists(self.atlas_image): + self.analyse = False + self.figures = False + + if os.path.exists(args.paths.summary_csv): + self.analyse = False + + if os.path.exists(args.paths.heatmap): + self.figures = False + + def update_if_candidates_required(self): + if not self.candidates_exist: + self.classify = False + + def update_if_cells_required(self): + if not self.cells_exist: + self.analyse = False + self.figures = False + + +def prep_registration(args): + args.target_brain_path = args.background_planes_path[0] + logging.debug("Making registration directory") + ensure_directory_exists(args.paths.registration_output_folder) + log_metadata(args.paths.registration_metadata_path, args) + additional_images_downsample = {} + for idx, images in enumerate(args.signal_planes_paths): + channel = args.signal_ch_ids[idx] + additional_images_downsample[f"channel_{channel}"] = images + return args, additional_images_downsample + + +def prep_channel_specific_general(args, what_to_run): + args.paths.output_dir = args.output_dir + args.paths.make_channel_specific_paths() + what_to_run.update(args) + return args, what_to_run + + +def prep_candidate_detection(args): + if args.save_planes: + args.plane_directory = os.path.join( + args.output_dir, "processed_planes" + ) + ensure_directory_exists(args.plane_directory) + else: + args.plane_directory = None # FIXME: remove this fudge + + return args diff --git a/cellfinder/tools/system.py b/cellfinder/tools/system.py new file mode 100644 index 00000000..612ad4da --- /dev/null +++ b/cellfinder/tools/system.py @@ -0,0 +1,82 @@ +from pathlib import Path + +from brainglobe_utils.general.exceptions import CommandLineInputError + + +def get_subdirectories(directory, names_only=False): + """ + Return all subdirectories in a given directory + :param directory: + :param names_only: If true, dont return paths, but the names + :return: Subdirectories + """ + + p = Path(directory) + if names_only: + return [x.name for x in p.iterdir() if x.is_dir()] + else: + return [x for x in p.iterdir() if x.is_dir()] + + +def get_number_of_files_in_dir(directory): + """ + Sums the number of files in a directory + :param directory: Any directory with files + :return: Number of files in directory + """ + directory = Path(directory) + files = directory.iterdir() + total_files = sum(1 for x in files) + return total_files + + +def check_path_exists(file): + """ + Returns True is a file exists, otherwise throws a FileNotFoundError + :param file: Input file + :return: True, if the file exists + """ + file = Path(file) + if file.exists(): + return True + else: + raise FileNotFoundError + + +def catch_input_file_error(path): + """ + Catches if an input path doesn't exist, and returns an informative error + :param path: Input file path + default) + """ + try: + check_path_exists(path) + except FileNotFoundError: + message = ( + "File path: '{}' cannot be found. Please check your input " + "arguments.".format(path) + ) + raise CommandLineInputError(message) + + +def memory_in_bytes(memory_amount, unit): + """ + Converts an amount of memory (in given units) to bytes + + :param float memory_amount: An amount of memory + :param str unit: The units ('KB', 'MB', 'GB', 'TB', 'PB') + :return: Amount of memory in bytes + """ + if memory_amount is None: + return memory_amount + + supported_units = {"KB": 3, "MB": 6, "GB": 9, "TB": 12, "PB": 15} + + unit = unit.upper() + if unit not in supported_units: + raise NotImplementedError( + f"Unit: {unit} is not supported. Please " + f"use one of {list(supported_units.keys())}" + ) + else: + return memory_amount * 10 ** supported_units[unit] diff --git a/cellfinder/tools/tools.py b/cellfinder/tools/tools.py new file mode 100644 index 00000000..4d8431a5 --- /dev/null +++ b/cellfinder/tools/tools.py @@ -0,0 +1,126 @@ +from natsort import natsorted + + +def get_max_value(obj_in): + """ + Returns the maximum allowed value for a specific object type. + :param obj_in: Object + :return int: Maximum value of object type + """ + # TODO: Generalise, and not rely on parsing a string + if obj_in.dtype == "uint8": + return 255 + else: + return 2 ** int(str(obj_in.dtype)[-2:]) - 1 + + +def union(a, b): + """ + Return the union (elements in both) of two lists + :param list a: + :param list b: + :return: Union of the two lists + """ + return list(set(a) | set(b)) + + +def check_unique_list(in_list, natural_sort=True): + """ + Checks if all the items in a list are unique or not + :param list in_list: Input list + :param bool natural_sort: Sort the resulting items naturally + (default: True) + :return: True/False and a list of any repeated values + """ + unique = set(in_list) + repeated_items = [] + + for item in unique: + count = in_list.count(item) + if count > 1: + repeated_items.append(item) + + if repeated_items: + if natural_sort: + repeated_items = natsorted(repeated_items) + return False, repeated_items + else: + return True, [] + + +def common_member(a, b, natural_sort=True): + """ + Checks if two lists (or sets) have a common member, and if so, returns + the common members. + :param a: First list (or set) + :param b: Second list (or set) + :param bool natural_sort: Sort the resulting items naturally + (default: True) + :return: True/False and the list of values + """ + a_set = set(a) + b_set = set(b) + intersection = list(a_set.intersection(b_set)) + if len(intersection) > 0: + result = True + else: + result = False + + if natural_sort: + intersection = natsorted(intersection) + + return result, intersection + + +def get_number_of_bins_nd(array_size, binning): + """ + Generate the number of bins needed in three dimensions, based on the size + of the array, and the binning. + :param array_size: Size of the image array (tuple or dict) + :param binning: How many pixels in each edge of nD equal sized bins + :return: + """ + if isinstance(array_size, tuple): + bins = [int(size / binning) for size in array_size] + elif isinstance(array_size, dict): + bins = [int(size / binning) for size in array_size.values()] + else: + raise NotImplementedError( + "Variable type: {} is not supported. Please" + "use tuple or dict".format(type(array_size)) + ) + return tuple(bins) + + +def interchange_np_fiji_coordinates(tuple_in): + """ + Swaps the first and second element of a tuple to swap between the numpy + convention (vertical is first) and FIJI convention (horizontal is first) + :param tuple_in: A 2+ element tuple + :return: Same tuple with element 0 and 1 interchanged + """ + tmp_list = list(tuple_in) + tmp_list = swap_elements_list(tmp_list, 0, 1) + return tuple(tmp_list) + + +def swap_elements_list(list_in, swap_a, swap_b): + """ + Swap two elements in a list + :param list_in: A list + :param swap_a: Index of first element to swap + :param swap_b: Index of second element to swap + :return: List with swap_a and swap_b exchanged + """ + list_in[swap_a], list_in[swap_b] = list_in[swap_b], list_in[swap_a] + return list_in + + +def is_any_list_overlap(list_a, list_b): + """ + Is there any overlap between two lists + :param list_a: Any list + :param list_b: Any other list + :return: True if lists have shared elements + """ + return any({*list_a} & {*list_b}) diff --git a/environment.yml b/environment.yml new file mode 100644 index 00000000..0691db0a --- /dev/null +++ b/environment.yml @@ -0,0 +1,7 @@ +name: cellfinder +dependencies: + - python=3.10 + - cudatoolkit + - cudnn + - pip: + - cellfinder diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..e589b61f --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,88 @@ +[project] +name = "cellfinder" +description = "Automated 3D cell detection and registration of whole-brain images" +readme = "README.md" +license = { file = "LICENSE" } +requires-python = ">=3.8" +authors = [ + { name = "Adam Tyson", email = "code@adamltyson.com" }, + { name = "Christian Niedworok" }, + { name = "Charly Rousseau" }, +] +classifiers = [ + "Development Status :: 3 - Alpha", + "Operating System :: POSIX :: Linux", + "Operating System :: Microsoft :: Windows :: Windows 10", + "Programming Language :: Python", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Topic :: Scientific/Engineering :: Image Recognition", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", +] +dependencies = [ + "brainreg", + "cellfinder-core>=0.2.4", + "configobj", + "fancylog>=0.0.7", + "imio", + "brainglobe-utils>=0.2.5", + "multiprocessing-logging>=0.3.4", + "natsort", + "numpy", + "pandas", + "packaging", + "scikit-image", + "tifffile", + "tqdm", +] +dynamic = ["version"] + +[project.scripts] +cellfinder = "cellfinder.main:main" + +[project.optional-dependencies] +dev = [ + "black", + "pytest-cov", + "pytest", + "gitpython", + "coverage>=5.0.3", + "pre-commit", + "setuptools_scm", +] +napari = ["napari[pyside2]", "brainglobe-napari-io", "cellfinder-napari"] + +[project.urls] +source = "https://github.com/brainglobe/cellfinder" +bug_tracker = "https://github.com/brainglobe/cellfinder/issues" +homepage = "https://brainglobe.info" +documentation = "https://brainglobe.info/documentation/cellfinder" +[build-system] +requires = ["setuptools>=45", "wheel", "setuptools_scm[toml]>=6.2"] +build-backend = "setuptools.build_meta" + +[tool.black] +target-version = ['py38', 'py39', 'py310'] +skip-string-normalization = false +line-length = 79 + +[tool.check-manifest] +ignore = ["*.yaml"] + +[tool.ruff] +line-length = 79 +exclude = ["__init__.py", "build", ".eggs"] +select = ["I", "E", "F"] +fix = true + +[tool.setuptools] +include-package-data = true +zip-safe = false + +[tool.setuptools.packages.find] +include = ["cellfinder"] +exclude = ["tests", "resources"] + +[tool.setuptools_scm] diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 00000000..769170c1 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,5 @@ +[pytest] +addopts = --cov=cellfinder +markers = + slow: marks tests as slow (deselect with '-m "not slow"') + serial diff --git a/resources/brainrender.png b/resources/brainrender.png new file mode 100644 index 00000000..66d510f5 Binary files /dev/null and b/resources/brainrender.png differ diff --git a/resources/classify.png b/resources/classify.png new file mode 100644 index 00000000..24c83454 Binary files /dev/null and b/resources/classify.png differ diff --git a/resources/detect.png b/resources/detect.png new file mode 100644 index 00000000..7ef4e5c9 Binary files /dev/null and b/resources/detect.png differ diff --git a/resources/heatmap.png b/resources/heatmap.png new file mode 100644 index 00000000..64df61af Binary files /dev/null and b/resources/heatmap.png differ diff --git a/resources/injection.png b/resources/injection.png new file mode 100644 index 00000000..677fe1dd Binary files /dev/null and b/resources/injection.png differ diff --git a/resources/probe.png b/resources/probe.png new file mode 100644 index 00000000..d894e909 Binary files /dev/null and b/resources/probe.png differ diff --git a/resources/raw.png b/resources/raw.png new file mode 100644 index 00000000..f2624947 Binary files /dev/null and b/resources/raw.png differ diff --git a/resources/register.png b/resources/register.png new file mode 100644 index 00000000..291fc69c Binary files /dev/null and b/resources/register.png differ diff --git a/tests/data/background/background_ch010000.tif b/tests/data/background/background_ch010000.tif new file mode 100644 index 00000000..02e7313f Binary files /dev/null and b/tests/data/background/background_ch010000.tif differ diff --git a/tests/data/background/background_ch010001.tif b/tests/data/background/background_ch010001.tif new file mode 100644 index 00000000..decf09bd Binary files /dev/null and b/tests/data/background/background_ch010001.tif differ diff --git a/tests/data/background/background_ch010002.tif b/tests/data/background/background_ch010002.tif new file mode 100644 index 00000000..7c61cc72 Binary files /dev/null and b/tests/data/background/background_ch010002.tif differ diff --git a/tests/data/background/background_ch010003.tif b/tests/data/background/background_ch010003.tif new file mode 100644 index 00000000..5f501eaa Binary files /dev/null and b/tests/data/background/background_ch010003.tif differ diff --git a/tests/data/background/background_ch010004.tif b/tests/data/background/background_ch010004.tif new file mode 100644 index 00000000..3871799e Binary files /dev/null and b/tests/data/background/background_ch010004.tif differ diff --git a/tests/data/background/background_ch010005.tif b/tests/data/background/background_ch010005.tif new file mode 100644 index 00000000..6a502b95 Binary files /dev/null and b/tests/data/background/background_ch010005.tif differ diff --git a/tests/data/background/background_ch010006.tif b/tests/data/background/background_ch010006.tif new file mode 100644 index 00000000..09e6877b Binary files /dev/null and b/tests/data/background/background_ch010006.tif differ diff --git a/tests/data/background/background_ch010007.tif b/tests/data/background/background_ch010007.tif new file mode 100644 index 00000000..ddce1149 Binary files /dev/null and b/tests/data/background/background_ch010007.tif differ diff --git a/tests/data/background/background_ch010008.tif b/tests/data/background/background_ch010008.tif new file mode 100644 index 00000000..46405368 Binary files /dev/null and b/tests/data/background/background_ch010008.tif differ diff --git a/tests/data/background/background_ch010009.tif b/tests/data/background/background_ch010009.tif new file mode 100644 index 00000000..c20619e7 Binary files /dev/null and b/tests/data/background/background_ch010009.tif differ diff --git a/tests/data/background/background_ch010010.tif b/tests/data/background/background_ch010010.tif new file mode 100644 index 00000000..daa78025 Binary files /dev/null and b/tests/data/background/background_ch010010.tif differ diff --git a/tests/data/background/background_ch010011.tif b/tests/data/background/background_ch010011.tif new file mode 100644 index 00000000..319342cf Binary files /dev/null and b/tests/data/background/background_ch010011.tif differ diff --git a/tests/data/background/background_ch010012.tif b/tests/data/background/background_ch010012.tif new file mode 100644 index 00000000..26964f15 Binary files /dev/null and b/tests/data/background/background_ch010012.tif differ diff --git a/tests/data/background/background_ch010013.tif b/tests/data/background/background_ch010013.tif new file mode 100644 index 00000000..a1470754 Binary files /dev/null and b/tests/data/background/background_ch010013.tif differ diff --git a/tests/data/background/background_ch010014.tif b/tests/data/background/background_ch010014.tif new file mode 100644 index 00000000..873e57f1 Binary files /dev/null and b/tests/data/background/background_ch010014.tif differ diff --git a/tests/data/background/background_ch010015.tif b/tests/data/background/background_ch010015.tif new file mode 100644 index 00000000..8c48bade Binary files /dev/null and b/tests/data/background/background_ch010015.tif differ diff --git a/tests/data/background/background_ch010016.tif b/tests/data/background/background_ch010016.tif new file mode 100644 index 00000000..afceb251 Binary files /dev/null and b/tests/data/background/background_ch010016.tif differ diff --git a/tests/data/background/background_ch010017.tif b/tests/data/background/background_ch010017.tif new file mode 100644 index 00000000..6c8f8f6e Binary files /dev/null and b/tests/data/background/background_ch010017.tif differ diff --git a/tests/data/background/background_ch010018.tif b/tests/data/background/background_ch010018.tif new file mode 100644 index 00000000..71c6a578 Binary files /dev/null and b/tests/data/background/background_ch010018.tif differ diff --git a/tests/data/background/background_ch010019.tif b/tests/data/background/background_ch010019.tif new file mode 100644 index 00000000..17cd9891 Binary files /dev/null and b/tests/data/background/background_ch010019.tif differ diff --git a/tests/data/background/background_ch010020.tif b/tests/data/background/background_ch010020.tif new file mode 100644 index 00000000..db8f2999 Binary files /dev/null and b/tests/data/background/background_ch010020.tif differ diff --git a/tests/data/background/background_ch010021.tif b/tests/data/background/background_ch010021.tif new file mode 100644 index 00000000..c4cc1951 Binary files /dev/null and b/tests/data/background/background_ch010021.tif differ diff --git a/tests/data/background/background_ch010022.tif b/tests/data/background/background_ch010022.tif new file mode 100644 index 00000000..65cc4361 Binary files /dev/null and b/tests/data/background/background_ch010022.tif differ diff --git a/tests/data/background/background_ch010023.tif b/tests/data/background/background_ch010023.tif new file mode 100644 index 00000000..95c84061 Binary files /dev/null and b/tests/data/background/background_ch010023.tif differ diff --git a/tests/data/background/background_ch010024.tif b/tests/data/background/background_ch010024.tif new file mode 100644 index 00000000..6371ea2f Binary files /dev/null and b/tests/data/background/background_ch010024.tif differ diff --git a/tests/data/background/background_ch010025.tif b/tests/data/background/background_ch010025.tif new file mode 100644 index 00000000..66e370ba Binary files /dev/null and b/tests/data/background/background_ch010025.tif differ diff --git a/tests/data/brain/image_0000.tif b/tests/data/brain/image_0000.tif new file mode 100644 index 00000000..c1288515 Binary files /dev/null and b/tests/data/brain/image_0000.tif differ diff --git a/tests/data/brain/image_0001.tif b/tests/data/brain/image_0001.tif new file mode 100644 index 00000000..5c32402b Binary files /dev/null and b/tests/data/brain/image_0001.tif differ diff --git a/tests/data/brain/image_0002.tif b/tests/data/brain/image_0002.tif new file mode 100644 index 00000000..cb9132bf Binary files /dev/null and b/tests/data/brain/image_0002.tif differ diff --git a/tests/data/brain/image_0003.tif b/tests/data/brain/image_0003.tif new file mode 100644 index 00000000..573452a1 Binary files /dev/null and b/tests/data/brain/image_0003.tif differ diff --git a/tests/data/brain/image_0004.tif b/tests/data/brain/image_0004.tif new file mode 100644 index 00000000..c2f57e1b Binary files /dev/null and b/tests/data/brain/image_0004.tif differ diff --git a/tests/data/brain/image_0005.tif b/tests/data/brain/image_0005.tif new file mode 100644 index 00000000..8c619b3d Binary files /dev/null and b/tests/data/brain/image_0005.tif differ diff --git a/tests/data/brain/image_0006.tif b/tests/data/brain/image_0006.tif new file mode 100644 index 00000000..4457e3f0 Binary files /dev/null and b/tests/data/brain/image_0006.tif differ diff --git a/tests/data/brain/image_0007.tif b/tests/data/brain/image_0007.tif new file mode 100644 index 00000000..bf436e82 Binary files /dev/null and b/tests/data/brain/image_0007.tif differ diff --git a/tests/data/brain/image_0008.tif b/tests/data/brain/image_0008.tif new file mode 100644 index 00000000..e949c008 Binary files /dev/null and b/tests/data/brain/image_0008.tif differ diff --git a/tests/data/brain/image_0009.tif b/tests/data/brain/image_0009.tif new file mode 100644 index 00000000..f0e444a7 Binary files /dev/null and b/tests/data/brain/image_0009.tif differ diff --git a/tests/data/brain/image_0010.tif b/tests/data/brain/image_0010.tif new file mode 100644 index 00000000..39e4623c Binary files /dev/null and b/tests/data/brain/image_0010.tif differ diff --git a/tests/data/brain/image_0011.tif b/tests/data/brain/image_0011.tif new file mode 100644 index 00000000..13487516 Binary files /dev/null and b/tests/data/brain/image_0011.tif differ diff --git a/tests/data/brain/image_0012.tif b/tests/data/brain/image_0012.tif new file mode 100644 index 00000000..1917add3 Binary files /dev/null and b/tests/data/brain/image_0012.tif differ diff --git a/tests/data/brain/image_0013.tif b/tests/data/brain/image_0013.tif new file mode 100644 index 00000000..1a976f3c Binary files /dev/null and b/tests/data/brain/image_0013.tif differ diff --git a/tests/data/brain/image_0014.tif b/tests/data/brain/image_0014.tif new file mode 100644 index 00000000..eb469207 Binary files /dev/null and b/tests/data/brain/image_0014.tif differ diff --git a/tests/data/brain/image_0015.tif b/tests/data/brain/image_0015.tif new file mode 100644 index 00000000..804d4105 Binary files /dev/null and b/tests/data/brain/image_0015.tif differ diff --git a/tests/data/brain/image_0016.tif b/tests/data/brain/image_0016.tif new file mode 100644 index 00000000..c5ed95ac Binary files /dev/null and b/tests/data/brain/image_0016.tif differ diff --git a/tests/data/brain/image_0017.tif b/tests/data/brain/image_0017.tif new file mode 100644 index 00000000..9bde06be Binary files /dev/null and b/tests/data/brain/image_0017.tif differ diff --git a/tests/data/brain/image_0018.tif b/tests/data/brain/image_0018.tif new file mode 100644 index 00000000..be3b262d Binary files /dev/null and b/tests/data/brain/image_0018.tif differ diff --git a/tests/data/brain/image_0019.tif b/tests/data/brain/image_0019.tif new file mode 100644 index 00000000..3542c9ba Binary files /dev/null and b/tests/data/brain/image_0019.tif differ diff --git a/tests/data/brain/image_0020.tif b/tests/data/brain/image_0020.tif new file mode 100644 index 00000000..6eda4149 Binary files /dev/null and b/tests/data/brain/image_0020.tif differ diff --git a/tests/data/brain/image_0021.tif b/tests/data/brain/image_0021.tif new file mode 100644 index 00000000..a1fcddc1 Binary files /dev/null and b/tests/data/brain/image_0021.tif differ diff --git a/tests/data/brain/image_0022.tif b/tests/data/brain/image_0022.tif new file mode 100644 index 00000000..f1c4fe97 Binary files /dev/null and b/tests/data/brain/image_0022.tif differ diff --git a/tests/data/brain/image_0023.tif b/tests/data/brain/image_0023.tif new file mode 100644 index 00000000..3b5ed1c3 Binary files /dev/null and b/tests/data/brain/image_0023.tif differ diff --git a/tests/data/brain/image_0024.tif b/tests/data/brain/image_0024.tif new file mode 100644 index 00000000..11e3763c Binary files /dev/null and b/tests/data/brain/image_0024.tif differ diff --git a/tests/data/brain/image_0025.tif b/tests/data/brain/image_0025.tif new file mode 100644 index 00000000..86d48deb Binary files /dev/null and b/tests/data/brain/image_0025.tif differ diff --git a/tests/data/brain/image_0026.tif b/tests/data/brain/image_0026.tif new file mode 100644 index 00000000..90619430 Binary files /dev/null and b/tests/data/brain/image_0026.tif differ diff --git a/tests/data/brain/image_0027.tif b/tests/data/brain/image_0027.tif new file mode 100644 index 00000000..d3e0a784 Binary files /dev/null and b/tests/data/brain/image_0027.tif differ diff --git a/tests/data/brain/image_0028.tif b/tests/data/brain/image_0028.tif new file mode 100644 index 00000000..b84f7273 Binary files /dev/null and b/tests/data/brain/image_0028.tif differ diff --git a/tests/data/brain/image_0029.tif b/tests/data/brain/image_0029.tif new file mode 100644 index 00000000..c1fe51f2 Binary files /dev/null and b/tests/data/brain/image_0029.tif differ diff --git a/tests/data/brain/image_0030.tif b/tests/data/brain/image_0030.tif new file mode 100644 index 00000000..6723656b Binary files /dev/null and b/tests/data/brain/image_0030.tif differ diff --git a/tests/data/brain/image_0031.tif b/tests/data/brain/image_0031.tif new file mode 100644 index 00000000..37d02908 Binary files /dev/null and b/tests/data/brain/image_0031.tif differ diff --git a/tests/data/brain/image_0032.tif b/tests/data/brain/image_0032.tif new file mode 100644 index 00000000..5e5fb256 Binary files /dev/null and b/tests/data/brain/image_0032.tif differ diff --git a/tests/data/brain/image_0033.tif b/tests/data/brain/image_0033.tif new file mode 100644 index 00000000..c9bb16ba Binary files /dev/null and b/tests/data/brain/image_0033.tif differ diff --git a/tests/data/brain/image_0034.tif b/tests/data/brain/image_0034.tif new file mode 100644 index 00000000..0d24e31e Binary files /dev/null and b/tests/data/brain/image_0034.tif differ diff --git a/tests/data/brain/image_0035.tif b/tests/data/brain/image_0035.tif new file mode 100644 index 00000000..c2062176 Binary files /dev/null and b/tests/data/brain/image_0035.tif differ diff --git a/tests/data/brain/image_0036.tif b/tests/data/brain/image_0036.tif new file mode 100644 index 00000000..d3d06625 Binary files /dev/null and b/tests/data/brain/image_0036.tif differ diff --git a/tests/data/brain/image_0037.tif b/tests/data/brain/image_0037.tif new file mode 100644 index 00000000..729cfd60 Binary files /dev/null and b/tests/data/brain/image_0037.tif differ diff --git a/tests/data/brain/image_0038.tif b/tests/data/brain/image_0038.tif new file mode 100644 index 00000000..1499f409 Binary files /dev/null and b/tests/data/brain/image_0038.tif differ diff --git a/tests/data/brain/image_0039.tif b/tests/data/brain/image_0039.tif new file mode 100644 index 00000000..67c32688 Binary files /dev/null and b/tests/data/brain/image_0039.tif differ diff --git a/tests/data/brain/image_0040.tif b/tests/data/brain/image_0040.tif new file mode 100644 index 00000000..7e3e89dd Binary files /dev/null and b/tests/data/brain/image_0040.tif differ diff --git a/tests/data/brain/image_0041.tif b/tests/data/brain/image_0041.tif new file mode 100644 index 00000000..469cd6af Binary files /dev/null and b/tests/data/brain/image_0041.tif differ diff --git a/tests/data/brain/image_0042.tif b/tests/data/brain/image_0042.tif new file mode 100644 index 00000000..9cd5ebe7 Binary files /dev/null and b/tests/data/brain/image_0042.tif differ diff --git a/tests/data/brain/image_0043.tif b/tests/data/brain/image_0043.tif new file mode 100644 index 00000000..a23adaf6 Binary files /dev/null and b/tests/data/brain/image_0043.tif differ diff --git a/tests/data/brain/image_0044.tif b/tests/data/brain/image_0044.tif new file mode 100644 index 00000000..8ee8bbee Binary files /dev/null and b/tests/data/brain/image_0044.tif differ diff --git a/tests/data/brain/image_0045.tif b/tests/data/brain/image_0045.tif new file mode 100644 index 00000000..be724a3b Binary files /dev/null and b/tests/data/brain/image_0045.tif differ diff --git a/tests/data/brain/image_0046.tif b/tests/data/brain/image_0046.tif new file mode 100644 index 00000000..b5863cbe Binary files /dev/null and b/tests/data/brain/image_0046.tif differ diff --git a/tests/data/brain/image_0047.tif b/tests/data/brain/image_0047.tif new file mode 100644 index 00000000..2cf23f5e Binary files /dev/null and b/tests/data/brain/image_0047.tif differ diff --git a/tests/data/brain/image_0048.tif b/tests/data/brain/image_0048.tif new file mode 100644 index 00000000..a7e1db4a Binary files /dev/null and b/tests/data/brain/image_0048.tif differ diff --git a/tests/data/brain/image_0049.tif b/tests/data/brain/image_0049.tif new file mode 100644 index 00000000..e19142ee Binary files /dev/null and b/tests/data/brain/image_0049.tif differ diff --git a/tests/data/brain/image_0050.tif b/tests/data/brain/image_0050.tif new file mode 100644 index 00000000..7f4ed5d0 Binary files /dev/null and b/tests/data/brain/image_0050.tif differ diff --git a/tests/data/brain/image_0051.tif b/tests/data/brain/image_0051.tif new file mode 100644 index 00000000..cfeacfb5 Binary files /dev/null and b/tests/data/brain/image_0051.tif differ diff --git a/tests/data/brain/image_0052.tif b/tests/data/brain/image_0052.tif new file mode 100644 index 00000000..71aaf4d1 Binary files /dev/null and b/tests/data/brain/image_0052.tif differ diff --git a/tests/data/brain/image_0053.tif b/tests/data/brain/image_0053.tif new file mode 100644 index 00000000..f5aa6218 Binary files /dev/null and b/tests/data/brain/image_0053.tif differ diff --git a/tests/data/brain/image_0054.tif b/tests/data/brain/image_0054.tif new file mode 100644 index 00000000..b7e82d95 Binary files /dev/null and b/tests/data/brain/image_0054.tif differ diff --git a/tests/data/brain/image_0055.tif b/tests/data/brain/image_0055.tif new file mode 100644 index 00000000..2c30c083 Binary files /dev/null and b/tests/data/brain/image_0055.tif differ diff --git a/tests/data/brain/image_0056.tif b/tests/data/brain/image_0056.tif new file mode 100644 index 00000000..b8e69938 Binary files /dev/null and b/tests/data/brain/image_0056.tif differ diff --git a/tests/data/brain/image_0057.tif b/tests/data/brain/image_0057.tif new file mode 100644 index 00000000..489d14db Binary files /dev/null and b/tests/data/brain/image_0057.tif differ diff --git a/tests/data/brain/image_0058.tif b/tests/data/brain/image_0058.tif new file mode 100644 index 00000000..258da06d Binary files /dev/null and b/tests/data/brain/image_0058.tif differ diff --git a/tests/data/brain/image_0059.tif b/tests/data/brain/image_0059.tif new file mode 100644 index 00000000..e38be562 Binary files /dev/null and b/tests/data/brain/image_0059.tif differ diff --git a/tests/data/brain/image_0060.tif b/tests/data/brain/image_0060.tif new file mode 100644 index 00000000..629f057c Binary files /dev/null and b/tests/data/brain/image_0060.tif differ diff --git a/tests/data/brain/image_0061.tif b/tests/data/brain/image_0061.tif new file mode 100644 index 00000000..bc5d969e Binary files /dev/null and b/tests/data/brain/image_0061.tif differ diff --git a/tests/data/brain/image_0062.tif b/tests/data/brain/image_0062.tif new file mode 100644 index 00000000..8dd288bd Binary files /dev/null and b/tests/data/brain/image_0062.tif differ diff --git a/tests/data/brain/image_0063.tif b/tests/data/brain/image_0063.tif new file mode 100644 index 00000000..1db3e696 Binary files /dev/null and b/tests/data/brain/image_0063.tif differ diff --git a/tests/data/brain/image_0064.tif b/tests/data/brain/image_0064.tif new file mode 100644 index 00000000..0b620f47 Binary files /dev/null and b/tests/data/brain/image_0064.tif differ diff --git a/tests/data/brain/image_0065.tif b/tests/data/brain/image_0065.tif new file mode 100644 index 00000000..e88e829b Binary files /dev/null and b/tests/data/brain/image_0065.tif differ diff --git a/tests/data/brain/image_0066.tif b/tests/data/brain/image_0066.tif new file mode 100644 index 00000000..a5e5f1ab Binary files /dev/null and b/tests/data/brain/image_0066.tif differ diff --git a/tests/data/brain/image_0067.tif b/tests/data/brain/image_0067.tif new file mode 100644 index 00000000..88159e37 Binary files /dev/null and b/tests/data/brain/image_0067.tif differ diff --git a/tests/data/brain/image_0068.tif b/tests/data/brain/image_0068.tif new file mode 100644 index 00000000..ae6a0ccc Binary files /dev/null and b/tests/data/brain/image_0068.tif differ diff --git a/tests/data/brain/image_0069.tif b/tests/data/brain/image_0069.tif new file mode 100644 index 00000000..6124f409 Binary files /dev/null and b/tests/data/brain/image_0069.tif differ diff --git a/tests/data/brain/image_0070.tif b/tests/data/brain/image_0070.tif new file mode 100644 index 00000000..fea1c7ab Binary files /dev/null and b/tests/data/brain/image_0070.tif differ diff --git a/tests/data/brain/image_0071.tif b/tests/data/brain/image_0071.tif new file mode 100644 index 00000000..bc643608 Binary files /dev/null and b/tests/data/brain/image_0071.tif differ diff --git a/tests/data/brain/image_0072.tif b/tests/data/brain/image_0072.tif new file mode 100644 index 00000000..0b23a9b0 Binary files /dev/null and b/tests/data/brain/image_0072.tif differ diff --git a/tests/data/brain/image_0073.tif b/tests/data/brain/image_0073.tif new file mode 100644 index 00000000..10290e41 Binary files /dev/null and b/tests/data/brain/image_0073.tif differ diff --git a/tests/data/brain/image_0074.tif b/tests/data/brain/image_0074.tif new file mode 100644 index 00000000..dd990b13 Binary files /dev/null and b/tests/data/brain/image_0074.tif differ diff --git a/tests/data/brain/image_0075.tif b/tests/data/brain/image_0075.tif new file mode 100644 index 00000000..2c4bd305 Binary files /dev/null and b/tests/data/brain/image_0075.tif differ diff --git a/tests/data/brain/image_0076.tif b/tests/data/brain/image_0076.tif new file mode 100644 index 00000000..6a3b3c60 Binary files /dev/null and b/tests/data/brain/image_0076.tif differ diff --git a/tests/data/brain/image_0077.tif b/tests/data/brain/image_0077.tif new file mode 100644 index 00000000..8a979db1 Binary files /dev/null and b/tests/data/brain/image_0077.tif differ diff --git a/tests/data/brain/image_0078.tif b/tests/data/brain/image_0078.tif new file mode 100644 index 00000000..61d4b34c Binary files /dev/null and b/tests/data/brain/image_0078.tif differ diff --git a/tests/data/brain/image_0079.tif b/tests/data/brain/image_0079.tif new file mode 100644 index 00000000..78634a33 Binary files /dev/null and b/tests/data/brain/image_0079.tif differ diff --git a/tests/data/brain/image_0080.tif b/tests/data/brain/image_0080.tif new file mode 100644 index 00000000..7916e02a Binary files /dev/null and b/tests/data/brain/image_0080.tif differ diff --git a/tests/data/brain/image_0081.tif b/tests/data/brain/image_0081.tif new file mode 100644 index 00000000..79019bbd Binary files /dev/null and b/tests/data/brain/image_0081.tif differ diff --git a/tests/data/brain/image_0082.tif b/tests/data/brain/image_0082.tif new file mode 100644 index 00000000..075fc1c6 Binary files /dev/null and b/tests/data/brain/image_0082.tif differ diff --git a/tests/data/brain/image_0083.tif b/tests/data/brain/image_0083.tif new file mode 100644 index 00000000..d2a38579 Binary files /dev/null and b/tests/data/brain/image_0083.tif differ diff --git a/tests/data/brain/image_0084.tif b/tests/data/brain/image_0084.tif new file mode 100644 index 00000000..eef137c9 Binary files /dev/null and b/tests/data/brain/image_0084.tif differ diff --git a/tests/data/brain/image_0085.tif b/tests/data/brain/image_0085.tif new file mode 100644 index 00000000..6524db0f Binary files /dev/null and b/tests/data/brain/image_0085.tif differ diff --git a/tests/data/brain/image_0086.tif b/tests/data/brain/image_0086.tif new file mode 100644 index 00000000..6cd99e60 Binary files /dev/null and b/tests/data/brain/image_0086.tif differ diff --git a/tests/data/brain/image_0087.tif b/tests/data/brain/image_0087.tif new file mode 100644 index 00000000..54f6c7f6 Binary files /dev/null and b/tests/data/brain/image_0087.tif differ diff --git a/tests/data/brain/image_0088.tif b/tests/data/brain/image_0088.tif new file mode 100644 index 00000000..cefe85eb Binary files /dev/null and b/tests/data/brain/image_0088.tif differ diff --git a/tests/data/brain/image_0089.tif b/tests/data/brain/image_0089.tif new file mode 100644 index 00000000..6a6c4480 Binary files /dev/null and b/tests/data/brain/image_0089.tif differ diff --git a/tests/data/brain/image_0090.tif b/tests/data/brain/image_0090.tif new file mode 100644 index 00000000..4f74cfa8 Binary files /dev/null and b/tests/data/brain/image_0090.tif differ diff --git a/tests/data/brain/image_0091.tif b/tests/data/brain/image_0091.tif new file mode 100644 index 00000000..d64f19ab Binary files /dev/null and b/tests/data/brain/image_0091.tif differ diff --git a/tests/data/brain/image_0092.tif b/tests/data/brain/image_0092.tif new file mode 100644 index 00000000..85c86525 Binary files /dev/null and b/tests/data/brain/image_0092.tif differ diff --git a/tests/data/brain/image_0093.tif b/tests/data/brain/image_0093.tif new file mode 100644 index 00000000..874748e1 Binary files /dev/null and b/tests/data/brain/image_0093.tif differ diff --git a/tests/data/brain/image_0094.tif b/tests/data/brain/image_0094.tif new file mode 100644 index 00000000..c07840ae Binary files /dev/null and b/tests/data/brain/image_0094.tif differ diff --git a/tests/data/brain/image_0095.tif b/tests/data/brain/image_0095.tif new file mode 100644 index 00000000..c6c85faa Binary files /dev/null and b/tests/data/brain/image_0095.tif differ diff --git a/tests/data/brain/image_0096.tif b/tests/data/brain/image_0096.tif new file mode 100644 index 00000000..5b1f7d3e Binary files /dev/null and b/tests/data/brain/image_0096.tif differ diff --git a/tests/data/brain/image_0097.tif b/tests/data/brain/image_0097.tif new file mode 100644 index 00000000..38e3440a Binary files /dev/null and b/tests/data/brain/image_0097.tif differ diff --git a/tests/data/brain/image_0098.tif b/tests/data/brain/image_0098.tif new file mode 100644 index 00000000..89302f5d Binary files /dev/null and b/tests/data/brain/image_0098.tif differ diff --git a/tests/data/brain/image_0099.tif b/tests/data/brain/image_0099.tif new file mode 100644 index 00000000..6538147c Binary files /dev/null and b/tests/data/brain/image_0099.tif differ diff --git a/tests/data/brain/image_0100.tif b/tests/data/brain/image_0100.tif new file mode 100644 index 00000000..9d7a29a1 Binary files /dev/null and b/tests/data/brain/image_0100.tif differ diff --git a/tests/data/brain/image_0101.tif b/tests/data/brain/image_0101.tif new file mode 100644 index 00000000..6e2dde74 Binary files /dev/null and b/tests/data/brain/image_0101.tif differ diff --git a/tests/data/brain/image_0102.tif b/tests/data/brain/image_0102.tif new file mode 100644 index 00000000..cb2e79f9 Binary files /dev/null and b/tests/data/brain/image_0102.tif differ diff --git a/tests/data/brain/image_0103.tif b/tests/data/brain/image_0103.tif new file mode 100644 index 00000000..63b33730 Binary files /dev/null and b/tests/data/brain/image_0103.tif differ diff --git a/tests/data/brain/image_0104.tif b/tests/data/brain/image_0104.tif new file mode 100644 index 00000000..c542e061 Binary files /dev/null and b/tests/data/brain/image_0104.tif differ diff --git a/tests/data/brain/image_0105.tif b/tests/data/brain/image_0105.tif new file mode 100644 index 00000000..19a43ac1 Binary files /dev/null and b/tests/data/brain/image_0105.tif differ diff --git a/tests/data/brain/image_0106.tif b/tests/data/brain/image_0106.tif new file mode 100644 index 00000000..f8bd91ae Binary files /dev/null and b/tests/data/brain/image_0106.tif differ diff --git a/tests/data/brain/image_0107.tif b/tests/data/brain/image_0107.tif new file mode 100644 index 00000000..955fa6be Binary files /dev/null and b/tests/data/brain/image_0107.tif differ diff --git a/tests/data/brain/image_0108.tif b/tests/data/brain/image_0108.tif new file mode 100644 index 00000000..f5a01fef Binary files /dev/null and b/tests/data/brain/image_0108.tif differ diff --git a/tests/data/brain/image_0109.tif b/tests/data/brain/image_0109.tif new file mode 100644 index 00000000..2a0cd4fc Binary files /dev/null and b/tests/data/brain/image_0109.tif differ diff --git a/tests/data/brain/image_0110.tif b/tests/data/brain/image_0110.tif new file mode 100644 index 00000000..4544ba10 Binary files /dev/null and b/tests/data/brain/image_0110.tif differ diff --git a/tests/data/brain/image_0111.tif b/tests/data/brain/image_0111.tif new file mode 100644 index 00000000..d4fb8650 Binary files /dev/null and b/tests/data/brain/image_0111.tif differ diff --git a/tests/data/brain/image_0112.tif b/tests/data/brain/image_0112.tif new file mode 100644 index 00000000..98a56d77 Binary files /dev/null and b/tests/data/brain/image_0112.tif differ diff --git a/tests/data/brain/image_0113.tif b/tests/data/brain/image_0113.tif new file mode 100644 index 00000000..781561f8 Binary files /dev/null and b/tests/data/brain/image_0113.tif differ diff --git a/tests/data/brain/image_0114.tif b/tests/data/brain/image_0114.tif new file mode 100644 index 00000000..e48dd0b5 Binary files /dev/null and b/tests/data/brain/image_0114.tif differ diff --git a/tests/data/brain/image_0115.tif b/tests/data/brain/image_0115.tif new file mode 100644 index 00000000..5b799bab Binary files /dev/null and b/tests/data/brain/image_0115.tif differ diff --git a/tests/data/brain/image_0116.tif b/tests/data/brain/image_0116.tif new file mode 100644 index 00000000..25ac832d Binary files /dev/null and b/tests/data/brain/image_0116.tif differ diff --git a/tests/data/brain/image_0117.tif b/tests/data/brain/image_0117.tif new file mode 100644 index 00000000..fdba09b9 Binary files /dev/null and b/tests/data/brain/image_0117.tif differ diff --git a/tests/data/brain/image_0118.tif b/tests/data/brain/image_0118.tif new file mode 100644 index 00000000..5e94f59c Binary files /dev/null and b/tests/data/brain/image_0118.tif differ diff --git a/tests/data/brain/image_0119.tif b/tests/data/brain/image_0119.tif new file mode 100644 index 00000000..7398b364 Binary files /dev/null and b/tests/data/brain/image_0119.tif differ diff --git a/tests/data/brain/image_0120.tif b/tests/data/brain/image_0120.tif new file mode 100644 index 00000000..94e923d0 Binary files /dev/null and b/tests/data/brain/image_0120.tif differ diff --git a/tests/data/brain/image_0121.tif b/tests/data/brain/image_0121.tif new file mode 100644 index 00000000..be3fd64a Binary files /dev/null and b/tests/data/brain/image_0121.tif differ diff --git a/tests/data/brain/image_0122.tif b/tests/data/brain/image_0122.tif new file mode 100644 index 00000000..d98260c7 Binary files /dev/null and b/tests/data/brain/image_0122.tif differ diff --git a/tests/data/brain/image_0123.tif b/tests/data/brain/image_0123.tif new file mode 100644 index 00000000..5d88e5bf Binary files /dev/null and b/tests/data/brain/image_0123.tif differ diff --git a/tests/data/brain/image_0124.tif b/tests/data/brain/image_0124.tif new file mode 100644 index 00000000..9e460d51 Binary files /dev/null and b/tests/data/brain/image_0124.tif differ diff --git a/tests/data/brain/image_0125.tif b/tests/data/brain/image_0125.tif new file mode 100644 index 00000000..ca4dd1c8 Binary files /dev/null and b/tests/data/brain/image_0125.tif differ diff --git a/tests/data/brain/image_0126.tif b/tests/data/brain/image_0126.tif new file mode 100644 index 00000000..cde39d1a Binary files /dev/null and b/tests/data/brain/image_0126.tif differ diff --git a/tests/data/brain/image_0127.tif b/tests/data/brain/image_0127.tif new file mode 100644 index 00000000..33b19c75 Binary files /dev/null and b/tests/data/brain/image_0127.tif differ diff --git a/tests/data/brain/image_0128.tif b/tests/data/brain/image_0128.tif new file mode 100644 index 00000000..8c791fa4 Binary files /dev/null and b/tests/data/brain/image_0128.tif differ diff --git a/tests/data/brain/image_0129.tif b/tests/data/brain/image_0129.tif new file mode 100644 index 00000000..e14bb12e Binary files /dev/null and b/tests/data/brain/image_0129.tif differ diff --git a/tests/data/brain/image_0130.tif b/tests/data/brain/image_0130.tif new file mode 100644 index 00000000..a4ba96e7 Binary files /dev/null and b/tests/data/brain/image_0130.tif differ diff --git a/tests/data/brain/image_0131.tif b/tests/data/brain/image_0131.tif new file mode 100644 index 00000000..69ff721d Binary files /dev/null and b/tests/data/brain/image_0131.tif differ diff --git a/tests/data/brain/image_0132.tif b/tests/data/brain/image_0132.tif new file mode 100644 index 00000000..e922be5f Binary files /dev/null and b/tests/data/brain/image_0132.tif differ diff --git a/tests/data/brain/image_0133.tif b/tests/data/brain/image_0133.tif new file mode 100644 index 00000000..e17bf60e Binary files /dev/null and b/tests/data/brain/image_0133.tif differ diff --git a/tests/data/brain/image_0134.tif b/tests/data/brain/image_0134.tif new file mode 100644 index 00000000..e7937bbe Binary files /dev/null and b/tests/data/brain/image_0134.tif differ diff --git a/tests/data/brain/image_0135.tif b/tests/data/brain/image_0135.tif new file mode 100644 index 00000000..28f80157 Binary files /dev/null and b/tests/data/brain/image_0135.tif differ diff --git a/tests/data/brain/image_0136.tif b/tests/data/brain/image_0136.tif new file mode 100644 index 00000000..000581b2 Binary files /dev/null and b/tests/data/brain/image_0136.tif differ diff --git a/tests/data/brain/image_0137.tif b/tests/data/brain/image_0137.tif new file mode 100644 index 00000000..70fae025 Binary files /dev/null and b/tests/data/brain/image_0137.tif differ diff --git a/tests/data/brain/image_0138.tif b/tests/data/brain/image_0138.tif new file mode 100644 index 00000000..b2e2b5ea Binary files /dev/null and b/tests/data/brain/image_0138.tif differ diff --git a/tests/data/brain/image_0139.tif b/tests/data/brain/image_0139.tif new file mode 100644 index 00000000..ffcfd2d6 Binary files /dev/null and b/tests/data/brain/image_0139.tif differ diff --git a/tests/data/brain/image_0140.tif b/tests/data/brain/image_0140.tif new file mode 100644 index 00000000..1498893e Binary files /dev/null and b/tests/data/brain/image_0140.tif differ diff --git a/tests/data/brain/image_0141.tif b/tests/data/brain/image_0141.tif new file mode 100644 index 00000000..98ef5f8b Binary files /dev/null and b/tests/data/brain/image_0141.tif differ diff --git a/tests/data/brain/image_0142.tif b/tests/data/brain/image_0142.tif new file mode 100644 index 00000000..bdedd289 Binary files /dev/null and b/tests/data/brain/image_0142.tif differ diff --git a/tests/data/brain/image_0143.tif b/tests/data/brain/image_0143.tif new file mode 100644 index 00000000..5c3d23a5 Binary files /dev/null and b/tests/data/brain/image_0143.tif differ diff --git a/tests/data/brain/image_0144.tif b/tests/data/brain/image_0144.tif new file mode 100644 index 00000000..06025c06 Binary files /dev/null and b/tests/data/brain/image_0144.tif differ diff --git a/tests/data/brain/image_0145.tif b/tests/data/brain/image_0145.tif new file mode 100644 index 00000000..13007f2d Binary files /dev/null and b/tests/data/brain/image_0145.tif differ diff --git a/tests/data/brain/image_0146.tif b/tests/data/brain/image_0146.tif new file mode 100644 index 00000000..a92c7aa7 Binary files /dev/null and b/tests/data/brain/image_0146.tif differ diff --git a/tests/data/brain/image_0147.tif b/tests/data/brain/image_0147.tif new file mode 100644 index 00000000..7a10becf Binary files /dev/null and b/tests/data/brain/image_0147.tif differ diff --git a/tests/data/brain/image_0148.tif b/tests/data/brain/image_0148.tif new file mode 100644 index 00000000..6830a952 Binary files /dev/null and b/tests/data/brain/image_0148.tif differ diff --git a/tests/data/brain/image_0149.tif b/tests/data/brain/image_0149.tif new file mode 100644 index 00000000..34064045 Binary files /dev/null and b/tests/data/brain/image_0149.tif differ diff --git a/tests/data/brain/image_0150.tif b/tests/data/brain/image_0150.tif new file mode 100644 index 00000000..09ac0b9b Binary files /dev/null and b/tests/data/brain/image_0150.tif differ diff --git a/tests/data/brain/image_0151.tif b/tests/data/brain/image_0151.tif new file mode 100644 index 00000000..62c1f916 Binary files /dev/null and b/tests/data/brain/image_0151.tif differ diff --git a/tests/data/brain/image_0152.tif b/tests/data/brain/image_0152.tif new file mode 100644 index 00000000..6b084d4f Binary files /dev/null and b/tests/data/brain/image_0152.tif differ diff --git a/tests/data/brain/image_0153.tif b/tests/data/brain/image_0153.tif new file mode 100644 index 00000000..d6a72348 Binary files /dev/null and b/tests/data/brain/image_0153.tif differ diff --git a/tests/data/brain/image_0154.tif b/tests/data/brain/image_0154.tif new file mode 100644 index 00000000..6b113878 Binary files /dev/null and b/tests/data/brain/image_0154.tif differ diff --git a/tests/data/brain/image_0155.tif b/tests/data/brain/image_0155.tif new file mode 100644 index 00000000..9f192a8d Binary files /dev/null and b/tests/data/brain/image_0155.tif differ diff --git a/tests/data/brain/image_0156.tif b/tests/data/brain/image_0156.tif new file mode 100644 index 00000000..3b9d998f Binary files /dev/null and b/tests/data/brain/image_0156.tif differ diff --git a/tests/data/brain/image_0157.tif b/tests/data/brain/image_0157.tif new file mode 100644 index 00000000..872ddf8d Binary files /dev/null and b/tests/data/brain/image_0157.tif differ diff --git a/tests/data/brain/image_0158.tif b/tests/data/brain/image_0158.tif new file mode 100644 index 00000000..5f5302d6 Binary files /dev/null and b/tests/data/brain/image_0158.tif differ diff --git a/tests/data/brain/image_0159.tif b/tests/data/brain/image_0159.tif new file mode 100644 index 00000000..5d9cf185 Binary files /dev/null and b/tests/data/brain/image_0159.tif differ diff --git a/tests/data/brain/image_0160.tif b/tests/data/brain/image_0160.tif new file mode 100644 index 00000000..4769fd91 Binary files /dev/null and b/tests/data/brain/image_0160.tif differ diff --git a/tests/data/brain/image_0161.tif b/tests/data/brain/image_0161.tif new file mode 100644 index 00000000..5847adf6 Binary files /dev/null and b/tests/data/brain/image_0161.tif differ diff --git a/tests/data/brain/image_0162.tif b/tests/data/brain/image_0162.tif new file mode 100644 index 00000000..8503e192 Binary files /dev/null and b/tests/data/brain/image_0162.tif differ diff --git a/tests/data/brain/image_0163.tif b/tests/data/brain/image_0163.tif new file mode 100644 index 00000000..c3d8e561 Binary files /dev/null and b/tests/data/brain/image_0163.tif differ diff --git a/tests/data/brain/image_0164.tif b/tests/data/brain/image_0164.tif new file mode 100644 index 00000000..5c0486ea Binary files /dev/null and b/tests/data/brain/image_0164.tif differ diff --git a/tests/data/brain/image_0165.tif b/tests/data/brain/image_0165.tif new file mode 100644 index 00000000..b8e3488a Binary files /dev/null and b/tests/data/brain/image_0165.tif differ diff --git a/tests/data/brain/image_0166.tif b/tests/data/brain/image_0166.tif new file mode 100644 index 00000000..c82475e6 Binary files /dev/null and b/tests/data/brain/image_0166.tif differ diff --git a/tests/data/brain/image_0167.tif b/tests/data/brain/image_0167.tif new file mode 100644 index 00000000..4eeb5ad4 Binary files /dev/null and b/tests/data/brain/image_0167.tif differ diff --git a/tests/data/brain/image_0168.tif b/tests/data/brain/image_0168.tif new file mode 100644 index 00000000..d9bb6d9b Binary files /dev/null and b/tests/data/brain/image_0168.tif differ diff --git a/tests/data/brain/image_0169.tif b/tests/data/brain/image_0169.tif new file mode 100644 index 00000000..b1f81791 Binary files /dev/null and b/tests/data/brain/image_0169.tif differ diff --git a/tests/data/brain/image_0170.tif b/tests/data/brain/image_0170.tif new file mode 100644 index 00000000..f968a623 Binary files /dev/null and b/tests/data/brain/image_0170.tif differ diff --git a/tests/data/brain/image_0171.tif b/tests/data/brain/image_0171.tif new file mode 100644 index 00000000..f84f7b8c Binary files /dev/null and b/tests/data/brain/image_0171.tif differ diff --git a/tests/data/brain/image_0172.tif b/tests/data/brain/image_0172.tif new file mode 100644 index 00000000..a581d39d Binary files /dev/null and b/tests/data/brain/image_0172.tif differ diff --git a/tests/data/brain/image_0173.tif b/tests/data/brain/image_0173.tif new file mode 100644 index 00000000..6eb36412 Binary files /dev/null and b/tests/data/brain/image_0173.tif differ diff --git a/tests/data/brain/image_0174.tif b/tests/data/brain/image_0174.tif new file mode 100644 index 00000000..d29219b7 Binary files /dev/null and b/tests/data/brain/image_0174.tif differ diff --git a/tests/data/brain/image_0175.tif b/tests/data/brain/image_0175.tif new file mode 100644 index 00000000..6f8cff7b Binary files /dev/null and b/tests/data/brain/image_0175.tif differ diff --git a/tests/data/brain/image_0176.tif b/tests/data/brain/image_0176.tif new file mode 100644 index 00000000..7058142c Binary files /dev/null and b/tests/data/brain/image_0176.tif differ diff --git a/tests/data/brain/image_0177.tif b/tests/data/brain/image_0177.tif new file mode 100644 index 00000000..c6c11538 Binary files /dev/null and b/tests/data/brain/image_0177.tif differ diff --git a/tests/data/brain/image_0178.tif b/tests/data/brain/image_0178.tif new file mode 100644 index 00000000..791e8e03 Binary files /dev/null and b/tests/data/brain/image_0178.tif differ diff --git a/tests/data/brain/image_0179.tif b/tests/data/brain/image_0179.tif new file mode 100644 index 00000000..17a66bad Binary files /dev/null and b/tests/data/brain/image_0179.tif differ diff --git a/tests/data/brain/image_0180.tif b/tests/data/brain/image_0180.tif new file mode 100644 index 00000000..5cebfff6 Binary files /dev/null and b/tests/data/brain/image_0180.tif differ diff --git a/tests/data/brain/image_0181.tif b/tests/data/brain/image_0181.tif new file mode 100644 index 00000000..f93e0aab Binary files /dev/null and b/tests/data/brain/image_0181.tif differ diff --git a/tests/data/brain/image_0182.tif b/tests/data/brain/image_0182.tif new file mode 100644 index 00000000..cebca3bb Binary files /dev/null and b/tests/data/brain/image_0182.tif differ diff --git a/tests/data/brain/image_0183.tif b/tests/data/brain/image_0183.tif new file mode 100644 index 00000000..bc7f033e Binary files /dev/null and b/tests/data/brain/image_0183.tif differ diff --git a/tests/data/brain/image_0184.tif b/tests/data/brain/image_0184.tif new file mode 100644 index 00000000..a50dcef3 Binary files /dev/null and b/tests/data/brain/image_0184.tif differ diff --git a/tests/data/brain/image_0185.tif b/tests/data/brain/image_0185.tif new file mode 100644 index 00000000..3dd1e4e1 Binary files /dev/null and b/tests/data/brain/image_0185.tif differ diff --git a/tests/data/brain/image_0186.tif b/tests/data/brain/image_0186.tif new file mode 100644 index 00000000..1170e2a3 Binary files /dev/null and b/tests/data/brain/image_0186.tif differ diff --git a/tests/data/brain/image_0187.tif b/tests/data/brain/image_0187.tif new file mode 100644 index 00000000..1fc2037b Binary files /dev/null and b/tests/data/brain/image_0187.tif differ diff --git a/tests/data/brain/image_0188.tif b/tests/data/brain/image_0188.tif new file mode 100644 index 00000000..ef569541 Binary files /dev/null and b/tests/data/brain/image_0188.tif differ diff --git a/tests/data/brain/image_0189.tif b/tests/data/brain/image_0189.tif new file mode 100644 index 00000000..3bc4d437 Binary files /dev/null and b/tests/data/brain/image_0189.tif differ diff --git a/tests/data/brain/image_0190.tif b/tests/data/brain/image_0190.tif new file mode 100644 index 00000000..be38ddfc Binary files /dev/null and b/tests/data/brain/image_0190.tif differ diff --git a/tests/data/brain/image_0191.tif b/tests/data/brain/image_0191.tif new file mode 100644 index 00000000..05cae462 Binary files /dev/null and b/tests/data/brain/image_0191.tif differ diff --git a/tests/data/brain/image_0192.tif b/tests/data/brain/image_0192.tif new file mode 100644 index 00000000..dd367f09 Binary files /dev/null and b/tests/data/brain/image_0192.tif differ diff --git a/tests/data/brain/image_0193.tif b/tests/data/brain/image_0193.tif new file mode 100644 index 00000000..28ddfbad Binary files /dev/null and b/tests/data/brain/image_0193.tif differ diff --git a/tests/data/brain/image_0194.tif b/tests/data/brain/image_0194.tif new file mode 100644 index 00000000..b91eda0c Binary files /dev/null and b/tests/data/brain/image_0194.tif differ diff --git a/tests/data/brain/image_0195.tif b/tests/data/brain/image_0195.tif new file mode 100644 index 00000000..ec0cf209 Binary files /dev/null and b/tests/data/brain/image_0195.tif differ diff --git a/tests/data/brain/image_0196.tif b/tests/data/brain/image_0196.tif new file mode 100644 index 00000000..3dd56dc3 Binary files /dev/null and b/tests/data/brain/image_0196.tif differ diff --git a/tests/data/brain/image_0197.tif b/tests/data/brain/image_0197.tif new file mode 100644 index 00000000..8973ed72 Binary files /dev/null and b/tests/data/brain/image_0197.tif differ diff --git a/tests/data/brain/image_0198.tif b/tests/data/brain/image_0198.tif new file mode 100644 index 00000000..816c0f2b Binary files /dev/null and b/tests/data/brain/image_0198.tif differ diff --git a/tests/data/brain/image_0199.tif b/tests/data/brain/image_0199.tif new file mode 100644 index 00000000..3d121b84 Binary files /dev/null and b/tests/data/brain/image_0199.tif differ diff --git a/tests/data/brain/image_0200.tif b/tests/data/brain/image_0200.tif new file mode 100644 index 00000000..ab0b9c19 Binary files /dev/null and b/tests/data/brain/image_0200.tif differ diff --git a/tests/data/brain/image_0201.tif b/tests/data/brain/image_0201.tif new file mode 100644 index 00000000..c023b509 Binary files /dev/null and b/tests/data/brain/image_0201.tif differ diff --git a/tests/data/brain/image_0202.tif b/tests/data/brain/image_0202.tif new file mode 100644 index 00000000..4395906f Binary files /dev/null and b/tests/data/brain/image_0202.tif differ diff --git a/tests/data/brain/image_0203.tif b/tests/data/brain/image_0203.tif new file mode 100644 index 00000000..9691b45f Binary files /dev/null and b/tests/data/brain/image_0203.tif differ diff --git a/tests/data/brain/image_0204.tif b/tests/data/brain/image_0204.tif new file mode 100644 index 00000000..6b24f9b1 Binary files /dev/null and b/tests/data/brain/image_0204.tif differ diff --git a/tests/data/brain/image_0205.tif b/tests/data/brain/image_0205.tif new file mode 100644 index 00000000..71e2304e Binary files /dev/null and b/tests/data/brain/image_0205.tif differ diff --git a/tests/data/brain/image_0206.tif b/tests/data/brain/image_0206.tif new file mode 100644 index 00000000..1b2586ca Binary files /dev/null and b/tests/data/brain/image_0206.tif differ diff --git a/tests/data/brain/image_0207.tif b/tests/data/brain/image_0207.tif new file mode 100644 index 00000000..af1baf55 Binary files /dev/null and b/tests/data/brain/image_0207.tif differ diff --git a/tests/data/brain/image_0208.tif b/tests/data/brain/image_0208.tif new file mode 100644 index 00000000..d8af70de Binary files /dev/null and b/tests/data/brain/image_0208.tif differ diff --git a/tests/data/brain/image_0209.tif b/tests/data/brain/image_0209.tif new file mode 100644 index 00000000..574da21e Binary files /dev/null and b/tests/data/brain/image_0209.tif differ diff --git a/tests/data/brain/image_0210.tif b/tests/data/brain/image_0210.tif new file mode 100644 index 00000000..ae63cab9 Binary files /dev/null and b/tests/data/brain/image_0210.tif differ diff --git a/tests/data/brain/image_0211.tif b/tests/data/brain/image_0211.tif new file mode 100644 index 00000000..1be8c71f Binary files /dev/null and b/tests/data/brain/image_0211.tif differ diff --git a/tests/data/brain/image_0212.tif b/tests/data/brain/image_0212.tif new file mode 100644 index 00000000..7bfe262c Binary files /dev/null and b/tests/data/brain/image_0212.tif differ diff --git a/tests/data/brain/image_0213.tif b/tests/data/brain/image_0213.tif new file mode 100644 index 00000000..d2dff52b Binary files /dev/null and b/tests/data/brain/image_0213.tif differ diff --git a/tests/data/brain/image_0214.tif b/tests/data/brain/image_0214.tif new file mode 100644 index 00000000..fd8cbb11 Binary files /dev/null and b/tests/data/brain/image_0214.tif differ diff --git a/tests/data/brain/image_0215.tif b/tests/data/brain/image_0215.tif new file mode 100644 index 00000000..105f0d14 Binary files /dev/null and b/tests/data/brain/image_0215.tif differ diff --git a/tests/data/brain/image_0216.tif b/tests/data/brain/image_0216.tif new file mode 100644 index 00000000..025206c1 Binary files /dev/null and b/tests/data/brain/image_0216.tif differ diff --git a/tests/data/brain/image_0217.tif b/tests/data/brain/image_0217.tif new file mode 100644 index 00000000..b99ad148 Binary files /dev/null and b/tests/data/brain/image_0217.tif differ diff --git a/tests/data/brain/image_0218.tif b/tests/data/brain/image_0218.tif new file mode 100644 index 00000000..af69b0c5 Binary files /dev/null and b/tests/data/brain/image_0218.tif differ diff --git a/tests/data/brain/image_0219.tif b/tests/data/brain/image_0219.tif new file mode 100644 index 00000000..923e1873 Binary files /dev/null and b/tests/data/brain/image_0219.tif differ diff --git a/tests/data/brain/image_0220.tif b/tests/data/brain/image_0220.tif new file mode 100644 index 00000000..286e7140 Binary files /dev/null and b/tests/data/brain/image_0220.tif differ diff --git a/tests/data/brain/image_0221.tif b/tests/data/brain/image_0221.tif new file mode 100644 index 00000000..d9d1f124 Binary files /dev/null and b/tests/data/brain/image_0221.tif differ diff --git a/tests/data/brain/image_0222.tif b/tests/data/brain/image_0222.tif new file mode 100644 index 00000000..a9f8ceb3 Binary files /dev/null and b/tests/data/brain/image_0222.tif differ diff --git a/tests/data/brain/image_0223.tif b/tests/data/brain/image_0223.tif new file mode 100644 index 00000000..59df46d2 Binary files /dev/null and b/tests/data/brain/image_0223.tif differ diff --git a/tests/data/brain/image_0224.tif b/tests/data/brain/image_0224.tif new file mode 100644 index 00000000..ce3df3ff Binary files /dev/null and b/tests/data/brain/image_0224.tif differ diff --git a/tests/data/brain/image_0225.tif b/tests/data/brain/image_0225.tif new file mode 100644 index 00000000..42ababef Binary files /dev/null and b/tests/data/brain/image_0225.tif differ diff --git a/tests/data/brain/image_0226.tif b/tests/data/brain/image_0226.tif new file mode 100644 index 00000000..117b39f8 Binary files /dev/null and b/tests/data/brain/image_0226.tif differ diff --git a/tests/data/brain/image_0227.tif b/tests/data/brain/image_0227.tif new file mode 100644 index 00000000..c6f3090d Binary files /dev/null and b/tests/data/brain/image_0227.tif differ diff --git a/tests/data/brain/image_0228.tif b/tests/data/brain/image_0228.tif new file mode 100644 index 00000000..5775774d Binary files /dev/null and b/tests/data/brain/image_0228.tif differ diff --git a/tests/data/brain/image_0229.tif b/tests/data/brain/image_0229.tif new file mode 100644 index 00000000..1623ccb3 Binary files /dev/null and b/tests/data/brain/image_0229.tif differ diff --git a/tests/data/brain/image_0230.tif b/tests/data/brain/image_0230.tif new file mode 100644 index 00000000..e9bc9b7f Binary files /dev/null and b/tests/data/brain/image_0230.tif differ diff --git a/tests/data/brain/image_0231.tif b/tests/data/brain/image_0231.tif new file mode 100644 index 00000000..2a1ed26b Binary files /dev/null and b/tests/data/brain/image_0231.tif differ diff --git a/tests/data/brain/image_0232.tif b/tests/data/brain/image_0232.tif new file mode 100644 index 00000000..9ec937c7 Binary files /dev/null and b/tests/data/brain/image_0232.tif differ diff --git a/tests/data/brain/image_0233.tif b/tests/data/brain/image_0233.tif new file mode 100644 index 00000000..acc7019c Binary files /dev/null and b/tests/data/brain/image_0233.tif differ diff --git a/tests/data/brain/image_0234.tif b/tests/data/brain/image_0234.tif new file mode 100644 index 00000000..1bdba899 Binary files /dev/null and b/tests/data/brain/image_0234.tif differ diff --git a/tests/data/brain/image_0235.tif b/tests/data/brain/image_0235.tif new file mode 100644 index 00000000..769464c0 Binary files /dev/null and b/tests/data/brain/image_0235.tif differ diff --git a/tests/data/brain/image_0236.tif b/tests/data/brain/image_0236.tif new file mode 100644 index 00000000..2c091f57 Binary files /dev/null and b/tests/data/brain/image_0236.tif differ diff --git a/tests/data/brain/image_0237.tif b/tests/data/brain/image_0237.tif new file mode 100644 index 00000000..e530c4af Binary files /dev/null and b/tests/data/brain/image_0237.tif differ diff --git a/tests/data/brain/image_0238.tif b/tests/data/brain/image_0238.tif new file mode 100644 index 00000000..80b4cfee Binary files /dev/null and b/tests/data/brain/image_0238.tif differ diff --git a/tests/data/brain/image_0239.tif b/tests/data/brain/image_0239.tif new file mode 100644 index 00000000..e64cfe6a Binary files /dev/null and b/tests/data/brain/image_0239.tif differ diff --git a/tests/data/brain/image_0240.tif b/tests/data/brain/image_0240.tif new file mode 100644 index 00000000..569cdcce Binary files /dev/null and b/tests/data/brain/image_0240.tif differ diff --git a/tests/data/brain/image_0241.tif b/tests/data/brain/image_0241.tif new file mode 100644 index 00000000..ca4713b8 Binary files /dev/null and b/tests/data/brain/image_0241.tif differ diff --git a/tests/data/brain/image_0242.tif b/tests/data/brain/image_0242.tif new file mode 100644 index 00000000..18e06f43 Binary files /dev/null and b/tests/data/brain/image_0242.tif differ diff --git a/tests/data/brain/image_0243.tif b/tests/data/brain/image_0243.tif new file mode 100644 index 00000000..acfca8ab Binary files /dev/null and b/tests/data/brain/image_0243.tif differ diff --git a/tests/data/brain/image_0244.tif b/tests/data/brain/image_0244.tif new file mode 100644 index 00000000..6c3ff2fe Binary files /dev/null and b/tests/data/brain/image_0244.tif differ diff --git a/tests/data/brain/image_0245.tif b/tests/data/brain/image_0245.tif new file mode 100644 index 00000000..665ef575 Binary files /dev/null and b/tests/data/brain/image_0245.tif differ diff --git a/tests/data/brain/image_0246.tif b/tests/data/brain/image_0246.tif new file mode 100644 index 00000000..72d8bd88 Binary files /dev/null and b/tests/data/brain/image_0246.tif differ diff --git a/tests/data/brain/image_0247.tif b/tests/data/brain/image_0247.tif new file mode 100644 index 00000000..f4136899 Binary files /dev/null and b/tests/data/brain/image_0247.tif differ diff --git a/tests/data/brain/image_0248.tif b/tests/data/brain/image_0248.tif new file mode 100644 index 00000000..984098e1 Binary files /dev/null and b/tests/data/brain/image_0248.tif differ diff --git a/tests/data/brain/image_0249.tif b/tests/data/brain/image_0249.tif new file mode 100644 index 00000000..0d88b096 Binary files /dev/null and b/tests/data/brain/image_0249.tif differ diff --git a/tests/data/brain/image_0250.tif b/tests/data/brain/image_0250.tif new file mode 100644 index 00000000..3c621f6c Binary files /dev/null and b/tests/data/brain/image_0250.tif differ diff --git a/tests/data/brain/image_0251.tif b/tests/data/brain/image_0251.tif new file mode 100644 index 00000000..f983bd25 Binary files /dev/null and b/tests/data/brain/image_0251.tif differ diff --git a/tests/data/brain/image_0252.tif b/tests/data/brain/image_0252.tif new file mode 100644 index 00000000..d92f266a Binary files /dev/null and b/tests/data/brain/image_0252.tif differ diff --git a/tests/data/brain/image_0253.tif b/tests/data/brain/image_0253.tif new file mode 100644 index 00000000..db0034c8 Binary files /dev/null and b/tests/data/brain/image_0253.tif differ diff --git a/tests/data/brain/image_0254.tif b/tests/data/brain/image_0254.tif new file mode 100644 index 00000000..819f9f7f Binary files /dev/null and b/tests/data/brain/image_0254.tif differ diff --git a/tests/data/brain/image_0255.tif b/tests/data/brain/image_0255.tif new file mode 100644 index 00000000..3dc92d36 Binary files /dev/null and b/tests/data/brain/image_0255.tif differ diff --git a/tests/data/brain/image_0256.tif b/tests/data/brain/image_0256.tif new file mode 100644 index 00000000..27e619fb Binary files /dev/null and b/tests/data/brain/image_0256.tif differ diff --git a/tests/data/brain/image_0257.tif b/tests/data/brain/image_0257.tif new file mode 100644 index 00000000..c7ebcbc2 Binary files /dev/null and b/tests/data/brain/image_0257.tif differ diff --git a/tests/data/brain/image_0258.tif b/tests/data/brain/image_0258.tif new file mode 100644 index 00000000..bd7df19b Binary files /dev/null and b/tests/data/brain/image_0258.tif differ diff --git a/tests/data/brain/image_0259.tif b/tests/data/brain/image_0259.tif new file mode 100644 index 00000000..99eb59ae Binary files /dev/null and b/tests/data/brain/image_0259.tif differ diff --git a/tests/data/brain/image_0260.tif b/tests/data/brain/image_0260.tif new file mode 100644 index 00000000..195e9895 Binary files /dev/null and b/tests/data/brain/image_0260.tif differ diff --git a/tests/data/brain/image_0261.tif b/tests/data/brain/image_0261.tif new file mode 100644 index 00000000..1e1de754 Binary files /dev/null and b/tests/data/brain/image_0261.tif differ diff --git a/tests/data/brain/image_0262.tif b/tests/data/brain/image_0262.tif new file mode 100644 index 00000000..dea579c5 Binary files /dev/null and b/tests/data/brain/image_0262.tif differ diff --git a/tests/data/brain/image_0263.tif b/tests/data/brain/image_0263.tif new file mode 100644 index 00000000..ac0f32fa Binary files /dev/null and b/tests/data/brain/image_0263.tif differ diff --git a/tests/data/brain/image_0264.tif b/tests/data/brain/image_0264.tif new file mode 100644 index 00000000..5879819f Binary files /dev/null and b/tests/data/brain/image_0264.tif differ diff --git a/tests/data/brain/image_0265.tif b/tests/data/brain/image_0265.tif new file mode 100644 index 00000000..a920e777 Binary files /dev/null and b/tests/data/brain/image_0265.tif differ diff --git a/tests/data/brain/image_0266.tif b/tests/data/brain/image_0266.tif new file mode 100644 index 00000000..97beecbf Binary files /dev/null and b/tests/data/brain/image_0266.tif differ diff --git a/tests/data/brain/image_0267.tif b/tests/data/brain/image_0267.tif new file mode 100644 index 00000000..80c46cdd Binary files /dev/null and b/tests/data/brain/image_0267.tif differ diff --git a/tests/data/brain/image_0268.tif b/tests/data/brain/image_0268.tif new file mode 100644 index 00000000..fb01fa63 Binary files /dev/null and b/tests/data/brain/image_0268.tif differ diff --git a/tests/data/brain/image_0269.tif b/tests/data/brain/image_0269.tif new file mode 100644 index 00000000..d95b0215 Binary files /dev/null and b/tests/data/brain/image_0269.tif differ diff --git a/tests/data/cells/cells.xml b/tests/data/cells/cells.xml new file mode 100644 index 00000000..10df74ad --- /dev/null +++ b/tests/data/cells/cells.xml @@ -0,0 +1,337 @@ + + + + placeholder.tif + + + 1 + + 1 + + 181 + 2379 + 1282 + + + 2117 + 133 + 1276 + + + 4082 + 332 + 1281 + + + 2137 + 134 + 1286 + + + 2129 + 133 + 1276 + + + 2141 + 134 + 1278 + + + 2130 + 132 + 1277 + + + 2130 + 133 + 1278 + + + 2133 + 136 + 1285 + + + 2141 + 136 + 1297 + + + 2162 + 130 + 1274 + + + 2127 + 1026 + 1294 + + + 1801 + 336 + 1290 + + + 2176 + 134 + 1279 + + + 2194 + 134 + 1280 + + + 2664 + 336 + 1296 + + + 2435 + 343 + 1290 + + + 1266 + 3427 + 1294 + + + 568 + 2012 + 1294 + + + 2103 + 138 + 1285 + + + 2098 + 138 + 1279 + + + 2105 + 140 + 1289 + + + 2208 + 135 + 1275 + + + 2162 + 134 + 1286 + + + 2221 + 137 + 1281 + + + 2081 + 142 + 1284 + + + 2230 + 139 + 1275 + + + 2015 + 1045 + 1291 + + + 2072 + 141 + 1273 + + + 1413 + 2045 + 1294 + + + 1950 + 1048 + 1294 + + + 3340 + 142 + 1274 + + + 2051 + 142 + 1274 + + + 3362 + 145 + 1274 + + + 2046 + 150 + 1283 + + + 2046 + 151 + 1287 + + + 2046 + 151 + 1290 + + + 2047 + 151 + 1294 + + + 2032 + 146 + 1272 + + + 2923 + 147 + 1275 + + + 2064 + 147 + 1275 + + + 2267 + 147 + 1274 + + + 2297 + 1068 + 1292 + + + 2004 + 149 + 1273 + + + 2356 + 521 + 1288 + + + 2357 + 522 + 1286 + + + 2359 + 523 + 1287 + + + 2360 + 523 + 1289 + + + 2365 + 525 + 1298 + + + 2612 + 520 + 1274 + + + 2623 + 520 + 1274 + + + 2657 + 521 + 1273 + + + 2906 + 522 + 1275 + + + 2165 + 524 + 1275 + + + 2685 + 522 + 1278 + + + 2892 + 526 + 1286 + + + 2896 + 525 + 1278 + + + 2894 + 525 + 1288 + + + 2901 + 526 + 1295 + + + 2270 + 524 + 1279 + + + 1924 + 974 + 1282 + + + 2505 + 522 + 1275 + + + 2531 + 527 + 1276 + + + 2542 + 524 + 1275 + + + 2536 + 523 + 1286 + + + + diff --git a/tests/data/config/__init__.py b/tests/data/config/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/data/config/test.conf b/tests/data/config/test.conf new file mode 100644 index 00000000..94262784 --- /dev/null +++ b/tests/data/config/test.conf @@ -0,0 +1,18 @@ +[model] + model_path = '' + model_type = '50-layer' + +[atlas] + base_folder = '' + atlas_name = 'annotations.nii' + brain_name = 'brain_filtered.nii' + hemispheres_name = 'hemispheres.nii' + structures_name = 'structures.csv' + orientation = 'horizontal' + left_hemisphere_value = 2 + right_hemisphere_value = 1 + + [[pixel_size]] + x = 100 + y = 100 + z = 100 diff --git a/tests/data/cube_extract/cells.xml b/tests/data/cube_extract/cells.xml new file mode 100644 index 00000000..c8d5deba --- /dev/null +++ b/tests/data/cube_extract/cells.xml @@ -0,0 +1,22 @@ + + + + placeholder.tif + + + 1 + + 1 + + 340 + 1004 + 15 + + + 392 + 522 + 10 + + + + diff --git a/tests/data/cube_extract/cubes/pCellz10y522x392Ch0.tif b/tests/data/cube_extract/cubes/pCellz10y522x392Ch0.tif new file mode 100644 index 00000000..d5c60fae Binary files /dev/null and b/tests/data/cube_extract/cubes/pCellz10y522x392Ch0.tif differ diff --git a/tests/data/cube_extract/cubes/pCellz10y522x392Ch1.tif b/tests/data/cube_extract/cubes/pCellz10y522x392Ch1.tif new file mode 100644 index 00000000..1df64a6d Binary files /dev/null and b/tests/data/cube_extract/cubes/pCellz10y522x392Ch1.tif differ diff --git a/tests/data/cube_extract/cubes/pCellz15y1004x340Ch0.tif b/tests/data/cube_extract/cubes/pCellz15y1004x340Ch0.tif new file mode 100644 index 00000000..08cb9dec Binary files /dev/null and b/tests/data/cube_extract/cubes/pCellz15y1004x340Ch0.tif differ diff --git a/tests/data/cube_extract/cubes/pCellz15y1004x340Ch1.tif b/tests/data/cube_extract/cubes/pCellz15y1004x340Ch1.tif new file mode 100644 index 00000000..1cc9d859 Binary files /dev/null and b/tests/data/cube_extract/cubes/pCellz15y1004x340Ch1.tif differ diff --git a/tests/data/cube_extract/cubes_scale/pCellz10y522x392Ch0.tif b/tests/data/cube_extract/cubes_scale/pCellz10y522x392Ch0.tif new file mode 100644 index 00000000..bb5e0a97 Binary files /dev/null and b/tests/data/cube_extract/cubes_scale/pCellz10y522x392Ch0.tif differ diff --git a/tests/data/cube_extract/cubes_scale/pCellz10y522x392Ch1.tif b/tests/data/cube_extract/cubes_scale/pCellz10y522x392Ch1.tif new file mode 100644 index 00000000..6bef30b2 Binary files /dev/null and b/tests/data/cube_extract/cubes_scale/pCellz10y522x392Ch1.tif differ diff --git a/tests/data/cube_extract/cubes_scale/pCellz15y1004x340Ch0.tif b/tests/data/cube_extract/cubes_scale/pCellz15y1004x340Ch0.tif new file mode 100644 index 00000000..a0cabc2f Binary files /dev/null and b/tests/data/cube_extract/cubes_scale/pCellz15y1004x340Ch0.tif differ diff --git a/tests/data/cube_extract/cubes_scale/pCellz15y1004x340Ch1.tif b/tests/data/cube_extract/cubes_scale/pCellz15y1004x340Ch1.tif new file mode 100644 index 00000000..1b9acc69 Binary files /dev/null and b/tests/data/cube_extract/cubes_scale/pCellz15y1004x340Ch1.tif differ diff --git a/tests/data/image_processing/despeckled.tif b/tests/data/image_processing/despeckled.tif new file mode 100644 index 00000000..90969162 Binary files /dev/null and b/tests/data/image_processing/despeckled.tif differ diff --git a/tests/data/image_processing/flatfield.tif b/tests/data/image_processing/flatfield.tif new file mode 100644 index 00000000..7df7f147 Binary files /dev/null and b/tests/data/image_processing/flatfield.tif differ diff --git a/tests/data/integration/detection/cell_classification.xml b/tests/data/integration/detection/cell_classification.xml new file mode 100644 index 00000000..ac7b5b73 --- /dev/null +++ b/tests/data/integration/detection/cell_classification.xml @@ -0,0 +1,292 @@ + + + + placeholder.tif + + + 1 + + 2 + + 132 + 308 + 10 + + + 216 + 492 + 14 + + + 223 + 133 + 14 + + + 195 + 209 + 14 + + + 240 + 253 + 14 + + + 159 + 318 + 14 + + + 208 + 338 + 14 + + + 317 + 125 + 12 + + + 119 + 165 + 12 + + + 205 + 244 + 12 + + + 125 + 264 + 12 + + + 274 + 310 + 12 + + + 122 + 338 + 12 + + + 630 + 359 + 12 + + + 163 + 403 + 12 + + + 185 + 296 + 12 + + + 171 + 297 + 12 + + + 103 + 303 + 12 + + + 187 + 153 + 13 + + + 207 + 443 + 13 + + + 156 + 400 + 13 + + + 128 + 421 + 13 + + + 142 + 159 + 13 + + + 196 + 462 + 13 + + + 319 + 211 + 11 + + + 49 + 482 + 11 + + + 304 + 110 + 11 + + + 141 + 159 + 11 + + + 236 + 212 + 15 + + + 223 + 269 + 15 + + + 165 + 293 + 15 + + + 138 + 296 + 15 + + + 188 + 333 + 15 + + + 214 + 352 + 15 + + + 236 + 358 + 15 + + + 214 + 462 + 15 + + + 234 + 233 + 15 + + + 189 + 252 + 15 + + + 145 + 272 + 15 + + + 57 + 296 + 15 + + + 142 + 421 + 15 + + + 98 + 343 + 15 + + + 213 + 277 + 17 + + + 597 + 254 + 17 + + + 415 + 143 + 17 + + + 198 + 331 + 17 + + + 129 + 422 + 17 + + + 165 + 305 + 19 + + + 183 + 424 + 16 + + + 203 + 381 + 16 + + + 278 + 237 + 16 + + + 187 + 295 + 16 + + + 158 + 400 + 16 + + + 99 + 342 + 18 + + + 198 + 429 + 18 + + + 240 + 468 + 18 + + + + diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00000.tif b/tests/data/integration/detection/crop_planes/ch0/ch00000.tif new file mode 100644 index 00000000..abca45a0 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00000.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00001.tif b/tests/data/integration/detection/crop_planes/ch0/ch00001.tif new file mode 100644 index 00000000..7f59b3d0 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00001.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00002.tif b/tests/data/integration/detection/crop_planes/ch0/ch00002.tif new file mode 100644 index 00000000..c2b4eb96 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00002.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00003.tif b/tests/data/integration/detection/crop_planes/ch0/ch00003.tif new file mode 100644 index 00000000..eec563fe Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00003.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00004.tif b/tests/data/integration/detection/crop_planes/ch0/ch00004.tif new file mode 100644 index 00000000..11600d10 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00004.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00005.tif b/tests/data/integration/detection/crop_planes/ch0/ch00005.tif new file mode 100644 index 00000000..e6ff786d Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00005.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00006.tif b/tests/data/integration/detection/crop_planes/ch0/ch00006.tif new file mode 100644 index 00000000..d17b219a Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00006.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00007.tif b/tests/data/integration/detection/crop_planes/ch0/ch00007.tif new file mode 100644 index 00000000..93757586 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00007.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00008.tif b/tests/data/integration/detection/crop_planes/ch0/ch00008.tif new file mode 100644 index 00000000..879bd53a Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00008.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00009.tif b/tests/data/integration/detection/crop_planes/ch0/ch00009.tif new file mode 100644 index 00000000..1492fd49 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00009.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00010.tif b/tests/data/integration/detection/crop_planes/ch0/ch00010.tif new file mode 100644 index 00000000..9eccc8c9 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00010.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00011.tif b/tests/data/integration/detection/crop_planes/ch0/ch00011.tif new file mode 100644 index 00000000..a116ea35 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00011.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00012.tif b/tests/data/integration/detection/crop_planes/ch0/ch00012.tif new file mode 100644 index 00000000..7dd73e6c Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00012.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00013.tif b/tests/data/integration/detection/crop_planes/ch0/ch00013.tif new file mode 100644 index 00000000..768d0fb3 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00013.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00014.tif b/tests/data/integration/detection/crop_planes/ch0/ch00014.tif new file mode 100644 index 00000000..c8f9df08 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00014.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00015.tif b/tests/data/integration/detection/crop_planes/ch0/ch00015.tif new file mode 100644 index 00000000..5a128b1e Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00015.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00016.tif b/tests/data/integration/detection/crop_planes/ch0/ch00016.tif new file mode 100644 index 00000000..8c36d48e Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00016.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00017.tif b/tests/data/integration/detection/crop_planes/ch0/ch00017.tif new file mode 100644 index 00000000..e72594f3 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00017.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00018.tif b/tests/data/integration/detection/crop_planes/ch0/ch00018.tif new file mode 100644 index 00000000..90091d5b Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00018.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00019.tif b/tests/data/integration/detection/crop_planes/ch0/ch00019.tif new file mode 100644 index 00000000..1626c60c Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00019.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00020.tif b/tests/data/integration/detection/crop_planes/ch0/ch00020.tif new file mode 100644 index 00000000..6cef6e18 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00020.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00021.tif b/tests/data/integration/detection/crop_planes/ch0/ch00021.tif new file mode 100644 index 00000000..f17445dc Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00021.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00022.tif b/tests/data/integration/detection/crop_planes/ch0/ch00022.tif new file mode 100644 index 00000000..71ecb688 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00022.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00023.tif b/tests/data/integration/detection/crop_planes/ch0/ch00023.tif new file mode 100644 index 00000000..a9c3cfed Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00023.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00024.tif b/tests/data/integration/detection/crop_planes/ch0/ch00024.tif new file mode 100644 index 00000000..5bab6d10 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00024.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00025.tif b/tests/data/integration/detection/crop_planes/ch0/ch00025.tif new file mode 100644 index 00000000..082d90bc Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00025.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00026.tif b/tests/data/integration/detection/crop_planes/ch0/ch00026.tif new file mode 100644 index 00000000..390241c5 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00026.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00027.tif b/tests/data/integration/detection/crop_planes/ch0/ch00027.tif new file mode 100644 index 00000000..2f293dec Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00027.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00028.tif b/tests/data/integration/detection/crop_planes/ch0/ch00028.tif new file mode 100644 index 00000000..effeb8a2 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00028.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch0/ch00029.tif b/tests/data/integration/detection/crop_planes/ch0/ch00029.tif new file mode 100644 index 00000000..4cfec35b Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch0/ch00029.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10000.tif b/tests/data/integration/detection/crop_planes/ch1/ch10000.tif new file mode 100644 index 00000000..d4a2398f Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10000.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10001.tif b/tests/data/integration/detection/crop_planes/ch1/ch10001.tif new file mode 100644 index 00000000..801ca48c Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10001.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10002.tif b/tests/data/integration/detection/crop_planes/ch1/ch10002.tif new file mode 100644 index 00000000..74f9593b Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10002.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10003.tif b/tests/data/integration/detection/crop_planes/ch1/ch10003.tif new file mode 100644 index 00000000..21a5a049 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10003.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10004.tif b/tests/data/integration/detection/crop_planes/ch1/ch10004.tif new file mode 100644 index 00000000..15576026 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10004.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10005.tif b/tests/data/integration/detection/crop_planes/ch1/ch10005.tif new file mode 100644 index 00000000..53ac6f78 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10005.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10006.tif b/tests/data/integration/detection/crop_planes/ch1/ch10006.tif new file mode 100644 index 00000000..a7510b68 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10006.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10007.tif b/tests/data/integration/detection/crop_planes/ch1/ch10007.tif new file mode 100644 index 00000000..8dc0836f Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10007.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10008.tif b/tests/data/integration/detection/crop_planes/ch1/ch10008.tif new file mode 100644 index 00000000..8f9531b5 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10008.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10009.tif b/tests/data/integration/detection/crop_planes/ch1/ch10009.tif new file mode 100644 index 00000000..f4d89f97 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10009.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10010.tif b/tests/data/integration/detection/crop_planes/ch1/ch10010.tif new file mode 100644 index 00000000..fd995d0e Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10010.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10011.tif b/tests/data/integration/detection/crop_planes/ch1/ch10011.tif new file mode 100644 index 00000000..059d274a Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10011.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10012.tif b/tests/data/integration/detection/crop_planes/ch1/ch10012.tif new file mode 100644 index 00000000..045c9373 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10012.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10013.tif b/tests/data/integration/detection/crop_planes/ch1/ch10013.tif new file mode 100644 index 00000000..546b0793 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10013.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10014.tif b/tests/data/integration/detection/crop_planes/ch1/ch10014.tif new file mode 100644 index 00000000..72732ff2 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10014.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10015.tif b/tests/data/integration/detection/crop_planes/ch1/ch10015.tif new file mode 100644 index 00000000..08831473 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10015.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10016.tif b/tests/data/integration/detection/crop_planes/ch1/ch10016.tif new file mode 100644 index 00000000..d35b957c Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10016.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10017.tif b/tests/data/integration/detection/crop_planes/ch1/ch10017.tif new file mode 100644 index 00000000..c21d7ac9 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10017.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10018.tif b/tests/data/integration/detection/crop_planes/ch1/ch10018.tif new file mode 100644 index 00000000..47b97660 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10018.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10019.tif b/tests/data/integration/detection/crop_planes/ch1/ch10019.tif new file mode 100644 index 00000000..2a7577e0 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10019.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10020.tif b/tests/data/integration/detection/crop_planes/ch1/ch10020.tif new file mode 100644 index 00000000..99530a9f Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10020.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10021.tif b/tests/data/integration/detection/crop_planes/ch1/ch10021.tif new file mode 100644 index 00000000..243309b0 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10021.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10022.tif b/tests/data/integration/detection/crop_planes/ch1/ch10022.tif new file mode 100644 index 00000000..09d97b35 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10022.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10023.tif b/tests/data/integration/detection/crop_planes/ch1/ch10023.tif new file mode 100644 index 00000000..9d87ac4f Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10023.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10024.tif b/tests/data/integration/detection/crop_planes/ch1/ch10024.tif new file mode 100644 index 00000000..38fa3af3 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10024.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10025.tif b/tests/data/integration/detection/crop_planes/ch1/ch10025.tif new file mode 100644 index 00000000..05634da5 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10025.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10026.tif b/tests/data/integration/detection/crop_planes/ch1/ch10026.tif new file mode 100644 index 00000000..d9be83e7 Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10026.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10027.tif b/tests/data/integration/detection/crop_planes/ch1/ch10027.tif new file mode 100644 index 00000000..5daacc7c Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10027.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10028.tif b/tests/data/integration/detection/crop_planes/ch1/ch10028.tif new file mode 100644 index 00000000..146ce30e Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10028.tif differ diff --git a/tests/data/integration/detection/crop_planes/ch1/ch10029.tif b/tests/data/integration/detection/crop_planes/ch1/ch10029.tif new file mode 100644 index 00000000..1a9409ca Binary files /dev/null and b/tests/data/integration/detection/crop_planes/ch1/ch10029.tif differ diff --git a/tests/data/integration/training/cells/pCellz1132y413x1896Ch0.tif b/tests/data/integration/training/cells/pCellz1132y413x1896Ch0.tif new file mode 100644 index 00000000..682b0c1a Binary files /dev/null and b/tests/data/integration/training/cells/pCellz1132y413x1896Ch0.tif differ diff --git a/tests/data/integration/training/cells/pCellz1132y413x1896Ch1.tif b/tests/data/integration/training/cells/pCellz1132y413x1896Ch1.tif new file mode 100644 index 00000000..d3454156 Binary files /dev/null and b/tests/data/integration/training/cells/pCellz1132y413x1896Ch1.tif differ diff --git a/tests/data/integration/training/cells/pCellz1138y502x1662Ch0.tif b/tests/data/integration/training/cells/pCellz1138y502x1662Ch0.tif new file mode 100644 index 00000000..a7dd151f Binary files /dev/null and b/tests/data/integration/training/cells/pCellz1138y502x1662Ch0.tif differ diff --git a/tests/data/integration/training/cells/pCellz1138y502x1662Ch1.tif b/tests/data/integration/training/cells/pCellz1138y502x1662Ch1.tif new file mode 100644 index 00000000..c55cad07 Binary files /dev/null and b/tests/data/integration/training/cells/pCellz1138y502x1662Ch1.tif differ diff --git a/tests/data/integration/training/non_cells/pCellz1137y278x1616Ch0.tif b/tests/data/integration/training/non_cells/pCellz1137y278x1616Ch0.tif new file mode 100644 index 00000000..0dc4da1d Binary files /dev/null and b/tests/data/integration/training/non_cells/pCellz1137y278x1616Ch0.tif differ diff --git a/tests/data/integration/training/non_cells/pCellz1137y278x1616Ch1.tif b/tests/data/integration/training/non_cells/pCellz1137y278x1616Ch1.tif new file mode 100644 index 00000000..ed817eab Binary files /dev/null and b/tests/data/integration/training/non_cells/pCellz1137y278x1616Ch1.tif differ diff --git a/tests/data/integration/training/non_cells/pCellz1137y426x1996Ch0.tif b/tests/data/integration/training/non_cells/pCellz1137y426x1996Ch0.tif new file mode 100644 index 00000000..48a94570 Binary files /dev/null and b/tests/data/integration/training/non_cells/pCellz1137y426x1996Ch0.tif differ diff --git a/tests/data/integration/training/non_cells/pCellz1137y426x1996Ch1.tif b/tests/data/integration/training/non_cells/pCellz1137y426x1996Ch1.tif new file mode 100644 index 00000000..771cde8e Binary files /dev/null and b/tests/data/integration/training/non_cells/pCellz1137y426x1996Ch1.tif differ diff --git a/tests/data/integration/training/training.yml b/tests/data/integration/training/training.yml new file mode 100644 index 00000000..90e0a634 --- /dev/null +++ b/tests/data/integration/training/training.yml @@ -0,0 +1,11 @@ +data: +- bg_channel: 1 + cell_def: '' + cube_dir: tests/data/integration/training/cells + signal_channel: 0 + type: cell +- bg_channel: 1 + cell_def: '' + cube_dir: tests/data/integration/training/cells + signal_channel: 0 + type: no_cell diff --git a/tests/data/registration_output/Linux/boundaries.tiff b/tests/data/registration_output/Linux/boundaries.tiff new file mode 100644 index 00000000..76754cc1 Binary files /dev/null and b/tests/data/registration_output/Linux/boundaries.tiff differ diff --git a/tests/data/registration_output/Linux/deformation_field_0.tiff b/tests/data/registration_output/Linux/deformation_field_0.tiff new file mode 100644 index 00000000..3947ceef Binary files /dev/null and b/tests/data/registration_output/Linux/deformation_field_0.tiff differ diff --git a/tests/data/registration_output/Linux/deformation_field_1.tiff b/tests/data/registration_output/Linux/deformation_field_1.tiff new file mode 100644 index 00000000..793184bd Binary files /dev/null and b/tests/data/registration_output/Linux/deformation_field_1.tiff differ diff --git a/tests/data/registration_output/Linux/deformation_field_2.tiff b/tests/data/registration_output/Linux/deformation_field_2.tiff new file mode 100644 index 00000000..62c97cdf Binary files /dev/null and b/tests/data/registration_output/Linux/deformation_field_2.tiff differ diff --git a/tests/data/registration_output/Linux/downsampled.tiff b/tests/data/registration_output/Linux/downsampled.tiff new file mode 100644 index 00000000..68270cb2 Binary files /dev/null and b/tests/data/registration_output/Linux/downsampled.tiff differ diff --git a/tests/data/registration_output/Linux/downsampled_channel_0.tiff b/tests/data/registration_output/Linux/downsampled_channel_0.tiff new file mode 100644 index 00000000..68270cb2 Binary files /dev/null and b/tests/data/registration_output/Linux/downsampled_channel_0.tiff differ diff --git a/tests/data/registration_output/Linux/downsampled_standard.tiff b/tests/data/registration_output/Linux/downsampled_standard.tiff new file mode 100644 index 00000000..60ea2df9 Binary files /dev/null and b/tests/data/registration_output/Linux/downsampled_standard.tiff differ diff --git a/tests/data/registration_output/Linux/downsampled_standard_channel_0.tiff b/tests/data/registration_output/Linux/downsampled_standard_channel_0.tiff new file mode 100644 index 00000000..60ea2df9 Binary files /dev/null and b/tests/data/registration_output/Linux/downsampled_standard_channel_0.tiff differ diff --git a/tests/data/registration_output/Linux/registered_atlas.tiff b/tests/data/registration_output/Linux/registered_atlas.tiff new file mode 100644 index 00000000..98431721 Binary files /dev/null and b/tests/data/registration_output/Linux/registered_atlas.tiff differ diff --git a/tests/data/registration_output/Linux/registered_hemispheres.tiff b/tests/data/registration_output/Linux/registered_hemispheres.tiff new file mode 100644 index 00000000..6a4af26c Binary files /dev/null and b/tests/data/registration_output/Linux/registered_hemispheres.tiff differ diff --git a/tests/data/registration_output/Linux/volumes.csv b/tests/data/registration_output/Linux/volumes.csv new file mode 100644 index 00000000..91416932 --- /dev/null +++ b/tests/data/registration_output/Linux/volumes.csv @@ -0,0 +1,663 @@ +structure_name,left_volume_mm3,right_volume_mm3,total_volume_mm3 +"Tuberomammillary nucleus, ventral part",0.057,0.056,0.113 +"Primary somatosensory area, mouth, layer 6b",0.06,0.061,0.121 +internal capsule,1.025,1.049,2.074 +Principal sensory nucleus of the trigeminal,0.589,0.5630000000000001,1.1520000000000001 +"Primary somatosensory area, trunk, layer 6a",0.138,0.114,0.252 +"Superior colliculus, motor related, intermediate gray layer",0.966,1.027,1.9929999999999999 +Interfascicular nucleus raphe,0.033,0.058,0.091 +Parataenial nucleus,0.11800000000000001,0.122,0.24 +"Superior colliculus, motor related, intermediate white layer",0.99,1.073,2.0629999999999997 +Induseum griseum,0.032,0.07200000000000001,0.10400000000000001 +"Entorhinal area, lateral part, layer 2",0.803,0.8,1.6030000000000002 +Anterior amygdalar area,0.23700000000000002,0.242,0.479 +"Superior colliculus, motor related, deep gray layer",0.5690000000000001,0.596,1.165 +Intergeniculate leaflet of the lateral geniculate complex,0.036000000000000004,0.035,0.07100000000000001 +"Entorhinal area, lateral part, layer 6a",0.545,0.528,1.073 +"Primary visual area, layer 6a",0.527,0.522,1.049 +Oculomotor nucleus,0.013000000000000001,0.014,0.027000000000000003 +"Gustatory areas, layer 1",0.1,0.101,0.201 +Paraventricular hypothalamic nucleus,0.089,0.098,0.187 +"posteromedial visual area, layer 2/3",0.14100000000000001,0.154,0.29500000000000004 +"Superior colliculus, motor related, deep white layer",0.162,0.158,0.32 +Precommissural nucleus,0.098,0.101,0.199 +"Entorhinal area, lateral part, layer 3",0.673,0.649,1.322 +medial forebrain bundle,0.03,0.024,0.054 +Nucleus accumbens,2.236,2.226,4.462 +Medial terminal nucleus of the accessory optic tract,0.026000000000000002,0.025,0.051000000000000004 +Intermediodorsal nucleus of the thalamus,0.045,0.137,0.182 +medial longitudinal fascicle,0.041,0.046,0.087 +"Paraventricular hypothalamic nucleus, descending division",0.075,0.065,0.14 +Anterodorsal nucleus,0.083,0.075,0.158 +Lateral terminal nucleus of the accessory optic tract,0.01,0.009000000000000001,0.019000000000000003 +Interstitial nucleus of Cajal,0.049,0.047,0.096 +"Frontal pole, layer 1",0.112,0.123,0.235 +Anterodorsal preoptic nucleus,0.053,0.053,0.106 +"Lateral visual area, layer 6a",0.10200000000000001,0.101,0.203 +Dorsal terminal nucleus of the accessory optic tract,0.006,0.006,0.012 +middle cerebellar peduncle,0.52,0.518,1.038 +lateral ventricle,1.002,1.114,2.116 +Inferior olivary complex,0.23800000000000002,0.256,0.494 +"Prelimbic area, layer 6a",0.212,0.23700000000000002,0.449 +Anterior hypothalamic nucleus,0.388,0.375,0.763 +Interposed nucleus,0.396,0.428,0.8240000000000001 +motor root of the trigeminal nerve,0.031,0.033,0.064 +Dorsal cochlear nucleus,0.302,0.317,0.619 +"Temporal association areas, layer 1",0.254,0.252,0.506 +subependymal zone,0.063,0.066,0.129 +Interpeduncular nucleus,0.003,0.006,0.009000000000000001 +Ventral cochlear nucleus,0.531,0.537,1.068 +nigrostriatal tract,0.054,0.064,0.118 +"Superior olivary complex, medial part",0.10200000000000001,0.10300000000000001,0.20500000000000002 +Inferior salivatory nucleus,0.005,0.005,0.01 +choroid plexus,0.638,0.775,1.413 +"Primary somatosensory area, lower limb, layer 2/3",0.357,0.34600000000000003,0.7030000000000001 +"Superior olivary complex, lateral part",0.17300000000000001,0.176,0.349 +Trochlear nucleus,0.003,0.003,0.006 +optic chiasm,0.151,0.17500000000000002,0.326 +"Periventricular hypothalamic nucleus, intermediate part",0.029,0.121,0.15 +"Agranular insular area, posterior part, layer 1",0.215,0.221,0.436 +"Lateral visual area, layer 6b",0.017,0.017,0.034 +"Superior olivary complex, periolivary region",0.196,0.192,0.388 +Koelliker-Fuse subnucleus,0.08600000000000001,0.08600000000000001,0.17200000000000001 +optic tract,0.34400000000000003,0.367,0.7110000000000001 +"Periventricular hypothalamic nucleus, posterior part",0.058,0.064,0.122 +Midbrain reticular nucleus,2.6390000000000002,2.589,5.228 +third ventricle,0.26,0.796,1.056 +Lateral amygdalar nucleus,0.417,0.43,0.847 +"Prelimbic area, layer 6b",0.011,0.008,0.019 +"Periventricular hypothalamic nucleus, preoptic part",0.022,0.096,0.118 +Intermediate reticular nucleus,1.397,1.418,2.815 +"Entorhinal area, lateral part, layer 5",0.709,0.713,1.422 +cerebral aqueduct,0.156,0.266,0.42200000000000004 +"Nucleus ambiguus, ventral division",0.008,0.009000000000000001,0.017 +fourth ventricle,0.227,0.299,0.526 +Pontine reticular nucleus,1.192,1.175,2.367 +Locus ceruleus,0.007,0.006,0.013000000000000001 +"Gustatory areas, layer 4",0.07200000000000001,0.069,0.14100000000000001 +Paraventricular nucleus of the thalamus,0.17,0.273,0.44300000000000006 +lateral recess,0.23800000000000002,0.23800000000000002,0.47600000000000003 +Lateral dorsal nucleus of thalamus,0.528,0.486,1.014 +"Dorsal auditory area, layer 6a",0.107,0.098,0.20500000000000002 +posterior commissure,0.019,0.03,0.049 +Anterior olfactory nucleus,2.448,2.497,4.945 +Laterodorsal tegmental nucleus,0.089,0.10300000000000001,0.192 +"Agranular insular area, posterior part, layer 2/3",0.397,0.402,0.799 +Nucleus prepositus,0.112,0.128,0.24 +"Prelimbic area, layer 1",0.209,0.328,0.537 +Retrochiasmatic area,0.077,0.068,0.14500000000000002 +Nucleus of Roller,0.014,0.017,0.031 +Ventral part of the lateral geniculate complex,0.21,0.2,0.41000000000000003 +"Gustatory areas, layer 2/3",0.211,0.217,0.428 +Nucleus of reuniens,0.20500000000000002,0.229,0.43400000000000005 +Lateral habenula,0.159,0.161,0.32 +"Gustatory areas, layer 5",0.266,0.279,0.545 +"Accessory olfactory bulb, glomerular layer",0.065,0.079,0.14400000000000002 +Rhomboid nucleus,0.035,0.05,0.085 +pyramid,0.29,0.293,0.583 +Lateral hypothalamic area,1.077,1.075,2.152 +"Accessory olfactory bulb, granular layer",0.08700000000000001,0.11,0.197 +Rostral linear nucleus raphe,0.011,0.04,0.051000000000000004 +pyramidal decussation,0.017,0.043000000000000003,0.060000000000000005 +"Primary somatosensory area, barrel field, layer 2/3",0.738,0.765,1.5030000000000001 +Medial vestibular nucleus,0.873,0.9470000000000001,1.82 +Linear nucleus of the medulla,0.029,0.036000000000000004,0.065 +"Accessory olfactory bulb, mitral layer",0.131,0.149,0.28 +Area postrema,0.019,0.035,0.054000000000000006 +Lateral vestibular nucleus,0.128,0.14400000000000002,0.272 +Lateral mammillary nucleus,0.036000000000000004,0.037,0.07300000000000001 +"Anterior cingulate area, dorsal part, layer 2/3",0.233,0.241,0.474 +Red nucleus,0.362,0.418,0.78 +Anterior pretectal nucleus,0.624,0.635,1.259 +Superior vestibular nucleus,0.159,0.17400000000000002,0.333 +Lateral posterior nucleus of the thalamus,0.598,0.616,1.214 +Arcuate hypothalamic nucleus,0.147,0.163,0.31 +Spinal vestibular nucleus,0.385,0.385,0.77 +Lateral preoptic area,0.246,0.273,0.519 +sensory root of the trigeminal nerve,0.332,0.356,0.688 +Anterior tegmental nucleus,0.018000000000000002,0.017,0.035 +"Anterolateral visual area, layer 5",0.109,0.09,0.199 +"Temporal association areas, layer 4",0.159,0.148,0.307 +solitary tract,0.006,0.005,0.011 +Nucleus raphe pontis,0.034,0.044,0.078 +"Dorsal auditory area, layer 6b",0.015,0.018000000000000002,0.033 +"Midbrain reticular nucleus, retrorubral area",0.074,0.065,0.139 +"Posterior auditory area, layer 6a",0.039,0.041,0.08 +"Lateral septal nucleus, caudal (caudodorsal) part",0.265,0.321,0.5860000000000001 +"Primary auditory area, layer 2/3",0.251,0.23500000000000001,0.486 +"Dorsal auditory area, layer 5",0.199,0.165,0.364 +Anteroventral nucleus of thalamus,0.2,0.213,0.41300000000000003 +"posteromedial visual area, layer 6a",0.07200000000000001,0.066,0.138 +"Lateral septal nucleus, rostral (rostroventral) part",0.961,0.9540000000000001,1.915 +"Nucleus of the lateral olfactory tract, molecular layer",0.053,0.049,0.10200000000000001 +Reticular nucleus of the thalamus,0.732,0.726,1.458 +Anteroventral preoptic nucleus,0.04,0.047,0.087 +"Lateral septal nucleus, ventral part",0.297,0.298,0.595 +"Nucleus of the lateral olfactory tract, pyramidal layer",0.076,0.075,0.151 +"Posterolateral visual area, layer 2/3",0.095,0.11900000000000001,0.21400000000000002 +Nucleus sagulum,0.046,0.054,0.1 +Anteroventral periventricular nucleus,0.078,0.095,0.173 +"Retrosplenial area, dorsal part, layer 6a",0.389,0.374,0.763 +"Retrosplenial area, lateral agranular part, layer 6b",0.019,0.019,0.038 +Barrington's nucleus,0.004,0.007,0.011 +"Anteromedial visual area, layer 1",0.07200000000000001,0.057,0.129 +Suprachiasmatic nucleus,0.038,0.041,0.079 +Bed nucleus of the anterior commissure,0.004,0.005,0.009000000000000001 +"Orbital area, ventrolateral part, layer 2/3",0.263,0.254,0.517 +"Temporal association areas, layer 5",0.463,0.47200000000000003,0.935 +Bed nucleus of the accessory olfactory tract,0.016,0.012,0.028 +"Anterior cingulate area, ventral part, layer 2/3",0.218,0.20700000000000002,0.42500000000000004 +Magnocellular nucleus,0.168,0.185,0.353 +stria terminalis,0.149,0.14100000000000001,0.29000000000000004 +"Basolateral amygdalar nucleus, anterior part",0.388,0.392,0.78 +"Prelimbic area, layer 2/3",0.176,0.183,0.359 +"Primary visual area, layer 6b",0.082,0.101,0.183 +Magnocellular reticular nucleus,0.276,0.263,0.539 +Septofimbrial nucleus,0.216,0.267,0.483 +"Basolateral amygdalar nucleus, posterior part",0.368,0.37,0.738 +Midbrain,3.204,3.451,6.655 +"Agranular insular area, posterior part, layer 6a",0.214,0.20400000000000001,0.41800000000000004 +Supragenual nucleus,0.007,0.009000000000000001,0.016 +"Primary motor area, Layer 1",0.656,0.657,1.3130000000000002 +Subgeniculate nucleus,0.012,0.013000000000000001,0.025 +Suprageniculate nucleus,0.099,0.092,0.191 +superior cerebelar peduncles,0.20500000000000002,0.20800000000000002,0.41300000000000003 +"Basomedial amygdalar nucleus, anterior part",0.402,0.406,0.808 +"Agranular insular area, dorsal part, layer 2/3",0.451,0.452,0.903 +"Retrosplenial area, dorsal part, layer 6b",0.02,0.022,0.041999999999999996 +Accessory supraoptic group,0.001,0.002,0.003 +Septohippocampal nucleus,0.018000000000000002,0.016,0.034 +"Basomedial amygdalar nucleus, posterior part",0.372,0.357,0.729 +"Perirhinal area, layer 6a",0.026000000000000002,0.038,0.064 +superior colliculus commissure,0.012,0.023,0.035 +Subfornical organ,0.007,0.015,0.022 +Substantia innominata,1.573,1.553,3.126 +"Agranular insular area, posterior part, layer 5",0.383,0.388,0.771 +Subparaventricular zone,0.074,0.048,0.122 +supraoptic commissures,0.015,0.016,0.031 +Subceruleus nucleus,0.014,0.015,0.028999999999999998 +Bed nuclei of the stria terminalis,0.687,0.668,1.355 +Medulla,2.581,2.854,5.4350000000000005 +"Agranular insular area, posterior part, layer 6b",0.012,0.009000000000000001,0.021 +Preparasubthalamic nucleus,0.007,0.01,0.017 +Sublaterodorsal nucleus,0.021,0.022,0.043 +Mediodorsal nucleus of thalamus,0.6910000000000001,0.683,1.374 +"Prelimbic area, layer 5",0.504,0.498,1.002 +Parasubthalamic nucleus,0.079,0.088,0.16699999999999998 +Submedial nucleus of the thalamus,0.133,0.157,0.29000000000000004 +"Perirhinal area, layer 6b",0.007,0.009000000000000001,0.016 +Infracerebellar nucleus,0.029,0.025,0.054000000000000006 +"Substantia nigra, compact part",0.1,0.10300000000000001,0.203 +"Posterolateral visual area, layer 6a",0.042,0.049,0.091 +cuneate fascicle,0.007,0.01,0.017 +"Substantia nigra, reticular part",0.778,0.721,1.499 +Field CA1,5.165,5.13,10.295 +Supraoptic nucleus,0.019,0.026000000000000002,0.045 +"Posterolateral visual area, layer 6b",0.004,0.005,0.009000000000000001 +ventral tegmental decussation,0.018000000000000002,0.032,0.05 +"Anteromedial visual area, layer 4",0.032,0.029,0.061 +Medial amygdalar nucleus,1.074,1.072,2.146 +"Orbital area, lateral part, layer 2/3",0.305,0.3,0.605 +vestibular nerve,0.116,0.115,0.231 +"Subparafascicular nucleus, magnocellular part",0.039,0.033,0.07200000000000001 +"Lateral visual area, layer 1",0.099,0.089,0.188 +"Subparafascicular nucleus, parvicellular part",0.075,0.064,0.139 +Field CA2,0.224,0.223,0.447 +Ectorhinal area/Layer 2/3,0.246,0.23900000000000002,0.485 +medial corticohypothalamic tract,0.005,0.005,0.01 +"Spinal nucleus of the trigeminal, caudal part",0.807,0.806,1.613 +"Retrosplenial area, ventral part, layer 2/3",0.539,0.514,1.053 +"Anteromedial visual area, layer 5",0.116,0.121,0.237 +"Retrosplenial area, dorsal part, layer 2/3",0.482,0.483,0.965 +columns of the fornix,0.139,0.147,0.28600000000000003 +"Spinal nucleus of the trigeminal, interpolar part",0.924,0.915,1.839 +"Orbital area, lateral part, layer 6a",0.23600000000000002,0.23500000000000001,0.47100000000000003 +"Anteromedial visual area, layer 6b",0.014,0.015,0.028999999999999998 +"Retrosplenial area, dorsal part, layer 1",0.399,0.418,0.817 +dorsal hippocampal commissure,0.47000000000000003,0.48,0.95 +"Spinal nucleus of the trigeminal, oral part",0.52,0.535,1.0550000000000002 +"Orbital area, lateral part, layer 1",0.181,0.192,0.373 +ventral hippocampal commissure,0.03,0.04,0.07 +"Primary somatosensory area, upper limb, layer 1",0.245,0.268,0.513 +"Basolateral amygdalar nucleus, ventral part",0.229,0.212,0.441 +Median preoptic nucleus,0.002,0.034,0.036000000000000004 +"Posterior auditory area, layer 6b",0.008,0.008,0.016 +Midbrain trigeminal nucleus,0.004,0.006,0.01 +"Primary somatosensory area, trunk, layer 6b",0.021,0.022,0.043 +Field CA3,3.173,3.082,6.255 +alveus,0.6890000000000001,0.7030000000000001,1.3920000000000001 +"posteromedial visual area, layer 6b",0.016,0.016,0.032 +Subthalamic nucleus,0.10300000000000001,0.106,0.20900000000000002 +Striatum,1.334,1.419,2.753 +"Primary somatosensory area, lower limb, layer 6a",0.312,0.243,0.5549999999999999 +brachium of the inferior colliculus,0.113,0.122,0.235 +Medial habenula,0.159,0.15,0.309 +"Orbital area, medial part, layer 1",0.17,0.267,0.43700000000000006 +"Orbital area, lateral part, layer 6b",0.018000000000000002,0.021,0.03900000000000001 +"posteromedial visual area, layer 4",0.039,0.042,0.081 +Subiculum,1.098,1.045,2.143 +dorsal acoustic stria,0.006,0.004,0.01 +Main olfactory bulb,3.379,3.755,7.134 +"Primary somatosensory area, lower limb, layer 6b",0.023,0.023,0.046 +Cerebellum,0.41400000000000003,0.419,0.833 +Medial preoptic nucleus,0.203,0.211,0.41400000000000003 +"Ventral auditory area, layer 6a",0.138,0.14300000000000002,0.281 +Medial preoptic area,0.269,0.28800000000000003,0.557 +Supramammillary nucleus,0.125,0.14,0.265 +"Entorhinal area, medial part, dorsal zone, layer 1",0.644,0.636,1.28 +"Dorsal auditory area, layer 1",0.07200000000000001,0.094,0.166 +dorsal fornix,0.009000000000000001,0.017,0.026000000000000002 +Medial pretectal area,0.024,0.023,0.047 +Supratrigeminal nucleus,0.132,0.116,0.248 +dorsal limb,0.07100000000000001,0.08,0.15100000000000002 +"Perirhinal area, layer 1",0.117,0.113,0.23 +"Retrosplenial area, ventral part, layer 1",0.322,0.5720000000000001,0.8940000000000001 +"Entorhinal area, medial part, dorsal zone, layer 2",0.671,0.657,1.328 +"Central amygdalar nucleus, capsular part",0.147,0.176,0.32299999999999995 +Thalamus,0.439,0.446,0.885 +"Central amygdalar nucleus, lateral part",0.128,0.135,0.263 +dorsal spinocerebellar tract,0.074,0.079,0.153 +"Infralimbic area, layer 2/3",0.078,0.074,0.152 +"Primary somatosensory area, nose, layer 1",0.209,0.20800000000000002,0.41700000000000004 +"Central amygdalar nucleus, medial part",0.365,0.377,0.742 +Medial septal nucleus,0.11900000000000001,0.281,0.4 +"posteromedial visual area, layer 5",0.136,0.146,0.28200000000000003 +Postpiriform transition area,0.634,0.634,1.268 +"Lateral visual area, layer 4",0.096,0.085,0.181 +Tegmental reticular nucleus,0.36,0.343,0.7030000000000001 +Central lateral nucleus of the thalamus,0.166,0.183,0.349 +Accessory facial motor nucleus,0.002,0.001,0.003 +"Primary somatosensory area, upper limb, layer 4",0.264,0.219,0.483 +external capsule,0.443,0.45,0.893 +Nucleus of the brachium of the inferior colliculus,0.043000000000000003,0.047,0.09 +Triangular nucleus of septum,0.16,0.199,0.359 +"Orbital area, medial part, layer 2/3",0.151,0.15,0.301 +Claustrum,0.272,0.276,0.548 +Nucleus of Darkschewitsch,0.059000000000000004,0.062,0.121 +"Anterior cingulate area, ventral part, layer 1",0.194,0.339,0.533 +"Retrosplenial area, ventral part, layer 6a",0.322,0.308,0.63 +Central linear nucleus raphe,0.038,0.063,0.101 +"Primary visual area, layer 1",0.628,0.628,1.256 +fasciculus retroflexus,0.084,0.082,0.166 +Diagonal band nucleus,0.342,0.402,0.744 +"Taenia tecta, dorsal part",0.34700000000000003,0.391,0.738 +"Ventral auditory area, layer 6b",0.021,0.024,0.045 +Central medial nucleus of the thalamus,0.098,0.156,0.254 +"Dorsal auditory area, layer 2/3",0.15,0.14300000000000002,0.29300000000000004 +"Anterolateral visual area, layer 6a",0.061,0.047,0.108 +fimbria,0.787,0.728,1.5150000000000001 +Nucleus incertus,0.035,0.07100000000000001,0.10600000000000001 +"Taenia tecta, ventral part",0.387,0.374,0.761 +"Orbital area, ventrolateral part, layer 6a",0.113,0.10400000000000001,0.21700000000000003 +Subparafascicular area,0.053,0.089,0.142 +"Retrosplenial area, dorsal part, layer 5",0.615,0.603,1.218 +habenular commissure,0.016,0.023,0.039 +Nucleus of the lateral lemniscus,0.387,0.375,0.762 +"Lateral visual area, layer 5",0.167,0.151,0.318 +Tuberal nucleus,0.259,0.293,0.552 +Cuneiform nucleus,0.256,0.28600000000000003,0.542 +"Orbital area, medial part, layer 5",0.222,0.233,0.455 +Motor nucleus of trigeminal,0.183,0.187,0.37 +"Retrosplenial area, ventral part, layer 6b",0.024,0.026000000000000002,0.05 +"Primary somatosensory area, upper limb, layer 5",0.316,0.34500000000000003,0.661 +Nucleus of the optic tract,0.099,0.106,0.20500000000000002 +Ventral anterior-lateral complex of the thalamus,0.401,0.399,0.8 +"Orbital area, lateral part, layer 5",0.601,0.551,1.1520000000000001 +"Dentate gyrus, granule cell layer",0.8170000000000001,0.8220000000000001,1.6390000000000002 +inferior colliculus commissure,0.009000000000000001,0.011,0.02 +Nucleus of the posterior commissure,0.147,0.153,0.3 +"Gustatory areas, layer 6a",0.20800000000000002,0.224,0.43200000000000005 +"Cortical amygdalar area, anterior part",0.40900000000000003,0.401,0.81 +Nucleus of the trapezoid body,0.08,0.08,0.16 +"Posterior auditory area, layer 2/3",0.07200000000000001,0.07100000000000001,0.14300000000000002 +"Primary motor area, Layer 5",1.585,1.6480000000000001,3.233 +"Anterolateral visual area, layer 6b",0.02,0.015,0.035 +Nucleus of the solitary tract,0.421,0.451,0.872 +Abducens nucleus,0.016,0.019,0.035 +"Primary somatosensory area, nose, layer 4",0.263,0.271,0.534 +"Cortical amygdalar area, posterior part, lateral zone",0.599,0.639,1.238 +"Secondary motor area, layer 1",1.235,1.171,2.406 +"Primary somatosensory area, mouth, layer 2/3",0.749,0.757,1.506 +lateral lemniscus,0.434,0.421,0.855 +Facial motor nucleus,0.46,0.487,0.9470000000000001 +"Gustatory areas, layer 6b",0.026000000000000002,0.022,0.048 +"Cortical amygdalar area, posterior part, medial zone",0.636,0.654,1.29 +"Entorhinal area, medial part, dorsal zone, layer 3",0.514,0.498,1.012 +"lateral olfactory tract, body",0.47800000000000004,0.47800000000000004,0.9560000000000001 +"Frontal pole, layer 2/3",0.113,0.125,0.238 +"Primary somatosensory area, trunk, layer 2/3",0.179,0.20800000000000002,0.387 +"Retrosplenial area, lateral agranular part, layer 1",0.241,0.244,0.485 +Caudoputamen,12.943,13.077,26.02 +mammillary peduncle,0.017,0.017,0.034 +"Agranular insular area, ventral part, layer 6a",0.08700000000000001,0.089,0.176 +"Dorsal auditory area, layer 4",0.067,0.059000000000000004,0.126 +Superior central nucleus raphe,0.274,0.343,0.617 +"Orbital area, ventrolateral part, layer 6b",0.003,0.003,0.006 +mammillotegmental tract,0.029,0.024,0.053000000000000005 +Ventral medial nucleus of the thalamus,0.482,0.504,0.986 +"Retrosplenial area, ventral part, layer 5",0.8160000000000001,0.8260000000000001,1.6420000000000001 +Ventrolateral preoptic nucleus,0.036000000000000004,0.03,0.066 +mammillothalamic tract,0.063,0.065,0.128 +"Perirhinal area, layer 5",0.085,0.084,0.169 +Ventromedial hypothalamic nucleus,0.27,0.275,0.545 +"Agranular insular area, ventral part, layer 2/3",0.28700000000000003,0.295,0.5820000000000001 +"Posterior auditory area, layer 1",0.053,0.052000000000000005,0.10500000000000001 +medial lemniscus,0.34800000000000003,0.327,0.675 +Olfactory areas,1.3900000000000001,1.487,2.8770000000000002 +"Agranular insular area, ventral part, layer 6b",0.001,0.001,0.002 +"Primary somatosensory area, nose, layer 5",0.308,0.28800000000000003,0.5960000000000001 +Cortical subplate,0.186,0.195,0.381 +"Agranular insular area, ventral part, layer 1",0.123,0.117,0.24 +Olivary pretectal nucleus,0.03,0.03,0.06 +"Infralimbic area, layer 1",0.044,0.10200000000000001,0.14600000000000002 +Cuneate nucleus,0.167,0.167,0.334 +Ventral posterolateral nucleus of the thalamus,0.47400000000000003,0.48,0.954 +"Primary visual area, layer 4",0.494,0.506,1.0 +"Ventral posterolateral nucleus of the thalamus, parvicellular part",0.04,0.051000000000000004,0.091 +"Entorhinal area, medial part, dorsal zone, layer 5",0.47800000000000004,0.461,0.9390000000000001 +arbor vitae,3.358,3.416,6.774 +"Temporal association areas, layer 6a",0.258,0.261,0.519 +"Medial mammillary nucleus, median part",0.025,0.053,0.078 +Ventral posteromedial nucleus of the thalamus,0.8200000000000001,0.845,1.665 +"Primary auditory area, layer 1",0.2,0.185,0.385 +"Ventral posteromedial nucleus of the thalamus, parvicellular part",0.11900000000000001,0.139,0.258 +"Entorhinal area, medial part, dorsal zone, layer 6",0.337,0.317,0.654 +cerebellar commissure,0.028,0.033,0.061 +Ventral tegmental area,0.222,0.226,0.448 +"Posterolateral visual area, layer 1",0.096,0.099,0.195 +principal mammillary tract,0.017,0.021,0.038000000000000006 +Olfactory tubercle,1.982,1.993,3.975 +"Ventral auditory area, layer 2/3",0.192,0.209,0.401 +Ventral tegmental nucleus,0.014,0.015,0.028999999999999998 +"Posterior auditory area, layer 4",0.044,0.038,0.08199999999999999 +Nucleus x,0.027,0.027,0.054 +"Secondary motor area, layer 5",2.351,2.101,4.452 +Pons,1.722,1.951,3.673 +"Anterior cingulate area, ventral part, layer 5",0.559,0.546,1.105 +Hypoglossal nucleus,0.131,0.14100000000000001,0.272 +"Retrosplenial area, lateral agranular part, layer 5",0.36,0.359,0.719 +"Primary visual area, layer 5",0.756,0.773,1.529 +Posterior amygdalar nucleus,0.47900000000000004,0.488,0.9670000000000001 +Nucleus y,0.011,0.013000000000000001,0.024 +"Agranular insular area, dorsal part, layer 6a",0.397,0.393,0.79 +corticospinal tract,0.044,0.049,0.093 +"Temporal association areas, layer 6b",0.042,0.032,0.07400000000000001 +Piriform-amygdalar area,0.607,0.648,1.255 +"Posterior auditory area, layer 5",0.093,0.095,0.188 +spinal tract of the trigeminal nerve,0.846,0.838,1.684 +Periaqueductal gray,1.962,2.165,4.127 +Zona incerta,0.782,0.726,1.508 +facial nerve,0.039,0.039,0.078 +"Agranular insular area, ventral part, layer 5",0.36,0.359,0.719 +stria medullaris,0.14100000000000001,0.134,0.275 +Pallidum,0.5760000000000001,0.5680000000000001,1.1440000000000001 +Fields of Forel,0.132,0.109,0.241 +"posteromedial visual area, layer 1",0.088,0.098,0.186 +"Supplemental somatosensory area, layer 2/3",1.061,1.029,2.09 +"Anterior cingulate area, ventral part, 6a",0.198,0.176,0.374 +"Inferior colliculus, central nucleus",0.535,0.5730000000000001,1.108 +superior cerebellar peduncle decussation,0.013000000000000001,0.03,0.043 +Dorsal peduncular area,0.234,0.267,0.501 +"Primary auditory area, layer 4",0.125,0.114,0.239 +"Anterior cingulate area, ventral part, 6b",0.035,0.029,0.064 +"Inferior colliculus, dorsal nucleus",0.664,0.652,1.316 +"Primary visual area, layer 2/3",0.975,0.981,1.956 +"Infralimbic area, layer 5",0.14400000000000002,0.135,0.279 +"Inferior colliculus, external nucleus",1.016,1.004,2.02 +Dorsomedial nucleus of the hypothalamus,0.21,0.178,0.388 +"Agranular insular area, dorsal part, layer 6b",0.026000000000000002,0.026000000000000002,0.052000000000000005 +oculomotor nerve,0.004,0.005,0.009000000000000001 +"Superior colliculus, zonal layer",0.135,0.169,0.30400000000000005 +Ectorhinal area/Layer 1,0.132,0.151,0.28300000000000003 +"Primary somatosensory area, nose, layer 2/3",0.312,0.329,0.641 +Dorsal motor nucleus of the vagus nerve,0.08600000000000001,0.09,0.176 +trapezoid body,0.157,0.184,0.34099999999999997 +"Superior colliculus, superficial gray layer",0.586,0.595,1.181 +Parasubiculum,0.48,0.458,0.938 +"Primary motor area, Layer 6a",1.333,1.4020000000000001,2.7350000000000003 +Dentate nucleus,0.183,0.156,0.33899999999999997 +"Primary auditory area, layer 5",0.34800000000000003,0.335,0.683 +optic nerve,0.034,0.04,0.07400000000000001 +"Visceral area, layer 6b",0.022,0.02,0.041999999999999996 +uncinate fascicle,0.04,0.039,0.079 +"Superior colliculus, optic layer",0.34500000000000003,0.31,0.655 +Parvicellular reticular nucleus,1.171,1.205,2.3760000000000003 +"Primary somatosensory area, upper limb, layer 2/3",0.511,0.453,0.964 +"Visceral area, layer 6a",0.278,0.266,0.544 +Parasolitary nucleus,0.017,0.014,0.031 +"Supplemental somatosensory area, layer 6a",0.998,0.992,1.99 +rubrospinal tract,0.302,0.29,0.592 +ventral spinocerebellar tract,0.159,0.161,0.32 +Parabrachial nucleus,0.453,0.486,0.9390000000000001 +"Posterolateral visual area, layer 4",0.016,0.019,0.035 +Dorsal nucleus raphe,0.026000000000000002,0.115,0.14100000000000001 +"Supplemental somatosensory area, layer 1",0.666,0.628,1.294 +Parabigeminal nucleus,0.024,0.024,0.048 +"Primary somatosensory area, mouth, layer 1",0.382,0.387,0.769 +Dorsal tegmental nucleus,0.051000000000000004,0.06,0.111 +"Primary motor area, Layer 6b",0.096,0.099,0.195 +amygdalar capsule,0.089,0.093,0.182 +"Perirhinal area, layer 2/3",0.158,0.171,0.329 +"Primary somatosensory area, nose, layer 6a",0.43,0.39,0.8200000000000001 +"Supplemental somatosensory area, layer 6b",0.105,0.092,0.197 +"Visceral area, layer 1",0.168,0.151,0.319 +Pontine central gray,0.258,0.271,0.529 +"anterior commissure, olfactory limb",0.371,0.422,0.7929999999999999 +"Posterolateral visual area, layer 5",0.10400000000000001,0.13,0.234 +External cuneate nucleus,0.10400000000000001,0.098,0.202 +"Anterolateral visual area, layer 2/3",0.096,0.098,0.194 +"Retrosplenial area, lateral agranular part, layer 6a",0.20800000000000002,0.202,0.41000000000000003 +Paracentral nucleus,0.115,0.112,0.227 +"anterior commissure, temporal limb",0.121,0.113,0.23399999999999999 +"Orbital area, medial part, layer 6a",0.09,0.08600000000000001,0.176 +trochlear nerve,0.004,0.005,0.009000000000000001 +Lingula (I),0.055,0.076,0.131 +Posterodorsal preoptic nucleus,0.005,0.004,0.009000000000000001 +brachium of the superior colliculus,0.088,0.097,0.185 +"Anterior cingulate area, dorsal part, layer 6a",0.332,0.385,0.7170000000000001 +cerebal peduncle,0.488,0.492,0.98 +"Anterior cingulate area, dorsal part, layer 6b",0.011,0.012,0.023 +"Primary somatosensory area, nose, layer 6b",0.026000000000000002,0.026000000000000002,0.052000000000000005 +Parafascicular nucleus,0.23900000000000002,0.255,0.494 +Pontine gray,0.485,0.496,0.981 +"Anterior cingulate area, dorsal part, layer 1",0.214,0.367,0.581 +Declive (VI),1.6,1.605,3.205 +"Nucleus ambiguus, dorsal division",0.014,0.014,0.028 +cingulum bundle,0.645,0.613,1.258 +"Primary motor area, Layer 2/3",1.9180000000000001,1.83,3.748 +Folium-tuber vermis (VII),0.549,0.518,1.0670000000000002 +"Primary somatosensory area, upper limb, layer 6a",0.507,0.497,1.004 +Posterior hypothalamic nucleus,0.322,0.35100000000000003,0.673 +vomeronasal nerve,0.008,0.008,0.016 +"Primary somatosensory area, mouth, layer 4",0.452,0.485,0.937 +Pyramus (VIII),0.582,0.581,1.1629999999999998 +"Endopiriform nucleus, dorsal part",0.925,0.901,1.826 +"Primary auditory area, layer 6a",0.147,0.139,0.28600000000000003 +"Lateral reticular nucleus, magnocellular part",0.24,0.263,0.503 +"corpus callosum, anterior forceps",0.437,0.406,0.843 +Uvula (IX),1.054,1.112,2.1660000000000004 +"Ventral auditory area, layer 1",0.14100000000000001,0.134,0.275 +Piriform area,5.931,5.878,11.809000000000001 +"Secondary motor area, layer 2/3",1.923,1.872,3.795 +"Lateral reticular nucleus, parvicellular part",0.029,0.034,0.063 +"corpus callosum, extreme capsule",0.054,0.048,0.10200000000000001 +"Retrosplenial area, lateral agranular part, layer 2/3",0.303,0.325,0.628 +"Endopiriform nucleus, ventral part",0.501,0.491,0.992 +Nodulus (X),0.731,0.797,1.528 +"Orbital area, ventrolateral part, layer 1",0.2,0.197,0.397 +"Paragigantocellular reticular nucleus, dorsal part",0.117,0.121,0.238 +"corpus callosum, posterior forceps",0.668,0.66,1.328 +"Lateral visual area, layer 2/3",0.158,0.149,0.307 +"Primary somatosensory area, mouth, layer 5",0.5740000000000001,0.614,1.1880000000000002 +Lobule II,0.612,0.717,1.329 +Ectorhinal area/Layer 6a,0.2,0.185,0.385 +"Paragigantocellular reticular nucleus, lateral part",0.383,0.361,0.744 +Dorsal premammillary nucleus,0.064,0.074,0.138 +"Primary somatosensory area, barrel field, layer 1",0.4,0.40700000000000003,0.807 +Fasciola cinerea,0.028,0.029,0.057 +Lobule III,1.281,1.456,2.737 +"corpus callosum, splenium",0.34400000000000003,0.363,0.7070000000000001 +Ectorhinal area/Layer 5,0.279,0.249,0.528 +Fastigial nucleus,0.248,0.275,0.523 +"Ventral auditory area, layer 4",0.108,0.107,0.215 +"Agranular insular area, dorsal part, layer 1",0.233,0.228,0.461 +root,1.731,1.877,3.608 +Fundus of striatum,0.242,0.221,0.46299999999999997 +Ventral premammillary nucleus,0.11,0.112,0.222 +"Primary auditory area, layer 6b",0.018000000000000002,0.019,0.037000000000000005 +"Primary somatosensory area, trunk, layer 1",0.091,0.101,0.192 +Simple lobule,2.824,2.695,5.519 +fiber tracts,0.807,0.802,1.609 +"Visceral area, layer 4",0.097,0.094,0.191 +"Anterior cingulate area, dorsal part, layer 5",0.5630000000000001,0.582,1.145 +olfactory nerve layer of main olfactory bulb,0.433,0.46,0.893 +Posterior complex of the thalamus,0.631,0.622,1.2530000000000001 +"Secondary motor area, layer 6a",1.038,1.236,2.274 +"Globus pallidus, external segment",0.791,0.8,1.5910000000000002 +"Ventral auditory area, layer 5",0.303,0.301,0.604 +Paramedian lobule,2.482,2.471,4.953 +"Primary somatosensory area, upper limb, layer 6b",0.042,0.043000000000000003,0.085 +Posterior limiting nucleus of the thalamus,0.097,0.096,0.193 +"Primary somatosensory area, lower limb, layer 1",0.17300000000000001,0.14,0.31300000000000006 +"Globus pallidus, internal segment",0.20400000000000001,0.194,0.398 +Copula pyramidis,1.216,1.173,2.3890000000000002 +"Supplemental somatosensory area, layer 4",0.5740000000000001,0.5690000000000001,1.1430000000000002 +Postsubiculum,0.515,0.52,1.0350000000000001 +"Primary somatosensory area, barrel field, layer 6a",0.636,0.633,1.2690000000000001 +Gracile nucleus,0.037,0.042,0.079 +Paraflocculus,2.949,2.866,5.8149999999999995 +crossed tectospinal pathway,0.248,0.255,0.503 +Peripeduncular nucleus,0.036000000000000004,0.028,0.064 +Ectorhinal area/Layer 6b,0.033,0.024,0.057 +"Anteromedial visual area, layer 6a",0.057,0.067,0.124 +"Primary somatosensory area, barrel field, layer 4",0.683,0.652,1.335 +Gigantocellular reticular nucleus,1.234,1.352,2.5860000000000003 +Flocculus,0.671,0.676,1.347 +Pedunculopontine nucleus,0.482,0.405,0.887 +"Infralimbic area, layer 6a",0.108,0.093,0.201 +Crus 1,2.846,2.797,5.643000000000001 +"Visceral area, layer 5",0.374,0.34800000000000003,0.722 +Posterior pretectal nucleus,0.07100000000000001,0.073,0.14400000000000002 +"Primary somatosensory area, barrel field, layer 6b",0.06,0.075,0.135 +Crus 2,2.516,2.605,5.121 +"Anteromedial visual area, layer 2/3",0.115,0.094,0.20900000000000002 +Parapyramidal nucleus,0.053,0.049,0.10200000000000001 +"Primary somatosensory area, barrel field, layer 5",0.628,0.59,1.218 +"Medial geniculate complex, dorsal part",0.082,0.083,0.165 +"Anterolateral visual area, layer 1",0.053,0.067,0.12 +Perireunensis nucleus,0.078,0.082,0.16 +"Medial geniculate complex, ventral part",0.128,0.133,0.261 +"Infralimbic area, layer 6b",0.004,0.003,0.007 +Presubiculum,0.465,0.463,0.928 +"Secondary motor area, layer 6b",0.036000000000000004,0.039,0.07500000000000001 +"Primary somatosensory area, trunk, layer 4",0.067,0.074,0.14100000000000001 +"Medial geniculate complex, medial part",0.11,0.11900000000000001,0.229 +Hippocampal formation,0.196,0.219,0.41500000000000004 +"Supplemental somatosensory area, layer 5",1.049,1.055,2.104 +Lobules IV-V,3.306,3.3890000000000002,6.695 +external medullary lamina of the thalamus,0.054,0.054,0.108 +"Pontine reticular nucleus, caudal part",1.2,1.193,2.393 +"Primary somatosensory area, lower limb, layer 4",0.11900000000000001,0.14100000000000001,0.26 +"Anteromedial nucleus, dorsal part",0.13,0.145,0.275 +Hypothalamus,1.3920000000000001,1.413,2.805 +"Medullary reticular nucleus, dorsal part",0.527,0.537,1.064 +"Agranular insular area, dorsal part, layer 5",0.755,0.747,1.502 +"Primary somatosensory area, mouth, layer 6a",0.891,0.805,1.6960000000000002 +"Anteromedial nucleus, ventral part",0.096,0.081,0.177 +Intercalated amygdalar nucleus,0.097,0.088,0.185 +"Visceral area, layer 2/3",0.278,0.264,0.542 +"Medullary reticular nucleus, ventral part",0.483,0.46900000000000003,0.952 +genu of corpus callosum,0.41300000000000003,0.386,0.799 +Parastrial nucleus,0.061,0.043000000000000003,0.10400000000000001 +"Primary somatosensory area, trunk, layer 5",0.179,0.17300000000000001,0.352 +Interanterodorsal nucleus of the thalamus,0.06,0.066,0.126 +"Anterolateral visual area, layer 4",0.059000000000000004,0.048,0.10700000000000001 +genu of the facial nerve,0.015,0.018000000000000002,0.033 +Interanteromedial nucleus of the thalamus,0.026000000000000002,0.033,0.059000000000000004 +"Entorhinal area, lateral part, layer 1",0.487,0.49,0.977 +inferior cerebellar peduncle,0.374,0.369,0.743 +"Orbital area, ventrolateral part, layer 5",0.319,0.31,0.629 +"Tuberomammillary nucleus, dorsal part",0.021,0.024,0.045 +"Temporal association areas, layer 2/3",0.367,0.34900000000000003,0.716 +"Primary somatosensory area, lower limb, layer 5",0.226,0.276,0.502 +"Nucleus of the lateral olfactory tract, layer 3",0.036000000000000004,0.031,0.067 +Median eminence,0.033,0.055,0.088 +"Dentate gyrus, molecular layer",2.239,2.1350000000000002,4.3740000000000006 +"Dentate gyrus, polymorph layer",0.32,0.311,0.631 +"Primary somatosensory area, unassigned, layer 1",0.085,0.066,0.15100000000000002 +"Primary somatosensory area, unassigned, layer 2/3",0.168,0.131,0.29900000000000004 +"Primary somatosensory area, unassigned, layer 4",0.07,0.10300000000000001,0.17300000000000001 +"Primary somatosensory area, unassigned, layer 5",0.124,0.152,0.276 +"Primary somatosensory area, unassigned, layer 6a",0.166,0.147,0.313 +"Primary somatosensory area, unassigned, layer 6b",0.015,0.015,0.03 +"Anterior area, layer 1",0.107,0.113,0.22 +"Anterior area, layer 2/3",0.215,0.213,0.428 +"Anterior area, layer 4",0.085,0.081,0.166 +"Anterior area, layer 5",0.213,0.17500000000000002,0.388 +"Anterior area, layer 6a",0.11,0.108,0.218 +"Anterior area, layer 6b",0.022,0.026000000000000002,0.048 +"Laterointermediate area, layer 1",0.037,0.035,0.07200000000000001 +"Laterointermediate area, layer 2/3",0.064,0.057,0.121 +"Laterointermediate area, layer 4",0.028,0.03,0.057999999999999996 +"Laterointermediate area, layer 5",0.078,0.073,0.151 +"Laterointermediate area, layer 6a",0.04,0.035,0.07500000000000001 +"Laterointermediate area, layer 6b",0.009000000000000001,0.008,0.017 +"Rostrolateral area, layer 1",0.088,0.08600000000000001,0.174 +"Rostrolateral area, layer 2/3",0.14200000000000002,0.132,0.274 +"Rostrolateral area, layer 4",0.07,0.07200000000000001,0.14200000000000002 +"Rostrolateral area, layer 5",0.113,0.123,0.236 +"Rostrolateral area, layer 6a",0.075,0.078,0.153 +"Rostrolateral area, layer 6b",0.009000000000000001,0.018000000000000002,0.027000000000000003 +"Postrhinal area, layer 1",0.115,0.121,0.236 +"Postrhinal area, layer 2/3",0.188,0.17500000000000002,0.363 +"Postrhinal area, layer 4",0.031,0.032,0.063 +"Postrhinal area, layer 5",0.181,0.191,0.372 +"Postrhinal area, layer 6a",0.08700000000000001,0.093,0.18 +"Postrhinal area, layer 6b",0.018000000000000002,0.018000000000000002,0.036000000000000004 +Prosubiculum,0.6,0.595,1.1949999999999998 +Area prostriata,0.17200000000000001,0.185,0.357 +supra-callosal cerebral white matter,0.561,0.514,1.0750000000000002 +"corpus callosum, body",1.5090000000000001,1.362,2.8710000000000004 +optic radiation,0.927,0.897,1.824 +auditory radiation,0.218,0.221,0.439 +commissural branch of stria terminalis,0.017,0.019,0.036000000000000004 +"Dorsal part of the lateral geniculate complex, shell",0.101,0.1,0.201 +"Dorsal part of the lateral geniculate complex, core",0.211,0.20600000000000002,0.41700000000000004 +"Dorsal part of the lateral geniculate complex, ipsilateral zone",0.043000000000000003,0.042,0.085 +"Frontal pole, layer 5",0.183,0.159,0.34199999999999997 +"Frontal pole, layer 6a",0.061,0.056,0.11699999999999999 +"Frontal pole, layer 6b",0.001,0.001,0.002 +"Orbital area, medial part, layer 6b",0.003,0.002,0.005 +Retroparafascicular nucleus,0.03,0.029,0.059 +Medial accesory oculomotor nucleus,0.01,0.01,0.02 +Peritrigeminal zone,0.177,0.149,0.32599999999999996 +Accessory trigeminal nucleus,0.007,0.009000000000000001,0.016 +Parvicellular motor 5 nucleus,0.033,0.034,0.067 +Intertrigeminal nucleus,0.023,0.029,0.052000000000000005 +Ethmoid nucleus of the thalamus,0.129,0.11900000000000001,0.248 +Xiphoid thalamic nucleus,0.006,0.066,0.07200000000000001 +Posterior intralaminar thalamic nucleus,0.099,0.084,0.183 +Posterior triangular thalamic nucleus,0.126,0.14,0.266 +Intermediate geniculate nucleus,0.011,0.01,0.020999999999999998 +Ventromedial preoptic nucleus,0.022,0.022,0.044 +Perifornical nucleus,0.115,0.101,0.21600000000000003 +Hippocampo-amygdalar transition area,0.21,0.195,0.405 +Paratrigeminal nucleus,0.053,0.037,0.09 +Vestibulocerebellar nucleus,0.041,0.046,0.087 +Subcommissural organ,0.002,0.01,0.012 +Posterodorsal tegmental nucleus,0.019,0.017,0.036000000000000004 +"Medial mammillary nucleus, lateral part",0.11900000000000001,0.112,0.231 +"Medial mammillary nucleus, medial part",0.081,0.078,0.159 +"Medial mammillary nucleus, posterior part",0.012,0.017,0.029 +"Medial mammillary nucleus, dorsal part",0.034,0.048,0.082 +Paratrochlear nucleus,0.011,0.009000000000000001,0.02 +Paranigral nucleus,0.012,0.011,0.023 +"Interpeduncular nucleus, rostral",0.029,0.051000000000000004,0.08 +"Interpeduncular nucleus, caudal",0.021,0.044,0.065 +"Interpeduncular nucleus, apical",0.005,0.015,0.02 +"Interpeduncular nucleus, lateral",0.026000000000000002,0.03,0.056 +"Interpeduncular nucleus, intermediate",0.021,0.021,0.042 +"Interpeduncular nucleus, dorsomedial",0.011,0.011,0.022 +"Interpeduncular nucleus, dorsolateral",0.018000000000000002,0.016,0.034 +"Interpeduncular nucleus, rostrolateral",0.009000000000000001,0.009000000000000001,0.018000000000000002 +Supraoculomotor periaqueductal gray,0.018000000000000002,0.016,0.034 diff --git a/tests/data/registration_output/Windows/boundaries.tiff b/tests/data/registration_output/Windows/boundaries.tiff new file mode 100644 index 00000000..d11336e9 Binary files /dev/null and b/tests/data/registration_output/Windows/boundaries.tiff differ diff --git a/tests/data/registration_output/Windows/deformation_field_0.tiff b/tests/data/registration_output/Windows/deformation_field_0.tiff new file mode 100644 index 00000000..3cf9586a Binary files /dev/null and b/tests/data/registration_output/Windows/deformation_field_0.tiff differ diff --git a/tests/data/registration_output/Windows/deformation_field_1.tiff b/tests/data/registration_output/Windows/deformation_field_1.tiff new file mode 100644 index 00000000..0b461762 Binary files /dev/null and b/tests/data/registration_output/Windows/deformation_field_1.tiff differ diff --git a/tests/data/registration_output/Windows/deformation_field_2.tiff b/tests/data/registration_output/Windows/deformation_field_2.tiff new file mode 100644 index 00000000..0abf8b09 Binary files /dev/null and b/tests/data/registration_output/Windows/deformation_field_2.tiff differ diff --git a/tests/data/registration_output/Windows/downsampled.tiff b/tests/data/registration_output/Windows/downsampled.tiff new file mode 100644 index 00000000..99486807 Binary files /dev/null and b/tests/data/registration_output/Windows/downsampled.tiff differ diff --git a/tests/data/registration_output/Windows/downsampled_channel_0.tiff b/tests/data/registration_output/Windows/downsampled_channel_0.tiff new file mode 100644 index 00000000..99486807 Binary files /dev/null and b/tests/data/registration_output/Windows/downsampled_channel_0.tiff differ diff --git a/tests/data/registration_output/Windows/downsampled_standard.tiff b/tests/data/registration_output/Windows/downsampled_standard.tiff new file mode 100644 index 00000000..3a0f3566 Binary files /dev/null and b/tests/data/registration_output/Windows/downsampled_standard.tiff differ diff --git a/tests/data/registration_output/Windows/downsampled_standard_channel_0.tiff b/tests/data/registration_output/Windows/downsampled_standard_channel_0.tiff new file mode 100644 index 00000000..3a0f3566 Binary files /dev/null and b/tests/data/registration_output/Windows/downsampled_standard_channel_0.tiff differ diff --git a/tests/data/registration_output/Windows/registered_atlas.tiff b/tests/data/registration_output/Windows/registered_atlas.tiff new file mode 100644 index 00000000..9dd642a0 Binary files /dev/null and b/tests/data/registration_output/Windows/registered_atlas.tiff differ diff --git a/tests/data/registration_output/Windows/registered_hemispheres.tiff b/tests/data/registration_output/Windows/registered_hemispheres.tiff new file mode 100644 index 00000000..dac21ee1 Binary files /dev/null and b/tests/data/registration_output/Windows/registered_hemispheres.tiff differ diff --git a/tests/data/registration_output/Windows/volumes.csv b/tests/data/registration_output/Windows/volumes.csv new file mode 100644 index 00000000..e69a6061 --- /dev/null +++ b/tests/data/registration_output/Windows/volumes.csv @@ -0,0 +1,664 @@ +structure_name,left_volume_mm3,right_volume_mm3,total_volume_mm3 +"Tuberomammillary nucleus, ventral part",0.059000000000000004,0.058,0.117 +"Primary somatosensory area, mouth, layer 6b",0.06,0.059000000000000004,0.119 +internal capsule,1.032,0.996,2.028 +Principal sensory nucleus of the trigeminal,0.578,0.537,1.115 +"Primary somatosensory area, trunk, layer 6a",0.117,0.10200000000000001,0.21900000000000003 +"Superior colliculus, motor related, intermediate gray layer",0.9560000000000001,1.008,1.964 +Interfascicular nucleus raphe,0.031,0.053,0.08399999999999999 +Parataenial nucleus,0.126,0.123,0.249 +"Superior colliculus, motor related, intermediate white layer",1.0150000000000001,1.049,2.064 +Induseum griseum,0.037,0.077,0.11399999999999999 +"Entorhinal area, lateral part, layer 2",0.8160000000000001,0.784,1.6 +Anterior amygdalar area,0.243,0.302,0.5449999999999999 +"Superior colliculus, motor related, deep gray layer",0.58,0.5740000000000001,1.154 +Intergeniculate leaflet of the lateral geniculate complex,0.037,0.03,0.067 +"Entorhinal area, lateral part, layer 6a",0.545,0.51,1.0550000000000002 +"Primary visual area, layer 6a",0.542,0.514,1.056 +Oculomotor nucleus,0.011,0.015,0.026 +"Gustatory areas, layer 1",0.101,0.089,0.19 +Paraventricular hypothalamic nucleus,0.095,0.10200000000000001,0.197 +"posteromedial visual area, layer 2/3",0.14200000000000002,0.147,0.28900000000000003 +"Superior colliculus, motor related, deep white layer",0.149,0.15,0.299 +Precommissural nucleus,0.1,0.096,0.196 +"Entorhinal area, lateral part, layer 3",0.682,0.636,1.318 +medial forebrain bundle,0.032,0.024,0.056 +Nucleus accumbens,2.248,2.188,4.436 +Medial terminal nucleus of the accessory optic tract,0.028,0.023,0.051000000000000004 +Intermediodorsal nucleus of the thalamus,0.045,0.138,0.183 +medial longitudinal fascicle,0.045,0.044,0.089 +"Paraventricular hypothalamic nucleus, descending division",0.07200000000000001,0.059000000000000004,0.131 +Anterodorsal nucleus,0.079,0.07200000000000001,0.15100000000000002 +Lateral terminal nucleus of the accessory optic tract,0.01,0.013000000000000001,0.023 +Interstitial nucleus of Cajal,0.041,0.039,0.08 +"Frontal pole, layer 1",0.115,0.10200000000000001,0.21700000000000003 +Anterodorsal preoptic nucleus,0.046,0.039,0.08499999999999999 +"Lateral visual area, layer 6a",0.107,0.094,0.201 +Dorsal terminal nucleus of the accessory optic tract,0.006,0.007,0.013000000000000001 +middle cerebellar peduncle,0.518,0.548,1.066 +lateral ventricle,1.016,1.038,2.0540000000000003 +Inferior olivary complex,0.253,0.234,0.487 +"Prelimbic area, layer 6a",0.232,0.20800000000000002,0.44000000000000006 +Anterior hypothalamic nucleus,0.382,0.341,0.7230000000000001 +Interposed nucleus,0.417,0.41100000000000003,0.8280000000000001 +motor root of the trigeminal nerve,0.027,0.035,0.062 +Dorsal cochlear nucleus,0.312,0.32,0.632 +"Temporal association areas, layer 1",0.263,0.23800000000000002,0.501 +subependymal zone,0.059000000000000004,0.06,0.119 +Interpeduncular nucleus,0.004,0.007,0.011 +Ventral cochlear nucleus,0.512,0.518,1.03 +nigrostriatal tract,0.053,0.06,0.11299999999999999 +"Superior olivary complex, medial part",0.10400000000000001,0.098,0.202 +Inferior salivatory nucleus,0.005,0.005,0.01 +choroid plexus,0.627,0.746,1.373 +"Primary somatosensory area, lower limb, layer 2/3",0.325,0.278,0.603 +"Superior olivary complex, lateral part",0.182,0.17300000000000001,0.355 +Trochlear nucleus,0.003,0.005,0.008 +optic chiasm,0.145,0.167,0.312 +"Periventricular hypothalamic nucleus, intermediate part",0.027,0.124,0.151 +"Agranular insular area, posterior part, layer 1",0.221,0.2,0.42100000000000004 +"Lateral visual area, layer 6b",0.018000000000000002,0.02,0.038000000000000006 +"Superior olivary complex, periolivary region",0.194,0.188,0.382 +Koelliker-Fuse subnucleus,0.096,0.092,0.188 +optic tract,0.34700000000000003,0.367,0.714 +"Periventricular hypothalamic nucleus, posterior part",0.038,0.058,0.096 +Midbrain reticular nucleus,2.6350000000000002,2.509,5.144 +third ventricle,0.23800000000000002,0.768,1.006 +Lateral amygdalar nucleus,0.424,0.402,0.8260000000000001 +"Prelimbic area, layer 6b",0.012,0.007,0.019 +"Periventricular hypothalamic nucleus, preoptic part",0.02,0.1,0.12000000000000001 +Intermediate reticular nucleus,1.416,1.355,2.771 +"Entorhinal area, lateral part, layer 5",0.723,0.6960000000000001,1.419 +cerebral aqueduct,0.146,0.22,0.366 +"Nucleus ambiguus, ventral division",0.007,0.008,0.015 +fourth ventricle,0.226,0.273,0.499 +Pontine reticular nucleus,1.189,1.167,2.356 +Locus ceruleus,0.009000000000000001,0.005,0.014000000000000002 +"Gustatory areas, layer 4",0.07200000000000001,0.056,0.128 +Paraventricular nucleus of the thalamus,0.176,0.28500000000000003,0.461 +lateral recess,0.233,0.229,0.462 +Lateral dorsal nucleus of thalamus,0.501,0.521,1.022 +"Dorsal auditory area, layer 6a",0.10400000000000001,0.084,0.188 +posterior commissure,0.016,0.031,0.047 +Anterior olfactory nucleus,2.315,2.447,4.7620000000000005 +Laterodorsal tegmental nucleus,0.097,0.079,0.176 +"Agranular insular area, posterior part, layer 2/3",0.405,0.376,0.781 +Nucleus prepositus,0.113,0.101,0.21400000000000002 +"Prelimbic area, layer 1",0.194,0.317,0.511 +Retrochiasmatic area,0.067,0.075,0.14200000000000002 +Nucleus of Roller,0.017,0.02,0.037000000000000005 +Ventral part of the lateral geniculate complex,0.203,0.193,0.396 +"Gustatory areas, layer 2/3",0.20600000000000002,0.177,0.383 +Nucleus of reuniens,0.192,0.232,0.42400000000000004 +Lateral habenula,0.147,0.177,0.32399999999999995 +"Gustatory areas, layer 5",0.27,0.244,0.514 +"Accessory olfactory bulb, glomerular layer",0.075,0.073,0.148 +Rhomboid nucleus,0.028,0.051000000000000004,0.079 +pyramid,0.289,0.28400000000000003,0.573 +Lateral hypothalamic area,1.102,1.068,2.17 +"Accessory olfactory bulb, granular layer",0.08700000000000001,0.112,0.199 +Rostral linear nucleus raphe,0.017,0.055,0.07200000000000001 +pyramidal decussation,0.017,0.045,0.062 +"Primary somatosensory area, barrel field, layer 2/3",0.724,0.675,1.399 +Medial vestibular nucleus,0.9,0.913,1.8130000000000002 +Linear nucleus of the medulla,0.03,0.039,0.069 +"Accessory olfactory bulb, mitral layer",0.124,0.132,0.256 +Area postrema,0.016,0.034,0.05 +Lateral vestibular nucleus,0.14,0.138,0.278 +Lateral mammillary nucleus,0.038,0.038,0.076 +"Anterior cingulate area, dorsal part, layer 2/3",0.222,0.218,0.44 +Red nucleus,0.371,0.436,0.8069999999999999 +Anterior pretectal nucleus,0.638,0.624,1.262 +Superior vestibular nucleus,0.17,0.166,0.336 +Lateral posterior nucleus of the thalamus,0.588,0.618,1.206 +Arcuate hypothalamic nucleus,0.147,0.152,0.299 +Spinal vestibular nucleus,0.393,0.382,0.775 +Lateral preoptic area,0.226,0.258,0.484 +sensory root of the trigeminal nerve,0.317,0.34600000000000003,0.663 +Anterior tegmental nucleus,0.016,0.022,0.038 +"Anterolateral visual area, layer 5",0.1,0.093,0.193 +"Temporal association areas, layer 4",0.159,0.137,0.29600000000000004 +solitary tract,0.005,0.006,0.011 +Nucleus raphe pontis,0.034,0.046,0.08 +"Dorsal auditory area, layer 6b",0.016,0.016,0.032 +"Midbrain reticular nucleus, retrorubral area",0.081,0.053,0.134 +"Posterior auditory area, layer 6a",0.043000000000000003,0.038,0.081 +"Lateral septal nucleus, caudal (caudodorsal) part",0.268,0.28800000000000003,0.556 +"Primary auditory area, layer 2/3",0.23800000000000002,0.221,0.459 +"Dorsal auditory area, layer 5",0.166,0.149,0.315 +Anteroventral nucleus of thalamus,0.193,0.222,0.41500000000000004 +"posteromedial visual area, layer 6a",0.07200000000000001,0.07200000000000001,0.14400000000000002 +"Lateral septal nucleus, rostral (rostroventral) part",0.896,0.909,1.8050000000000002 +"Nucleus of the lateral olfactory tract, molecular layer",0.05,0.05,0.1 +Reticular nucleus of the thalamus,0.706,0.6970000000000001,1.403 +Anteroventral preoptic nucleus,0.042,0.048,0.09 +"Lateral septal nucleus, ventral part",0.289,0.301,0.59 +"Nucleus of the lateral olfactory tract, pyramidal layer",0.074,0.075,0.149 +"Posterolateral visual area, layer 2/3",0.092,0.096,0.188 +Nucleus sagulum,0.04,0.055,0.095 +Anteroventral periventricular nucleus,0.092,0.10300000000000001,0.195 +"Retrosplenial area, dorsal part, layer 6a",0.384,0.376,0.76 +"Retrosplenial area, lateral agranular part, layer 6b",0.019,0.017,0.036000000000000004 +Barrington's nucleus,0.008,0.007,0.015 +"Anteromedial visual area, layer 1",0.077,0.068,0.14500000000000002 +Suprachiasmatic nucleus,0.031,0.034,0.065 +Bed nucleus of the anterior commissure,0.004,0.002,0.006 +"Orbital area, ventrolateral part, layer 2/3",0.233,0.25,0.483 +"Temporal association areas, layer 5",0.482,0.439,0.921 +Bed nucleus of the accessory olfactory tract,0.014,0.012,0.026000000000000002 +"Anterior cingulate area, ventral part, layer 2/3",0.198,0.202,0.4 +Magnocellular nucleus,0.162,0.17400000000000002,0.336 +stria terminalis,0.139,0.151,0.29000000000000004 +"Basolateral amygdalar nucleus, anterior part",0.403,0.339,0.742 +"Prelimbic area, layer 2/3",0.167,0.167,0.334 +"Primary visual area, layer 6b",0.08600000000000001,0.093,0.179 +Magnocellular reticular nucleus,0.289,0.271,0.56 +Septofimbrial nucleus,0.212,0.257,0.469 +"Basolateral amygdalar nucleus, posterior part",0.369,0.372,0.741 +Midbrain,3.168,3.358,6.526 +"Agranular insular area, posterior part, layer 6a",0.215,0.20600000000000002,0.42100000000000004 +Supragenual nucleus,0.009000000000000001,0.013000000000000001,0.022000000000000002 +"Primary motor area, Layer 1",0.646,0.623,1.2690000000000001 +Subgeniculate nucleus,0.011,0.013000000000000001,0.024 +Suprageniculate nucleus,0.096,0.095,0.191 +superior cerebelar peduncles,0.20700000000000002,0.20400000000000001,0.41100000000000003 +"Basomedial amygdalar nucleus, anterior part",0.41100000000000003,0.401,0.812 +"Agranular insular area, dorsal part, layer 2/3",0.42,0.466,0.886 +"Retrosplenial area, dorsal part, layer 6b",0.023,0.019,0.041999999999999996 +Accessory supraoptic group,0.001,0.002,0.003 +Septohippocampal nucleus,0.014,0.016,0.03 +"Basomedial amygdalar nucleus, posterior part",0.35100000000000003,0.372,0.7230000000000001 +"Perirhinal area, layer 6a",0.028,0.035,0.063 +superior colliculus commissure,0.015,0.022,0.037 +Subfornical organ,0.008,0.017,0.025 +Substantia innominata,1.522,1.471,2.9930000000000003 +"Agranular insular area, posterior part, layer 5",0.386,0.364,0.75 +Subparaventricular zone,0.07200000000000001,0.046,0.11800000000000001 +supraoptic commissures,0.014,0.016,0.03 +Subceruleus nucleus,0.011,0.015,0.026 +Bed nuclei of the stria terminalis,0.678,0.687,1.3650000000000002 +Medulla,2.5,2.741,5.241 +"Agranular insular area, posterior part, layer 6b",0.01,0.009000000000000001,0.019000000000000003 +Preparasubthalamic nucleus,0.007,0.008,0.015 +Sublaterodorsal nucleus,0.02,0.016,0.036000000000000004 +Mediodorsal nucleus of thalamus,0.6910000000000001,0.672,1.363 +"Prelimbic area, layer 5",0.47000000000000003,0.463,0.933 +Parasubthalamic nucleus,0.07200000000000001,0.077,0.14900000000000002 +Submedial nucleus of the thalamus,0.147,0.163,0.31 +"Perirhinal area, layer 6b",0.008,0.008,0.016 +Infracerebellar nucleus,0.027,0.025,0.052000000000000005 +"Substantia nigra, compact part",0.10300000000000001,0.093,0.196 +"Posterolateral visual area, layer 6a",0.041,0.043000000000000003,0.084 +cuneate fascicle,0.007,0.01,0.017 +"Substantia nigra, reticular part",0.777,0.722,1.499 +Field CA1,5.061,4.947,10.008 +Supraoptic nucleus,0.018000000000000002,0.025,0.043000000000000003 +"Posterolateral visual area, layer 6b",0.004,0.005,0.009000000000000001 +ventral tegmental decussation,0.013000000000000001,0.024,0.037000000000000005 +"Anteromedial visual area, layer 4",0.03,0.024,0.054 +Medial amygdalar nucleus,1.061,0.995,2.056 +"Orbital area, lateral part, layer 2/3",0.279,0.255,0.534 +vestibular nerve,0.109,0.128,0.237 +"Subparafascicular nucleus, magnocellular part",0.033,0.033,0.066 +"Lateral visual area, layer 1",0.092,0.081,0.173 +"Subparafascicular nucleus, parvicellular part",0.089,0.06,0.149 +Field CA2,0.22,0.219,0.439 +Ectorhinal area/Layer 2/3,0.231,0.227,0.458 +medial corticohypothalamic tract,0.005,0.005,0.01 +"Spinal nucleus of the trigeminal, caudal part",0.837,0.8210000000000001,1.658 +"Retrosplenial area, ventral part, layer 2/3",0.539,0.489,1.028 +"Anteromedial visual area, layer 5",0.113,0.101,0.21400000000000002 +"Retrosplenial area, dorsal part, layer 2/3",0.463,0.452,0.915 +columns of the fornix,0.14200000000000002,0.14400000000000002,0.28600000000000003 +"Spinal nucleus of the trigeminal, interpolar part",0.96,0.923,1.883 +"Orbital area, lateral part, layer 6a",0.225,0.231,0.456 +"Anteromedial visual area, layer 6b",0.014,0.015,0.028999999999999998 +"Retrosplenial area, dorsal part, layer 1",0.381,0.403,0.784 +dorsal hippocampal commissure,0.46,0.47000000000000003,0.93 +"Spinal nucleus of the trigeminal, oral part",0.517,0.527,1.044 +"Orbital area, lateral part, layer 1",0.169,0.157,0.326 +ventral hippocampal commissure,0.029,0.041,0.07 +"Primary somatosensory area, upper limb, layer 1",0.245,0.264,0.509 +"Basolateral amygdalar nucleus, ventral part",0.199,0.215,0.41400000000000003 +Median preoptic nucleus,0.002,0.032,0.034 +"Posterior auditory area, layer 6b",0.007,0.008,0.015 +Midbrain trigeminal nucleus,0.006,0.007,0.013000000000000001 +"Primary somatosensory area, trunk, layer 6b",0.021,0.02,0.041 +Field CA3,3.11,3.0140000000000002,6.1240000000000006 +alveus,0.6910000000000001,0.657,1.348 +"posteromedial visual area, layer 6b",0.018000000000000002,0.02,0.038000000000000006 +Subthalamic nucleus,0.10300000000000001,0.112,0.21500000000000002 +Striatum,1.322,1.413,2.7350000000000003 +"Primary somatosensory area, lower limb, layer 6a",0.3,0.228,0.528 +brachium of the inferior colliculus,0.124,0.122,0.246 +Medial habenula,0.145,0.124,0.269 +"Orbital area, medial part, layer 1",0.149,0.269,0.41800000000000004 +"Orbital area, lateral part, layer 6b",0.011,0.023,0.034 +"posteromedial visual area, layer 4",0.044,0.044,0.088 +Subiculum,1.096,0.991,2.087 +dorsal acoustic stria,0.006,0.007,0.013000000000000001 +Main olfactory bulb,3.614,3.855,7.468999999999999 +"Primary somatosensory area, lower limb, layer 6b",0.021,0.019,0.04 +Cerebellum,0.397,0.403,0.8 +Medial preoptic nucleus,0.234,0.216,0.45 +"Ventral auditory area, layer 6a",0.137,0.14100000000000001,0.278 +Medial preoptic area,0.259,0.296,0.5549999999999999 +Supramammillary nucleus,0.11900000000000001,0.139,0.258 +"Entorhinal area, medial part, dorsal zone, layer 1",0.618,0.618,1.236 +"Dorsal auditory area, layer 1",0.09,0.091,0.181 +dorsal fornix,0.004,0.02,0.024 +Medial pretectal area,0.024,0.023,0.047 +Supratrigeminal nucleus,0.16,0.10200000000000001,0.262 +dorsal limb,0.06,0.077,0.137 +"Perirhinal area, layer 1",0.121,0.117,0.238 +"Retrosplenial area, ventral part, layer 1",0.328,0.556,0.8840000000000001 +"Entorhinal area, medial part, dorsal zone, layer 2",0.619,0.63,1.249 +"Central amygdalar nucleus, capsular part",0.14100000000000001,0.158,0.29900000000000004 +Thalamus,0.446,0.424,0.87 +"Central amygdalar nucleus, lateral part",0.134,0.14,0.274 +dorsal spinocerebellar tract,0.075,0.073,0.148 +"Infralimbic area, layer 2/3",0.083,0.075,0.158 +"Primary somatosensory area, nose, layer 1",0.199,0.198,0.397 +"Central amygdalar nucleus, medial part",0.356,0.385,0.741 +Medial septal nucleus,0.121,0.277,0.398 +"posteromedial visual area, layer 5",0.14100000000000001,0.155,0.29600000000000004 +Postpiriform transition area,0.706,0.6970000000000001,1.403 +"Lateral visual area, layer 4",0.092,0.083,0.175 +Tegmental reticular nucleus,0.34400000000000003,0.341,0.685 +Central lateral nucleus of the thalamus,0.163,0.181,0.344 +Accessory facial motor nucleus,0.002,0.002,0.004 +"Primary somatosensory area, upper limb, layer 4",0.265,0.233,0.498 +external capsule,0.455,0.44,0.895 +Nucleus of the brachium of the inferior colliculus,0.043000000000000003,0.042,0.085 +Triangular nucleus of septum,0.156,0.191,0.347 +"Orbital area, medial part, layer 2/3",0.134,0.148,0.28200000000000003 +Claustrum,0.267,0.264,0.531 +Nucleus of Darkschewitsch,0.054,0.05,0.10400000000000001 +"Anterior cingulate area, ventral part, layer 1",0.17200000000000001,0.312,0.484 +"Retrosplenial area, ventral part, layer 6a",0.327,0.316,0.643 +Central linear nucleus raphe,0.03,0.052000000000000005,0.082 +"Primary visual area, layer 1",0.641,0.578,1.2189999999999999 +fasciculus retroflexus,0.083,0.083,0.166 +Diagonal band nucleus,0.343,0.387,0.73 +"Taenia tecta, dorsal part",0.318,0.362,0.6799999999999999 +"Ventral auditory area, layer 6b",0.016,0.022,0.038 +Central medial nucleus of the thalamus,0.1,0.159,0.259 +"Dorsal auditory area, layer 2/3",0.136,0.14400000000000002,0.28 +"Anterolateral visual area, layer 6a",0.06,0.049,0.109 +fimbria,0.745,0.711,1.456 +Nucleus incertus,0.044,0.067,0.111 +"Taenia tecta, ventral part",0.341,0.34400000000000003,0.685 +"Orbital area, ventrolateral part, layer 6a",0.101,0.092,0.193 +Subparafascicular area,0.054,0.08600000000000001,0.14 +"Retrosplenial area, dorsal part, layer 5",0.547,0.577,1.124 +habenular commissure,0.014,0.022,0.036 +Nucleus of the lateral lemniscus,0.384,0.357,0.741 +"Lateral visual area, layer 5",0.171,0.148,0.319 +Tuberal nucleus,0.274,0.27,0.544 +Cuneiform nucleus,0.28,0.281,0.561 +"Orbital area, medial part, layer 5",0.2,0.225,0.42500000000000004 +Motor nucleus of trigeminal,0.163,0.179,0.34199999999999997 +"Retrosplenial area, ventral part, layer 6b",0.021,0.024,0.045 +"Primary somatosensory area, upper limb, layer 5",0.292,0.313,0.605 +Nucleus of the optic tract,0.092,0.10400000000000001,0.196 +Ventral anterior-lateral complex of the thalamus,0.393,0.384,0.777 +"Orbital area, lateral part, layer 5",0.555,0.555,1.11 +"Dentate gyrus, granule cell layer",0.8240000000000001,0.761,1.585 +inferior colliculus commissure,0.007,0.011,0.018 +Nucleus of the posterior commissure,0.148,0.149,0.297 +"Gustatory areas, layer 6a",0.211,0.195,0.406 +"Cortical amygdalar area, anterior part",0.387,0.395,0.782 +Nucleus of the trapezoid body,0.082,0.08,0.162 +"Posterior auditory area, layer 2/3",0.07100000000000001,0.062,0.133 +"Primary motor area, Layer 5",1.51,1.468,2.9779999999999998 +"Anterolateral visual area, layer 6b",0.021,0.016,0.037000000000000005 +Nucleus of the solitary tract,0.40800000000000003,0.437,0.845 +Abducens nucleus,0.02,0.016,0.036000000000000004 +"Primary somatosensory area, nose, layer 4",0.254,0.262,0.516 +"Cortical amygdalar area, posterior part, lateral zone",0.619,0.621,1.24 +"Secondary motor area, layer 1",1.1400000000000001,1.118,2.258 +"Primary somatosensory area, mouth, layer 2/3",0.738,0.738,1.476 +lateral lemniscus,0.428,0.40900000000000003,0.837 +Facial motor nucleus,0.458,0.455,0.913 +"Gustatory areas, layer 6b",0.022,0.021,0.043 +"Cortical amygdalar area, posterior part, medial zone",0.679,0.651,1.33 +"Entorhinal area, medial part, dorsal zone, layer 3",0.506,0.493,0.999 +"lateral olfactory tract, body",0.468,0.456,0.924 +"Frontal pole, layer 2/3",0.131,0.108,0.239 +"Primary somatosensory area, trunk, layer 2/3",0.187,0.196,0.383 +"Retrosplenial area, lateral agranular part, layer 1",0.23,0.24,0.47 +Caudoputamen,12.784,12.508000000000001,25.292 +mammillary peduncle,0.017,0.015,0.032 +"Agranular insular area, ventral part, layer 6a",0.091,0.088,0.179 +"Dorsal auditory area, layer 4",0.065,0.058,0.123 +Superior central nucleus raphe,0.276,0.343,0.619 +"Orbital area, ventrolateral part, layer 6b",0.003,0.004,0.007 +mammillotegmental tract,0.032,0.032,0.064 +Ventral medial nucleus of the thalamus,0.47600000000000003,0.45,0.926 +"Retrosplenial area, ventral part, layer 5",0.807,0.8180000000000001,1.625 +Ventrolateral preoptic nucleus,0.039,0.027,0.066 +mammillothalamic tract,0.058,0.066,0.124 +"Perirhinal area, layer 5",0.084,0.08,0.164 +Ventromedial hypothalamic nucleus,0.28800000000000003,0.28200000000000003,0.5700000000000001 +"Agranular insular area, ventral part, layer 2/3",0.29,0.302,0.592 +"Posterior auditory area, layer 1",0.054,0.048,0.10200000000000001 +medial lemniscus,0.354,0.333,0.687 +Olfactory areas,1.3800000000000001,1.3760000000000001,2.7560000000000002 +"Agranular insular area, ventral part, layer 6b",0.001,0.001,0.002 +"Primary somatosensory area, nose, layer 5",0.28600000000000003,0.278,0.5640000000000001 +Cortical subplate,0.185,0.185,0.37 +"Agranular insular area, ventral part, layer 1",0.111,0.129,0.24 +Olivary pretectal nucleus,0.03,0.034,0.064 +"Infralimbic area, layer 1",0.044,0.101,0.14500000000000002 +Cuneate nucleus,0.152,0.17300000000000001,0.325 +Ventral posterolateral nucleus of the thalamus,0.426,0.388,0.8140000000000001 +"Primary visual area, layer 4",0.502,0.49,0.992 +"Ventral posterolateral nucleus of the thalamus, parvicellular part",0.053,0.044,0.097 +"Entorhinal area, medial part, dorsal zone, layer 5",0.46900000000000003,0.457,0.926 +arbor vitae,3.344,3.317,6.661 +"Temporal association areas, layer 6a",0.262,0.234,0.496 +"Medial mammillary nucleus, median part",0.021,0.045,0.066 +Ventral posteromedial nucleus of the thalamus,0.808,0.864,1.6720000000000002 +"Primary auditory area, layer 1",0.193,0.176,0.369 +"Ventral posteromedial nucleus of the thalamus, parvicellular part",0.132,0.11,0.242 +"Entorhinal area, medial part, dorsal zone, layer 6",0.335,0.314,0.649 +cerebellar commissure,0.03,0.032,0.062 +Ventral tegmental area,0.246,0.211,0.45699999999999996 +"Posterolateral visual area, layer 1",0.096,0.099,0.195 +principal mammillary tract,0.02,0.019,0.039 +Olfactory tubercle,1.956,1.977,3.933 +"Ventral auditory area, layer 2/3",0.189,0.203,0.392 +Ventral tegmental nucleus,0.017,0.02,0.037000000000000005 +"Posterior auditory area, layer 4",0.041,0.039,0.08 +Nucleus x,0.024,0.027,0.051000000000000004 +"Secondary motor area, layer 5",2.253,2.043,4.296 +Pons,1.719,1.94,3.659 +"Anterior cingulate area, ventral part, layer 5",0.492,0.542,1.034 +Hypoglossal nucleus,0.107,0.139,0.246 +"Retrosplenial area, lateral agranular part, layer 5",0.363,0.34900000000000003,0.712 +"Primary visual area, layer 5",0.786,0.768,1.554 +Posterior amygdalar nucleus,0.505,0.492,0.997 +Nucleus y,0.013000000000000001,0.01,0.023 +"Agranular insular area, dorsal part, layer 6a",0.383,0.381,0.764 +corticospinal tract,0.047,0.047,0.094 +"Temporal association areas, layer 6b",0.042,0.03,0.07200000000000001 +Piriform-amygdalar area,0.631,0.638,1.2690000000000001 +"Posterior auditory area, layer 5",0.093,0.089,0.182 +spinal tract of the trigeminal nerve,0.848,0.8210000000000001,1.669 +Periaqueductal gray,1.995,2.058,4.053 +Zona incerta,0.8170000000000001,0.808,1.625 +facial nerve,0.041,0.022,0.063 +"Agranular insular area, ventral part, layer 5",0.35100000000000003,0.359,0.71 +stria medullaris,0.137,0.128,0.265 +Pallidum,0.595,0.578,1.173 +Fields of Forel,0.129,0.14200000000000002,0.271 +"posteromedial visual area, layer 1",0.091,0.079,0.16999999999999998 +"Supplemental somatosensory area, layer 2/3",1.061,0.971,2.032 +"Anterior cingulate area, ventral part, 6a",0.176,0.192,0.368 +"Inferior colliculus, central nucleus",0.549,0.56,1.109 +superior cerebellar peduncle decussation,0.012,0.025,0.037000000000000005 +Dorsal peduncular area,0.23800000000000002,0.24,0.478 +"Primary auditory area, layer 4",0.123,0.11,0.23299999999999998 +"Anterior cingulate area, ventral part, 6b",0.029,0.026000000000000002,0.05500000000000001 +"Inferior colliculus, dorsal nucleus",0.6,0.641,1.241 +"Primary visual area, layer 2/3",1.0130000000000001,0.9560000000000001,1.9690000000000003 +"Infralimbic area, layer 5",0.136,0.14,0.276 +"Inferior colliculus, external nucleus",1.02,0.985,2.005 +Dorsomedial nucleus of the hypothalamus,0.20700000000000002,0.192,0.399 +"Agranular insular area, dorsal part, layer 6b",0.019,0.025,0.044 +oculomotor nerve,0.004,0.006,0.01 +"Superior colliculus, zonal layer",0.133,0.153,0.28600000000000003 +Ectorhinal area/Layer 1,0.124,0.148,0.272 +"Primary somatosensory area, nose, layer 2/3",0.32,0.307,0.627 +Dorsal motor nucleus of the vagus nerve,0.078,0.09,0.16799999999999998 +trapezoid body,0.157,0.177,0.33399999999999996 +"Superior colliculus, superficial gray layer",0.536,0.5710000000000001,1.1070000000000002 +Parasubiculum,0.47700000000000004,0.451,0.928 +"Primary motor area, Layer 6a",1.331,1.337,2.668 +Dentate nucleus,0.169,0.152,0.321 +"Primary auditory area, layer 5",0.34500000000000003,0.313,0.658 +optic nerve,0.04,0.043000000000000003,0.083 +"Visceral area, layer 6b",0.021,0.02,0.041 +uncinate fascicle,0.043000000000000003,0.047,0.09 +"Superior colliculus, optic layer",0.291,0.312,0.603 +Parvicellular reticular nucleus,1.193,1.162,2.355 +"Primary somatosensory area, upper limb, layer 2/3",0.518,0.47600000000000003,0.994 +"Visceral area, layer 6a",0.271,0.265,0.536 +Parasolitary nucleus,0.017,0.013000000000000001,0.030000000000000002 +"Supplemental somatosensory area, layer 6a",0.975,0.93,1.905 +rubrospinal tract,0.28800000000000003,0.28500000000000003,0.5730000000000001 +ventral spinocerebellar tract,0.153,0.149,0.302 +Parabrachial nucleus,0.47800000000000004,0.464,0.9420000000000001 +"Posterolateral visual area, layer 4",0.016,0.011,0.027 +Dorsal nucleus raphe,0.033,0.124,0.157 +"Supplemental somatosensory area, layer 1",0.637,0.598,1.2349999999999999 +Parabigeminal nucleus,0.016,0.021,0.037000000000000005 +"Primary somatosensory area, mouth, layer 1",0.384,0.377,0.761 +Dorsal tegmental nucleus,0.056,0.061,0.11699999999999999 +"Primary motor area, Layer 6b",0.098,0.088,0.186 +amygdalar capsule,0.084,0.088,0.172 +"Perirhinal area, layer 2/3",0.168,0.169,0.337 +"Primary somatosensory area, nose, layer 6a",0.451,0.379,0.8300000000000001 +"Supplemental somatosensory area, layer 6b",0.10200000000000001,0.08600000000000001,0.188 +"Visceral area, layer 1",0.169,0.156,0.325 +Pontine central gray,0.26,0.229,0.489 +"anterior commissure, olfactory limb",0.382,0.376,0.758 +"Posterolateral visual area, layer 5",0.101,0.115,0.21600000000000003 +External cuneate nucleus,0.105,0.105,0.21 +"Anterolateral visual area, layer 2/3",0.091,0.098,0.189 +"Retrosplenial area, lateral agranular part, layer 6a",0.203,0.20400000000000001,0.40700000000000003 +Paracentral nucleus,0.108,0.117,0.225 +"anterior commissure, temporal limb",0.115,0.111,0.226 +"Orbital area, medial part, layer 6a",0.088,0.08,0.16799999999999998 +trochlear nerve,0.004,0.004,0.008 +Lingula (I),0.049,0.057,0.10600000000000001 +Posterodorsal preoptic nucleus,0.004,0.005,0.009000000000000001 +brachium of the superior colliculus,0.085,0.08600000000000001,0.171 +"Anterior cingulate area, dorsal part, layer 6a",0.326,0.363,0.6890000000000001 +cerebal peduncle,0.465,0.455,0.92 +"Anterior cingulate area, dorsal part, layer 6b",0.01,0.02,0.03 +"Primary somatosensory area, nose, layer 6b",0.025,0.025,0.05 +Parafascicular nucleus,0.23800000000000002,0.264,0.502 +Pontine gray,0.485,0.48,0.965 +"Anterior cingulate area, dorsal part, layer 1",0.20700000000000002,0.353,0.56 +Declive (VI),1.472,1.691,3.1630000000000003 +"Nucleus ambiguus, dorsal division",0.013000000000000001,0.015,0.028 +cingulum bundle,0.655,0.553,1.2080000000000002 +"Primary motor area, Layer 2/3",1.8860000000000001,1.653,3.539 +Folium-tuber vermis (VII),0.494,0.534,1.028 +"Primary somatosensory area, upper limb, layer 6a",0.505,0.429,0.9339999999999999 +Posterior hypothalamic nucleus,0.328,0.363,0.6910000000000001 +vomeronasal nerve,0.008,0.006,0.014 +"Primary somatosensory area, mouth, layer 4",0.461,0.463,0.924 +Pyramus (VIII),0.515,0.622,1.137 +"Endopiriform nucleus, dorsal part",0.89,0.894,1.784 +"Primary auditory area, layer 6a",0.134,0.134,0.268 +"Lateral reticular nucleus, magnocellular part",0.27,0.264,0.534 +"corpus callosum, anterior forceps",0.418,0.417,0.835 +Uvula (IX),0.918,1.1500000000000001,2.068 +"Ventral auditory area, layer 1",0.131,0.135,0.266 +Piriform area,5.9,5.776,11.676 +"Secondary motor area, layer 2/3",1.8860000000000001,1.848,3.734 +"Lateral reticular nucleus, parvicellular part",0.03,0.031,0.061 +"corpus callosum, extreme capsule",0.057,0.048,0.10500000000000001 +"Retrosplenial area, lateral agranular part, layer 2/3",0.31,0.309,0.619 +"Endopiriform nucleus, ventral part",0.485,0.47900000000000004,0.964 +Nodulus (X),0.666,0.768,1.4340000000000002 +"Orbital area, ventrolateral part, layer 1",0.185,0.199,0.384 +"Paragigantocellular reticular nucleus, dorsal part",0.11800000000000001,0.101,0.21900000000000003 +"corpus callosum, posterior forceps",0.675,0.666,1.3410000000000002 +"Lateral visual area, layer 2/3",0.16,0.135,0.29500000000000004 +"Primary somatosensory area, mouth, layer 5",0.546,0.587,1.133 +Lobule II,0.613,0.626,1.2389999999999999 +Ectorhinal area/Layer 6a,0.195,0.183,0.378 +"Paragigantocellular reticular nucleus, lateral part",0.381,0.35100000000000003,0.732 +Dorsal premammillary nucleus,0.07200000000000001,0.069,0.14100000000000001 +"Primary somatosensory area, barrel field, layer 1",0.403,0.372,0.775 +Fasciola cinerea,0.031,0.031,0.062 +Lobule III,1.179,1.414,2.593 +"corpus callosum, splenium",0.329,0.329,0.658 +Ectorhinal area/Layer 5,0.267,0.254,0.521 +Fastigial nucleus,0.245,0.26,0.505 +"Ventral auditory area, layer 4",0.109,0.10400000000000001,0.21300000000000002 +"Agranular insular area, dorsal part, layer 1",0.224,0.23,0.454 +root,1.677,1.864,3.5410000000000004 +Fundus of striatum,0.23800000000000002,0.20400000000000001,0.44200000000000006 +Ventral premammillary nucleus,0.111,0.096,0.20700000000000002 +"Primary auditory area, layer 6b",0.017,0.019,0.036000000000000004 +"Primary somatosensory area, trunk, layer 1",0.098,0.093,0.191 +Simple lobule,2.845,2.587,5.432 +fiber tracts,0.777,0.772,1.549 +"Visceral area, layer 4",0.1,0.096,0.196 +"Anterior cingulate area, dorsal part, layer 5",0.54,0.529,1.069 +olfactory nerve layer of main olfactory bulb,0.503,0.5660000000000001,1.069 +Posterior complex of the thalamus,0.642,0.599,1.241 +"Secondary motor area, layer 6a",0.978,1.173,2.151 +"Globus pallidus, external segment",0.803,0.759,1.562 +"Ventral auditory area, layer 5",0.303,0.295,0.598 +Paramedian lobule,2.477,2.345,4.822 +"Primary somatosensory area, upper limb, layer 6b",0.041,0.045,0.086 +Posterior limiting nucleus of the thalamus,0.1,0.092,0.192 +"Primary somatosensory area, lower limb, layer 1",0.165,0.127,0.29200000000000004 +"Globus pallidus, internal segment",0.20500000000000002,0.198,0.403 +Copula pyramidis,1.258,1.057,2.315 +"Supplemental somatosensory area, layer 4",0.59,0.544,1.134 +Postsubiculum,0.535,0.509,1.044 +"Primary somatosensory area, barrel field, layer 6a",0.637,0.605,1.242 +Gracile nucleus,0.038,0.042,0.08 +Paraflocculus,2.914,2.7520000000000002,5.666 +crossed tectospinal pathway,0.25,0.243,0.493 +Peripeduncular nucleus,0.036000000000000004,0.035,0.07100000000000001 +Ectorhinal area/Layer 6b,0.033,0.025,0.058 +"Anteromedial visual area, layer 6a",0.061,0.058,0.119 +"Primary somatosensory area, barrel field, layer 4",0.641,0.599,1.24 +Gigantocellular reticular nucleus,1.262,1.303,2.565 +Flocculus,0.655,0.658,1.3130000000000002 +Pedunculopontine nucleus,0.464,0.39,0.8540000000000001 +"Infralimbic area, layer 6a",0.10200000000000001,0.095,0.197 +Crus 1,2.82,2.725,5.545 +"Visceral area, layer 5",0.355,0.353,0.708 +doral tegmental decussation,0.001,0.003,0.004 +Posterior pretectal nucleus,0.07100000000000001,0.07100000000000001,0.14200000000000002 +"Primary somatosensory area, barrel field, layer 6b",0.059000000000000004,0.07100000000000001,0.13 +Crus 2,2.481,2.52,5.0009999999999994 +"Anteromedial visual area, layer 2/3",0.114,0.089,0.203 +Parapyramidal nucleus,0.056,0.049,0.10500000000000001 +"Primary somatosensory area, barrel field, layer 5",0.635,0.5660000000000001,1.201 +"Medial geniculate complex, dorsal part",0.081,0.076,0.157 +"Anterolateral visual area, layer 1",0.056,0.063,0.119 +Perireunensis nucleus,0.075,0.082,0.157 +"Medial geniculate complex, ventral part",0.125,0.129,0.254 +"Infralimbic area, layer 6b",0.003,0.004,0.007 +Presubiculum,0.47100000000000003,0.445,0.916 +"Secondary motor area, layer 6b",0.037,0.039,0.076 +"Primary somatosensory area, trunk, layer 4",0.063,0.068,0.131 +"Medial geniculate complex, medial part",0.115,0.107,0.222 +Hippocampal formation,0.195,0.209,0.404 +"Supplemental somatosensory area, layer 5",1.065,0.997,2.062 +Lobules IV-V,3.079,3.399,6.478 +external medullary lamina of the thalamus,0.053,0.052000000000000005,0.10500000000000001 +"Pontine reticular nucleus, caudal part",1.21,1.218,2.428 +"Primary somatosensory area, lower limb, layer 4",0.131,0.153,0.28400000000000003 +"Anteromedial nucleus, dorsal part",0.135,0.105,0.24 +Hypothalamus,1.359,1.421,2.7800000000000002 +"Medullary reticular nucleus, dorsal part",0.533,0.516,1.049 +"Agranular insular area, dorsal part, layer 5",0.753,0.748,1.501 +"Primary somatosensory area, mouth, layer 6a",0.872,0.792,1.6640000000000001 +"Anteromedial nucleus, ventral part",0.095,0.07,0.165 +Intercalated amygdalar nucleus,0.10300000000000001,0.079,0.182 +"Visceral area, layer 2/3",0.275,0.269,0.544 +"Medullary reticular nucleus, ventral part",0.421,0.456,0.877 +genu of corpus callosum,0.403,0.392,0.795 +Parastrial nucleus,0.053,0.05,0.10300000000000001 +"Primary somatosensory area, trunk, layer 5",0.191,0.168,0.359 +Interanterodorsal nucleus of the thalamus,0.061,0.067,0.128 +"Anterolateral visual area, layer 4",0.053,0.049,0.10200000000000001 +genu of the facial nerve,0.019,0.014,0.033 +Interanteromedial nucleus of the thalamus,0.022,0.02,0.041999999999999996 +"Entorhinal area, lateral part, layer 1",0.494,0.46900000000000003,0.9630000000000001 +inferior cerebellar peduncle,0.372,0.363,0.735 +"Orbital area, ventrolateral part, layer 5",0.276,0.28300000000000003,0.559 +"Tuberomammillary nucleus, dorsal part",0.026000000000000002,0.024,0.05 +"Temporal association areas, layer 2/3",0.377,0.329,0.706 +"Primary somatosensory area, lower limb, layer 5",0.211,0.304,0.515 +"Nucleus of the lateral olfactory tract, layer 3",0.037,0.029,0.066 +Median eminence,0.029,0.053,0.082 +"Dentate gyrus, molecular layer",2.233,2.071,4.304 +"Dentate gyrus, polymorph layer",0.324,0.295,0.619 +"Primary somatosensory area, unassigned, layer 1",0.084,0.067,0.15100000000000002 +"Primary somatosensory area, unassigned, layer 2/3",0.17500000000000002,0.138,0.31300000000000006 +"Primary somatosensory area, unassigned, layer 4",0.075,0.08,0.155 +"Primary somatosensory area, unassigned, layer 5",0.11900000000000001,0.12,0.239 +"Primary somatosensory area, unassigned, layer 6a",0.164,0.158,0.322 +"Primary somatosensory area, unassigned, layer 6b",0.016,0.015,0.031 +"Anterior area, layer 1",0.10200000000000001,0.117,0.21900000000000003 +"Anterior area, layer 2/3",0.209,0.20700000000000002,0.41600000000000004 +"Anterior area, layer 4",0.089,0.073,0.16199999999999998 +"Anterior area, layer 5",0.2,0.16,0.36 +"Anterior area, layer 6a",0.11,0.094,0.20400000000000001 +"Anterior area, layer 6b",0.022,0.023,0.045 +"Laterointermediate area, layer 1",0.036000000000000004,0.032,0.068 +"Laterointermediate area, layer 2/3",0.06,0.054,0.11399999999999999 +"Laterointermediate area, layer 4",0.03,0.031,0.061 +"Laterointermediate area, layer 5",0.078,0.069,0.14700000000000002 +"Laterointermediate area, layer 6a",0.04,0.032,0.07200000000000001 +"Laterointermediate area, layer 6b",0.008,0.009000000000000001,0.017 +"Rostrolateral area, layer 1",0.088,0.081,0.16899999999999998 +"Rostrolateral area, layer 2/3",0.148,0.134,0.28200000000000003 +"Rostrolateral area, layer 4",0.075,0.07,0.14500000000000002 +"Rostrolateral area, layer 5",0.111,0.116,0.227 +"Rostrolateral area, layer 6a",0.073,0.079,0.152 +"Rostrolateral area, layer 6b",0.011,0.016,0.027 +"Postrhinal area, layer 1",0.113,0.117,0.23 +"Postrhinal area, layer 2/3",0.178,0.163,0.34099999999999997 +"Postrhinal area, layer 4",0.033,0.03,0.063 +"Postrhinal area, layer 5",0.17300000000000001,0.185,0.358 +"Postrhinal area, layer 6a",0.082,0.09,0.172 +"Postrhinal area, layer 6b",0.017,0.019,0.036000000000000004 +Prosubiculum,0.58,0.562,1.142 +Area prostriata,0.181,0.183,0.364 +supra-callosal cerebral white matter,0.56,0.501,1.061 +"corpus callosum, body",1.458,1.252,2.71 +optic radiation,0.865,0.867,1.732 +auditory radiation,0.22,0.198,0.41800000000000004 +commissural branch of stria terminalis,0.017,0.018000000000000002,0.035 +"Dorsal part of the lateral geniculate complex, shell",0.10400000000000001,0.097,0.201 +"Dorsal part of the lateral geniculate complex, core",0.211,0.203,0.41400000000000003 +"Dorsal part of the lateral geniculate complex, ipsilateral zone",0.043000000000000003,0.043000000000000003,0.08600000000000001 +"Frontal pole, layer 5",0.176,0.17500000000000002,0.351 +"Frontal pole, layer 6a",0.04,0.048,0.088 +"Frontal pole, layer 6b",0.001,0.001,0.002 +"Orbital area, medial part, layer 6b",0.004,0.002,0.006 +Retroparafascicular nucleus,0.027,0.033,0.06 +Medial accesory oculomotor nucleus,0.01,0.006,0.016 +Peritrigeminal zone,0.158,0.162,0.32 +Accessory trigeminal nucleus,0.005,0.007,0.012 +Parvicellular motor 5 nucleus,0.029,0.033,0.062 +Intertrigeminal nucleus,0.02,0.028,0.048 +Ethmoid nucleus of the thalamus,0.129,0.112,0.241 +Xiphoid thalamic nucleus,0.007,0.07100000000000001,0.07800000000000001 +Posterior intralaminar thalamic nucleus,0.101,0.091,0.192 +Posterior triangular thalamic nucleus,0.131,0.128,0.259 +Intermediate geniculate nucleus,0.01,0.01,0.02 +Ventromedial preoptic nucleus,0.02,0.021,0.041 +Perifornical nucleus,0.113,0.108,0.221 +Hippocampo-amygdalar transition area,0.203,0.2,0.403 +Paratrigeminal nucleus,0.054,0.05,0.10400000000000001 +Vestibulocerebellar nucleus,0.039,0.046,0.08499999999999999 +Subcommissural organ,0.002,0.009000000000000001,0.011000000000000001 +Posterodorsal tegmental nucleus,0.021,0.022,0.043 +"Medial mammillary nucleus, lateral part",0.111,0.11,0.221 +"Medial mammillary nucleus, medial part",0.065,0.07,0.135 +"Medial mammillary nucleus, posterior part",0.011,0.02,0.031 +"Medial mammillary nucleus, dorsal part",0.032,0.044,0.076 +Paratrochlear nucleus,0.011,0.007,0.018 +Paranigral nucleus,0.012,0.011,0.023 +"Interpeduncular nucleus, rostral",0.029,0.051000000000000004,0.08 +"Interpeduncular nucleus, caudal",0.021,0.045,0.066 +"Interpeduncular nucleus, apical",0.004,0.012,0.016 +"Interpeduncular nucleus, lateral",0.029,0.031,0.06 +"Interpeduncular nucleus, intermediate",0.02,0.021,0.041 +"Interpeduncular nucleus, dorsomedial",0.011,0.009000000000000001,0.02 +"Interpeduncular nucleus, dorsolateral",0.015,0.018000000000000002,0.033 +"Interpeduncular nucleus, rostrolateral",0.009000000000000001,0.009000000000000001,0.018000000000000002 +Supraoculomotor periaqueductal gray,0.015,0.018000000000000002,0.033 diff --git a/tests/data/signal/signal_ch000000.tif b/tests/data/signal/signal_ch000000.tif new file mode 100644 index 00000000..0c3456ce Binary files /dev/null and b/tests/data/signal/signal_ch000000.tif differ diff --git a/tests/data/signal/signal_ch000001.tif b/tests/data/signal/signal_ch000001.tif new file mode 100644 index 00000000..085b2afb Binary files /dev/null and b/tests/data/signal/signal_ch000001.tif differ diff --git a/tests/data/signal/signal_ch000002.tif b/tests/data/signal/signal_ch000002.tif new file mode 100644 index 00000000..a5b65252 Binary files /dev/null and b/tests/data/signal/signal_ch000002.tif differ diff --git a/tests/data/signal/signal_ch000003.tif b/tests/data/signal/signal_ch000003.tif new file mode 100644 index 00000000..367b8532 Binary files /dev/null and b/tests/data/signal/signal_ch000003.tif differ diff --git a/tests/data/signal/signal_ch000004.tif b/tests/data/signal/signal_ch000004.tif new file mode 100644 index 00000000..81a0d018 Binary files /dev/null and b/tests/data/signal/signal_ch000004.tif differ diff --git a/tests/data/signal/signal_ch000005.tif b/tests/data/signal/signal_ch000005.tif new file mode 100644 index 00000000..cb479e8e Binary files /dev/null and b/tests/data/signal/signal_ch000005.tif differ diff --git a/tests/data/signal/signal_ch000006.tif b/tests/data/signal/signal_ch000006.tif new file mode 100644 index 00000000..56161f0d Binary files /dev/null and b/tests/data/signal/signal_ch000006.tif differ diff --git a/tests/data/signal/signal_ch000007.tif b/tests/data/signal/signal_ch000007.tif new file mode 100644 index 00000000..7af83e4d Binary files /dev/null and b/tests/data/signal/signal_ch000007.tif differ diff --git a/tests/data/signal/signal_ch000008.tif b/tests/data/signal/signal_ch000008.tif new file mode 100644 index 00000000..03795ddf Binary files /dev/null and b/tests/data/signal/signal_ch000008.tif differ diff --git a/tests/data/signal/signal_ch000009.tif b/tests/data/signal/signal_ch000009.tif new file mode 100644 index 00000000..9d28134d Binary files /dev/null and b/tests/data/signal/signal_ch000009.tif differ diff --git a/tests/data/signal/signal_ch000010.tif b/tests/data/signal/signal_ch000010.tif new file mode 100644 index 00000000..30aa0b20 Binary files /dev/null and b/tests/data/signal/signal_ch000010.tif differ diff --git a/tests/data/signal/signal_ch000011.tif b/tests/data/signal/signal_ch000011.tif new file mode 100644 index 00000000..e361256e Binary files /dev/null and b/tests/data/signal/signal_ch000011.tif differ diff --git a/tests/data/signal/signal_ch000012.tif b/tests/data/signal/signal_ch000012.tif new file mode 100644 index 00000000..da655f39 Binary files /dev/null and b/tests/data/signal/signal_ch000012.tif differ diff --git a/tests/data/signal/signal_ch000013.tif b/tests/data/signal/signal_ch000013.tif new file mode 100644 index 00000000..8f176dd4 Binary files /dev/null and b/tests/data/signal/signal_ch000013.tif differ diff --git a/tests/data/signal/signal_ch000014.tif b/tests/data/signal/signal_ch000014.tif new file mode 100644 index 00000000..0246e1a8 Binary files /dev/null and b/tests/data/signal/signal_ch000014.tif differ diff --git a/tests/data/signal/signal_ch000015.tif b/tests/data/signal/signal_ch000015.tif new file mode 100644 index 00000000..86e44f1f Binary files /dev/null and b/tests/data/signal/signal_ch000015.tif differ diff --git a/tests/data/signal/signal_ch000016.tif b/tests/data/signal/signal_ch000016.tif new file mode 100644 index 00000000..75a9f430 Binary files /dev/null and b/tests/data/signal/signal_ch000016.tif differ diff --git a/tests/data/signal/signal_ch000017.tif b/tests/data/signal/signal_ch000017.tif new file mode 100644 index 00000000..dde72ae8 Binary files /dev/null and b/tests/data/signal/signal_ch000017.tif differ diff --git a/tests/data/signal/signal_ch000018.tif b/tests/data/signal/signal_ch000018.tif new file mode 100644 index 00000000..e07e823f Binary files /dev/null and b/tests/data/signal/signal_ch000018.tif differ diff --git a/tests/data/signal/signal_ch000019.tif b/tests/data/signal/signal_ch000019.tif new file mode 100644 index 00000000..71353e6e Binary files /dev/null and b/tests/data/signal/signal_ch000019.tif differ diff --git a/tests/data/signal/signal_ch000020.tif b/tests/data/signal/signal_ch000020.tif new file mode 100644 index 00000000..897355b4 Binary files /dev/null and b/tests/data/signal/signal_ch000020.tif differ diff --git a/tests/data/signal/signal_ch000021.tif b/tests/data/signal/signal_ch000021.tif new file mode 100644 index 00000000..619851d6 Binary files /dev/null and b/tests/data/signal/signal_ch000021.tif differ diff --git a/tests/data/signal/signal_ch000022.tif b/tests/data/signal/signal_ch000022.tif new file mode 100644 index 00000000..95ed5efc Binary files /dev/null and b/tests/data/signal/signal_ch000022.tif differ diff --git a/tests/data/signal/signal_ch000023.tif b/tests/data/signal/signal_ch000023.tif new file mode 100644 index 00000000..96078183 Binary files /dev/null and b/tests/data/signal/signal_ch000023.tif differ diff --git a/tests/data/signal/signal_ch000024.tif b/tests/data/signal/signal_ch000024.tif new file mode 100644 index 00000000..a5e63056 Binary files /dev/null and b/tests/data/signal/signal_ch000024.tif differ diff --git a/tests/data/signal/signal_ch000025.tif b/tests/data/signal/signal_ch000025.tif new file mode 100644 index 00000000..474232e4 Binary files /dev/null and b/tests/data/signal/signal_ch000025.tif differ diff --git a/tests/tests/conftest.py b/tests/tests/conftest.py new file mode 100644 index 00000000..6f29d259 --- /dev/null +++ b/tests/tests/conftest.py @@ -0,0 +1,56 @@ +import pathlib +import sys + +import pytest +from brainglobe_utils.general.config import get_config_obj +from cellfinder_core.download.cli import main as cellfinder_download + +test_data_dir = pathlib.Path(__file__) / ".." / ".." / "data" +data_dir = test_data_dir / "brain" +test_output_dir = test_data_dir / "registration_output" + +TEST_ATLAS = "allen_2017_100um" + + +def download_atlas(directory): + download_args = [ + "cellfinder_download", + "--atlas", + TEST_ATLAS, + "--install-path", + directory, + "--no-amend-config", + "--no-models", + ] + sys.argv = download_args + cellfinder_download() + return directory + + +def generate_test_config(atlas_dir): + config = test_data_dir / "config" / "test.conf" + config_obj = get_config_obj(config) + atlas_conf = config_obj["atlas"] + orig_base_directory = atlas_conf["base_folder"] + + with open(config, "r") as in_conf: + data = in_conf.readlines() + for i, line in enumerate(data): + data[i] = line.replace( + f"base_folder = '{orig_base_directory}", + f"base_folder = '{atlas_dir / 'atlas' / TEST_ATLAS}", + ) + test_config = atlas_dir / "config.conf" + with open(test_config, "w") as out_conf: + out_conf.writelines(data) + + return test_config + + +@pytest.fixture() +def test_config_path(tmpdir): + print("fixture") + atlas_directory = str(tmpdir) + download_atlas(atlas_directory) + test_config = generate_test_config(atlas_directory) + return test_config diff --git a/tests/tests/test_integration/test_detection.py b/tests/tests/test_integration/test_detection.py new file mode 100644 index 00000000..e4cd5e26 --- /dev/null +++ b/tests/tests/test_integration/test_detection.py @@ -0,0 +1,76 @@ +import os +import sys +from math import isclose + +import brainglobe_utils.IO.cells as cell_io +import pytest + +from cellfinder.main import main as cellfinder_run + +data_dir = os.path.join( + os.getcwd(), "tests", "data", "integration", "detection" +) +signal_data = os.path.join(data_dir, "crop_planes", "ch0") +background_data = os.path.join(data_dir, "crop_planes", "ch1") +cells_validation_xml = os.path.join(data_dir, "cell_classification.xml") + +x_pix = "2" +y_pix = "2" +z_pix = "5" + +DETECTION_TOLERANCE = 2 + + +# FIXME: This isn't a very good example + + +@pytest.mark.slow +def test_detection_full(tmpdir): + cellfinder_args = [ + "cellfinder", + "-s", + signal_data, + "-b", + background_data, + "-o", + str(tmpdir), + "-v", + z_pix, + y_pix, + x_pix, + "--orientation", + "psl", + "--n-free-cpus", + "0", + "--no-register", + "--save-planes", + ] + sys.argv = cellfinder_args + cellfinder_run() + + cells_test_xml = tmpdir / "points" / "cell_classification.xml" + + cells_validation = cell_io.get_cells(cells_validation_xml) + cells_test = cell_io.get_cells(str(cells_test_xml)) + + num_non_cells_validation = sum( + [cell.type == 1 for cell in cells_validation] + ) + num_cells_validation = sum([cell.type == 2 for cell in cells_validation]) + + num_non_cells_test = sum([cell.type == 1 for cell in cells_test]) + num_cells_test = sum([cell.type == 2 for cell in cells_test]) + + assert isclose( + num_non_cells_validation, + num_non_cells_test, + abs_tol=DETECTION_TOLERANCE, + ) + assert isclose( + num_cells_validation, num_cells_test, abs_tol=DETECTION_TOLERANCE + ) + # Check that planes are saved + for i in range(2, 30): + assert ( + tmpdir / "processed_planes" / f"plane_{str(i).zfill(4)}.tif" + ).exists() diff --git a/tests/tests/test_integration/test_extract.py b/tests/tests/test_integration/test_extract.py new file mode 100644 index 00000000..1116ee58 --- /dev/null +++ b/tests/tests/test_integration/test_extract.py @@ -0,0 +1,170 @@ +import os + +import imio +import numpy as np +import pytest +from brainglobe_utils.cells.cells import Cell +from brainglobe_utils.general.system import ( + delete_directory_contents, + get_sorted_file_paths, +) +from brainglobe_utils.IO.cells import get_cells +from tifffile import tifffile + +import cellfinder.extract.extract_cubes as extract_cubes + +data_dir = os.path.join("tests", "data") + +signal_data_dir = os.path.join(data_dir, "signal") +background_data_dir = os.path.join(data_dir, "background") +xml_path = os.path.join(data_dir, "cube_extract", "cells.xml") +validate_cubes_dir = os.path.join(data_dir, "cube_extract", "cubes") +validate_cubes_scale_dir = os.path.join( + data_dir, "cube_extract", "cubes_scale" +) + + +class CubeExtractArgs: + def __init__(self, tmpdir): + self.cells_file_path = xml_path + + self.cube_width = 50 + self.cube_height = 50 + self.cube_depth = 20 + self.save_empty_cubes = False + self.voxel_sizes = [5, 1, 1] + + # get these from parser defaults + self.network_voxel_sizes = [5, 1, 1] + + self.n_free_cpus = 0 + self.n_max_threads = 10 + self.max_ram = None + + self.paths = Paths(cells_file_path=xml_path, cubes_output_dir=tmpdir) + + @staticmethod + def get_plane_paths(): + return signal_data_dir + background_data_dir + + +class Paths: + def __init__(self, cells_file_path=None, cubes_output_dir=None): + self.cells_file_path = cells_file_path + self.tmp__cubes_output_dir = cubes_output_dir + + +def load_cubes_in_dir(directory): + cube_list = os.listdir(directory) + cubes = [] + for file in cube_list: + file_path = os.path.join(directory, file) + cubes.append(imio.load_any(file_path)) + return cubes + + +def test_cube_extraction(tmpdir, depth=20): + tmpdir = str(tmpdir) + args = CubeExtractArgs(tmpdir) + + planes_paths = {} + planes_paths[0] = get_sorted_file_paths( + signal_data_dir, file_extension="tif" + ) + planes_paths[1] = get_sorted_file_paths( + background_data_dir, file_extension="tif" + ) + + extract_cubes.main( + get_cells(args.paths.cells_file_path), + args.paths.tmp__cubes_output_dir, + planes_paths, + args.cube_depth, + args.cube_width, + args.cube_height, + args.voxel_sizes, + args.network_voxel_sizes, + args.max_ram, + args.n_free_cpus, + args.save_empty_cubes, + ) + + validation_cubes = load_cubes_in_dir(validate_cubes_dir) + test_cubes = load_cubes_in_dir(tmpdir) + + for idx, test_cube in enumerate(test_cubes): + assert (validation_cubes[idx] == test_cube).all() + + delete_directory_contents(tmpdir) + + # test cube scaling + args.voxel_sizes = [7.25, 2, 2] + args.x_pixel_um = 2 + args.y_pixel_um = 2 + args.z_pixel_um = 7.25 + + extract_cubes.main( + get_cells(args.paths.cells_file_path), + args.paths.tmp__cubes_output_dir, + planes_paths, + args.cube_depth, + args.cube_width, + args.cube_height, + args.voxel_sizes, + args.network_voxel_sizes, + args.max_ram, + args.n_free_cpus, + args.save_empty_cubes, + ) + + validation_cubes_scale = load_cubes_in_dir(validate_cubes_scale_dir) + test_cubes = load_cubes_in_dir(tmpdir) + for idx, test_cube in enumerate(test_cubes): + assert (validation_cubes_scale[idx] == test_cube).all() + + # test edge of data errors + cell = Cell("x0y0z10", 2) + plane_paths = os.listdir(signal_data_dir) + first_plane = tifffile.imread( + os.path.join(signal_data_dir, plane_paths[0]) + ) + stack_shape = first_plane.shape + (depth,) + stacks = {} + stacks[0] = np.zeros(stack_shape, dtype=np.uint16) + stacks[0][:, :, 0] = first_plane + + for plane in range(1, depth): + im_path = os.path.join(signal_data_dir, plane_paths[plane]) + stacks[0][:, :, plane] = tifffile.imread(im_path) + + cube = extract_cubes.Cube(cell, 0, stacks) + assert (cube.data == 0).all() + + cell = Cell("x2500y2500z10", 2) + cube = extract_cubes.Cube(cell, 0, stacks) + assert (cube.data == 0).all() + + # test insufficient z-planes for a specific cube + stacks[0] = stacks[0][:, :, 1:] + cube = extract_cubes.Cube(cell, 0, stacks) + assert (cube.data == 0).all() + + # test insufficient z-planes for any cube to be extracted at all. + delete_directory_contents(tmpdir) + # args.z_pixel_um = 0.1 + args.voxel_sizes[0] = 0.1 + + with pytest.raises(extract_cubes.StackSizeError): + extract_cubes.main( + get_cells(args.paths.cells_file_path), + args.paths.tmp__cubes_output_dir, + planes_paths, + args.cube_depth, + args.cube_width, + args.cube_height, + args.voxel_sizes, + args.network_voxel_sizes, + args.max_ram, + args.n_free_cpus, + args.save_empty_cubes, + ) diff --git a/tests/tests/test_integration/test_registration.py b/tests/tests/test_integration/test_registration.py new file mode 100644 index 00000000..cc6d66f7 --- /dev/null +++ b/tests/tests/test_integration/test_registration.py @@ -0,0 +1,111 @@ +import os +import platform +import sys + +import numpy as np +import pandas as pd +import pytest +from imio.load import load_any + +from cellfinder.main import main as cellfinder_run + +data_dir = os.path.join( + os.getcwd(), + "tests", + "data", + "brain", +) + +test_niftyreg_output = os.path.join( + os.getcwd(), "tests", "data", "registration_output", platform.system() +) + +x_pix = "40" +y_pix = "40" +z_pix = "50" + +relative_tolerance = 0.01 +absolute_tolerance = 10 +check_less_precise_pd = 1 + + +@pytest.mark.xfail(reason="Issues across machines") +@pytest.mark.slow +def test_registration_niftyreg(tmpdir): + output_directory = os.path.join(str(tmpdir), "output") + cellfinder_args = [ + "cellfinder", + "-s", + data_dir, + "-b", + data_dir, + "-o", + output_directory, + "-v", + z_pix, + y_pix, + x_pix, + "--orientation", + "psl", + "--n-free-cpus", + "0", + "--atlas", + "allen_mouse_100um", + "--no-detection", + "--no-classification", + "--no-analyse", + "--no-figures", + ] + + sys.argv = cellfinder_args + cellfinder_run() + + # none of this testing is ideal, as results seem to vary between systems + + if platform.system() == "Linux": + image_list = [ + "boundaries.tiff", + "deformation_field_0.tiff", + "deformation_field_1.tiff", + "deformation_field_2.tiff", + "downsampled.tiff", + "downsampled_channel_0.tiff", + "downsampled_standard.tiff", + "downsampled_standard_channel_0.tiff", + "registered_atlas.tiff", + "registered_hemispheres.tiff", + ] + else: + image_list = [ + "boundaries.tiff", + "deformation_field_0.tiff", + "deformation_field_1.tiff", + "deformation_field_2.tiff", + "downsampled.tiff", + "downsampled_channel_0.tiff", + # "downsampled_standard.tiff", + # "downsampled_standard_channel_0.tiff", + # "registered_atlas.tiff", + # "registered_hemispheres.tiff", + ] + output_directory = os.path.join(output_directory, "registration") + for image in image_list: + are_images_equal(image, output_directory, test_niftyreg_output) + + if platform.system() == "Linux": + pd.testing.assert_frame_equal( + pd.read_csv(os.path.join(output_directory, "volumes.csv")), + pd.read_csv(os.path.join(test_niftyreg_output, "volumes.csv")), + ) + + +def are_images_equal(image_name, output_directory, test_output_directory): + image = load_any( + os.path.join(output_directory, image_name), + ) + test_image = load_any( + os.path.join(test_output_directory, image_name), + ) + np.testing.assert_allclose( + image, test_image, rtol=relative_tolerance, atol=absolute_tolerance + ) diff --git a/tests/tests/test_unit/test_tools/test_image_processing.py b/tests/tests/test_unit/test_tools/test_image_processing.py new file mode 100644 index 00000000..788fa01d --- /dev/null +++ b/tests/tests/test_unit/test_tools/test_image_processing.py @@ -0,0 +1,37 @@ +import random + +import numpy as np + +from cellfinder.tools import image_processing as img_tools + + +def test_crop_center_2d(): + x_shape = random.randint(2, 100) + y_shape = random.randint(2, 100) + img = np.random.rand(y_shape, x_shape) + assert ( + img == img_tools.crop_center_2d(img, crop_x=x_shape, crop_y=y_shape) + ).all() + + new_x_shape = random.randint(1, x_shape) + new_y_shape = random.randint(1, y_shape) + pad_img = img_tools.crop_center_2d( + img, crop_x=new_x_shape, crop_y=new_y_shape + ) + assert (new_y_shape, new_x_shape) == pad_img.shape + + +def test_pad_centre_2d(): + x_shape = random.randint(2, 100) + y_shape = random.randint(2, 100) + img = np.random.rand(y_shape, x_shape) + assert ( + img == img_tools.pad_center_2d(img, x_size=x_shape, y_size=y_shape) + ).all() + + new_x_shape = random.randint(x_shape, x_shape * 10) + new_y_shape = random.randint(y_shape, y_shape * 10) + pad_img = img_tools.pad_center_2d( + img, x_size=new_x_shape, y_size=new_y_shape + ) + assert (new_y_shape, new_x_shape) == pad_img.shape diff --git a/tests/tests/test_unit/test_tools/test_prep.py b/tests/tests/test_unit/test_tools/test_prep.py new file mode 100644 index 00000000..404b5703 --- /dev/null +++ b/tests/tests/test_unit/test_tools/test_prep.py @@ -0,0 +1,241 @@ +import os + +import pytest +from brainglobe_utils.general.exceptions import CommandLineInputError + +from cellfinder.tools import prep + +# import shutil + +# from pathlib import Path + + +data_dir = os.path.join("tests", "data") + + +def test_check_return_ch_ids(): + signal_ch = [0, 1, 3] + bg_ch = 6 + signal_list = ["file1.txt", "file_2.txt", "file_3.txt"] + # None given + assert ([0, 1, 2], 3) == prep.check_and_return_ch_ids( + None, None, signal_list + ) + # Only signal given + assert (signal_ch, 4) == prep.check_and_return_ch_ids( + signal_ch, None, signal_list + ) + + # Only background given + assert ([7, 8, 9], bg_ch) == prep.check_and_return_ch_ids( + None, bg_ch, signal_list + ) + + # Both given (no overlap) + assert (signal_ch, bg_ch) == prep.check_and_return_ch_ids( + signal_ch, bg_ch, signal_list + ) + + # Both given (overlap) + with pytest.raises(CommandLineInputError): + assert prep.check_and_return_ch_ids(signal_ch, 3, signal_list) + + +class Args: + def __init__( + self, + model_dir=None, + empty=None, + no_detection=False, + no_classification=False, + no_register=False, + no_analyse=False, + no_standard_space=False, + output_dir=None, + registration_output_folder=None, + cells_file_path=None, + cubes_output_dir=None, + classification_out_file=None, + cells_in_standard_space=None, + ): + self.cell_count_model_dir = model_dir + self.empty = empty + + self.no_detection = no_detection + self.no_classification = no_classification + self.no_register = no_register + self.no_summarise = no_analyse + self.no_standard_space = no_standard_space + + self.output_dir = output_dir + + self.paths = Paths( + output_dir=registration_output_folder, + cells_file_path=cells_file_path, + cubes_output_dir=cubes_output_dir, + classification_out_file=classification_out_file, + cells_in_standard_space=cells_in_standard_space, + ) + + +class Paths: + def __init__( + self, + output_dir=None, + cells_file_path=None, + cubes_output_dir=None, + classification_out_file=None, + cells_in_standard_space=None, + ): + self.registration_output_folder = output_dir + self.cells_file_path = cells_file_path + self.tmp__cubes_output_dir = cubes_output_dir + self.classification_out_file = classification_out_file + self.cells_in_standard_space = cells_in_standard_space + + +# def get_dict_of_what_to_run(what_to_run): +# what_to_run_dict = { +# "detect": what_to_run.detect, +# "classify": what_to_run.classify, +# "register": what_to_run.register, +# "figures": what_to_run.figures, +# } +# return what_to_run_dict +# +# +# def test_calc_what_to_run(tmpdir): +# tmpdir = str(tmpdir) +# +# # registered_atlas_path = os.path.join(tmpdir, "registered_atlas.tiff") +# cells_file_path = os.path.join(tmpdir, "cells.xml") +# classification_out_file_path = os.path.join( +# tmpdir, "cell_classification.xml" +# ) +# summary_cell_counts_path = os.path.join( +# tmpdir, "summary_cell_counts.csv") +# figures_dir = os.path.join(tmpdir, "figures") +# +# args = Args( +# output_dir=tmpdir, +# registration_output_folder=tmpdir, +# cells_file_path=cells_file_path, +# classification_out_file=classification_out_file_path, +# figures_dir=figures_dir, +# ) +# +# # default +# what_to_run = prep.CalcWhatToRun(args) +# default_validation = { +# "detect": True, +# "classify": True, +# "register": False, +# "figures": False, +# } +# default_test = get_dict_of_what_to_run(what_to_run) +# assert default_validation == default_test +# +# # options +# args.no_classification = True +# what_to_run = prep.CalcWhatToRun(args) +# validation = { +# "detect": True, +# "classify": False, +# "register": False, +# "figures": False, +# } +# test = get_dict_of_what_to_run(what_to_run) +# assert validation == test +# +# +# # # existance +# # Path(registered_atlas_path).touch() +# # what_to_run = prep.CalcWhatToRun(args) +# # validation = { +# # "detect": True, +# # "classify": True, +# # "register": False, +# # "figures": True, +# # } +# # test = get_dict_of_what_to_run(what_to_run) +# # assert validation == test +# +# Path(cells_file_path).touch() +# what_to_run.update(args) +# validation = { +# "detect": False, +# "classify": True, +# "register": False, +# "figures": True, +# } +# test = get_dict_of_what_to_run(what_to_run) +# assert validation == test +# +# os.remove(cells_file_path) +# what_to_run.update(args) +# validation = { +# "detect": True, +# "classify": True, +# "register": False, +# "figures": True, +# } +# test = get_dict_of_what_to_run(what_to_run) +# assert validation == test +# +# Path(classification_out_file_path).touch() +# what_to_run.update(args) +# validation = { +# "detect": False, +# "classify": False, +# "register": False, +# "figures": True, +# } +# test = get_dict_of_what_to_run(what_to_run) +# assert validation == test +# +# Path(summary_cell_counts_path).touch() +# what_to_run.update(args) +# validation = { +# "detect": False, +# "classify": False, +# "register": False, +# "summarise": False, +# "figures": True, +# } +# test = get_dict_of_what_to_run(what_to_run) +# assert validation == test +# +# make_and_fill_directory(figures_dir) +# args.figures = True +# what_to_run.update(args) +# validation = { +# "detect": False, +# "classify": False, +# "register": False, +# "summarise": False, +# "figures": False, +# } +# test = get_dict_of_what_to_run(what_to_run) +# assert validation == test +# +# +# # os.remove(registered_atlas_path) +# os.remove(summary_cell_counts_path) +# shutil.rmtree(figures_dir) +# what_to_run.update(args) +# validation = { +# "detect": False, +# "classify": False, +# "register": True, +# "summarise": True, +# "figures": True, +# } +# test = get_dict_of_what_to_run(what_to_run) +# assert validation == test + + +def make_and_fill_directory(directory): + os.mkdir(directory) + for file_size in range(100, 200, 20): + with open(os.path.join(directory, str(file_size)), "wb") as fout: + fout.write(os.urandom(file_size)) diff --git a/tests/tests/test_unit/test_tools/test_system.py b/tests/tests/test_unit/test_tools/test_system.py new file mode 100644 index 00000000..480036d1 --- /dev/null +++ b/tests/tests/test_unit/test_tools/test_system.py @@ -0,0 +1,99 @@ +import os +from math import isclose +from pathlib import Path + +import pytest +from brainglobe_utils.general.exceptions import CommandLineInputError +from brainglobe_utils.general.system import ensure_directory_exists + +import cellfinder.tools.system as system + +data_dir = Path("tests", "data") +background_im_dir = os.path.join(data_dir, "background") + + +def test_get_subdirectories(): + subdirs = system.get_subdirectories(data_dir) + assert len(subdirs) == 9 + assert Path(data_dir / "cells") in subdirs + assert Path(data_dir / "brain") in subdirs + + subdir_names = system.get_subdirectories(data_dir, names_only=True) + assert len(subdir_names) == 9 + assert "cells" in subdir_names + assert "brain" in subdir_names + + +def test_get_number_of_files_in_dir(): + assert system.get_number_of_files_in_dir(background_im_dir) == 26 + + +def write_file_single_size(directory, file_size): + with open(os.path.join(directory, str(file_size)), "wb") as fout: + fout.write(os.urandom(file_size)) + + +def test_check_path_exists(tmpdir): + num = 10 + tmpdir = str(tmpdir) + + assert system.check_path_exists(os.path.join(tmpdir)) + no_exist_dir = os.path.join(tmpdir, "i_dont_exist") + with pytest.raises(FileNotFoundError): + assert system.check_path_exists(no_exist_dir) + + write_file_single_size(tmpdir, num) + assert system.check_path_exists(os.path.join(tmpdir, str(num))) + with pytest.raises(FileNotFoundError): + assert system.check_path_exists(os.path.join(tmpdir, "20")) + + +def test_catch_input_file_error(tmpdir): + tmpdir = str(tmpdir) + # check no error is raised: + system.catch_input_file_error(tmpdir) + + no_exist_dir = os.path.join(tmpdir, "i_dont_exist") + with pytest.raises(CommandLineInputError): + system.catch_input_file_error(no_exist_dir) + + +def test_ensure_directory_exists(): + home = os.path.expanduser("~") + exist_dir = os.path.join(home, ".cellfinder_test_dir") + ensure_directory_exists(exist_dir) + assert os.path.exists(exist_dir) + os.rmdir(exist_dir) + + +def test_memory_in_bytes(): + memory_detection_tolerance = 1 # byte + + assert isclose( + system.memory_in_bytes(1, "kb"), + 1000, + abs_tol=memory_detection_tolerance, + ) + assert isclose( + system.memory_in_bytes(1.2, "MB"), + 1200000, + abs_tol=memory_detection_tolerance, + ) + assert isclose( + system.memory_in_bytes(0.00065, "gb"), + 650000, + abs_tol=memory_detection_tolerance, + ) + assert isclose( + system.memory_in_bytes(0.000000000234, "TB"), + 234, + abs_tol=memory_detection_tolerance, + ) + assert isclose( + system.memory_in_bytes(1000, "pb"), + 10**18, + abs_tol=memory_detection_tolerance, + ) + + with pytest.raises(NotImplementedError): + system.memory_in_bytes(1000, "ab") diff --git a/tests/tests/test_unit/test_tools/test_tools_general.py b/tests/tests/test_unit/test_tools/test_tools_general.py new file mode 100644 index 00000000..61cce44e --- /dev/null +++ b/tests/tests/test_unit/test_tools/test_tools_general.py @@ -0,0 +1,65 @@ +import random + +import numpy as np +import pytest + +import cellfinder.tools.tools as tools + +a = [1, "a", 10, 30] +b = [30, 10, "c", "d"] + +test_2d_img = np.array([[1, 2, 10, 100], [5, 25, 300, 1000], [1, 0, 0, 125]]) +validate_2d_img = np.array( + [ + [65.535, 131.07, 655.35, 6553.5], + [327.675, 1638.375, 19660.5, 65535], + [65.535, 0, 0, 8191.875], + ] +) + + +def test_get_max_value(): + num = random.randint(0, 100) + assert 255 == tools.get_max_value(np.array(num, dtype=np.uint8)) + assert 65535 == tools.get_max_value(np.array(num, dtype=np.uint16)) + + +def test_union(): + ab = [1, "a", 10, 30, "c", "d"] + assert set(ab) == set(tools.union(a, b)) + + +def test_check_unique_list(): + assert (True, []) == tools.check_unique_list(a) + repeating_list = [1, 2, 3, 3, "dog", "cat", "dog"] + assert (False, [3, "dog"]) == tools.check_unique_list(repeating_list) + + +def test_common_member(): + assert (True, [10, 30]) == tools.common_member(a, b) + + +def test_get_number_of_bins_nd(): + array_tuple = (100, 1000, 5000) + assert tools.get_number_of_bins_nd(array_tuple, 12) == (8, 83, 416) + + shape_dict = {"x": 20, "y": 200} + assert tools.get_number_of_bins_nd(shape_dict, 8) == (2, 25) + + with pytest.raises(NotImplementedError): + tools.get_number_of_bins_nd([200, 300, 400], 10) + + +def test_interchange_np_fiji_coordinates(): + tuple_in = (100, 200, 300) + assert tools.interchange_np_fiji_coordinates(tuple_in) == (200, 100, 300) + + +def test_swap_elements_list(): + list_in = [1, 2, 3, 4] + assert tools.swap_elements_list(list_in, 1, 2) == [1, 3, 2, 4] + + +def test_is_any_list_overlap(): + assert tools.is_any_list_overlap(a, b) + assert not tools.is_any_list_overlap(a, [2, "b", (1, 2, 3)]) diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..ed409e7a --- /dev/null +++ b/tox.ini @@ -0,0 +1,25 @@ +# For more information about tox, see https://tox.readthedocs.io/en/latest/ +[tox] +envlist = py{38,39,310}-{coredev} + +[gh-actions] +python = + 3.8: py38 + 3.9: py39 + 3.10: py310 + +[gh-actions:env] +# This runs the coredev environment if the "coredev" github actions input +# is set to "true" +INPUT_COREDEV = + true: coredev + +[testenv] +commands = pytest -v --cov=./ --cov-report=xml +deps = + pytest-cov + pytest + coredev: git+https://github.com/brainglobe/cellfinder-core.git +description = + Run tests + coredev: Run tests with the development version of cellfinder-core