Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename everything to brainmapper and explicitly support old cellfinder directories #61

Merged
merged 2 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import json
import os
from pathlib import Path
from typing import Callable, List, Optional, Tuple, Union
from typing import Callable, Dict, List, Optional, Tuple, Union

import bg_space as bgs
from napari.types import LayerDataTuple
Expand All @@ -14,22 +14,25 @@
PathOrPaths = Union[List[os.PathLike], os.PathLike]


def is_wholebrain_cell_dir(path: os.PathLike) -> bool:
def is_brainmapper_dir(path: os.PathLike) -> bool:
"""
Determines whether a path is to a BrainGlobe workflows whole brain
Determines whether a path is to a BrainGlobe brainmapper whole brain
cell detection (previously cellfinder) output directory.
"""
path = os.path.abspath(path)
if os.path.isdir(path):
filelist = os.listdir(path)
else:
return False
if "cellfinder.json" in filelist:
if "brainmapper.json" in filelist:
return True
# for backwards compatibility
elif "cellfinder.json" in filelist:
return True
return False


def wholebrain_cell_read_dir(path: PathOrPaths) -> Optional[Callable]:
def brainmapper_read_dir(path: PathOrPaths) -> Optional[Callable]:
"""A basic implementation of the napari_get_reader hook specification.

Parameters
Expand All @@ -43,12 +46,23 @@ def wholebrain_cell_read_dir(path: PathOrPaths) -> Optional[Callable]:
If the path is a recognized format, return a function that accepts the
same path or list of paths, and returns a list of layer data tuples.
"""
if isinstance(path, str) and is_wholebrain_cell_dir(path):
if isinstance(path, str) and is_brainmapper_dir(path):
return reader_function
else:
return None


def get_metadata(directory: Path) -> Dict:
try:
with open(directory / "brainmapper.json") as json_file:
metadata = json.load(json_file)
# for backwards compatibility
except FileNotFoundError:
with open(directory / "cellfinder.json") as json_file:
metadata = json.load(json_file)
return metadata


def reader_function(
path: os.PathLike,
point_size: int = 15,
Expand Down Expand Up @@ -78,10 +92,9 @@ def reader_function(
layer_type=="image" if not provided
"""

print("Loading whole brain cell detection directory")
print("Loading brainmapper directory")
path = Path(os.path.abspath(path))
with open(path / "cellfinder.json") as json_file:
metadata = json.load(json_file)
metadata = get_metadata(path)

layers: List[LayerDataTuple] = []

Expand Down
8 changes: 4 additions & 4 deletions brainglobe_napari_io/napari.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ contributions:
title: Brainreg Read Directory Atlas Space
python_name: brainglobe_napari_io.brainreg.reader_dir_atlas_space:brainreg_read_dir_atlas_space

- id: brainglobe-napari-io.workflows_wholebrain_cell_read_dir
title: Workflows Whole Brain Cell Detection Read Directory
python_name: brainglobe_napari_io.workflows.wholebrain_cell_reader_dir:wholebrain_cell_read_dir
- id: brainglobe-napari-io.brainmapper_read_dir
title: Brainmapper Read Directory
python_name: brainglobe_napari_io.brainmapper.brainmapper_reader_dir:brainmapper_read_dir

- id: brainglobe-napari-io.cellfinder_read_xml
title: Cellfinder Read XML
Expand All @@ -34,7 +34,7 @@ contributions:
- '*.tiff'
accepts_directories: true

- command: brainglobe-napari-io.workflows_wholebrain_cell_read_dir
- command: brainglobe-napari-io.brainmapper_read_dir
filename_patterns:
- '*.tif'
accepts_directories: true
Expand Down
1 change: 1 addition & 0 deletions tests/data/brainmapper_output/brainmapper.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"signal_planes_paths": ["2"], "background_planes_path": ["4"], "output_dir": "output", "signal_ch_ids": null, "background_ch_id": null, "registration_config": "cellfinder.conf.custom", "voxel_sizes": ["5", "2.31", "2.31"], "network_voxel_sizes": [5, 1, 1], "no_detection": false, "no_classification": false, "no_register": false, "no_analyse": false, "no_figures": false, "start_plane": 0, "end_plane": -1, "save_planes": false, "outlier_keep": false, "artifact_keep": false, "max_cluster_size": 100000, "soma_diameter": 16, "ball_xy_size": 6, "ball_z_size": 15, "ball_overlap_fraction": 0.6, "log_sigma_size": 0.2, "n_sds_above_mean_thresh": 10, "soma_spread_factor": 1.4, "trained_model": "model.h5", "model_weights": null, "network_depth": "50", "batch_size": 64, "cube_width": 50, "cube_height": 50, "cube_depth": 20, "save_empty_cubes": false, "n_free_cpus": 8, "max_ram": null, "save_csv": false, "debug": false, "sort_input_file": false, "no_models": false, "model": "resnet50_tv", "heatmap_smooth": 100, "mask_figures": true, "install_path": ".cellfinder", "download_path": "tmp", "no_amend_config": false, "atlas": "allen_mouse_100um", "orientation": "prs", "backend": "niftyreg", "affine_n_steps": 6, "affine_use_n_steps": 5, "freeform_n_steps": 6, "freeform_use_n_steps": 4, "bending_energy_weight": 0.95, "grid_spacing": -10, "smoothing_sigma_reference": -1.0, "smoothing_sigma_floating": -1.0, "histogram_n_bins_floating": 128, "histogram_n_bins_reference": 128, "paths": {"output_dir": "output_dir", "registration_output_folder": "output_dir/brainreg_output", "metadata_path": "output/brainmapper.json", "registration_metadata_path": "output_dir/brainreg_output/brainreg.json"}}
90 changes: 90 additions & 0 deletions tests/tests/test_integration/test_brainmapper_reader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import json
import pathlib

import pytest

from brainglobe_napari_io.brainmapper import brainmapper_reader_dir

brainmapper_dir = (
pathlib.Path(__file__).parent.parent.parent / "data" / "brainmapper_output"
)
registration_dir = brainmapper_dir / "registration"

cellfinder_dir = (
pathlib.Path(__file__).parent.parent.parent / "data" / "cellfinder_output"
)
DOWNSAMPLED_IMAGE_SIZE = (135, 108, 77)


@pytest.fixture
def metadata():
with open(brainmapper_dir / "brainmapper.json") as json_file:
metadata = json.load(json_file)
return metadata


def test_is_brainmapper_dir():
assert brainmapper_reader_dir.is_brainmapper_dir(brainmapper_dir)
assert not brainmapper_reader_dir.is_brainmapper_dir(
brainmapper_dir.parent
)
assert not brainmapper_reader_dir.is_brainmapper_dir(__file__)


def test_is_cellfinder_dir():
assert brainmapper_reader_dir.is_brainmapper_dir(cellfinder_dir)


def test_brainmapper_read_dir():
assert (
brainmapper_reader_dir.brainmapper_read_dir(str(brainmapper_dir))
== brainmapper_reader_dir.reader_function
)
assert brainmapper_reader_dir.brainmapper_read_dir(brainmapper_dir) is None
assert (
brainmapper_reader_dir.brainmapper_read_dir(
str(brainmapper_dir.parent)
)
is None
)


def check_metadata(metadata):
assert metadata["atlas"] == "allen_mouse_100um"
assert metadata["orientation"] == "prs"
assert metadata["soma_diameter"] == 16


def test_get_metadata():
check_metadata(brainmapper_reader_dir.get_metadata(brainmapper_dir))
check_metadata(brainmapper_reader_dir.get_metadata(cellfinder_dir))


def test_load_brainmapper_dir():
layers = brainmapper_reader_dir.reader_function(brainmapper_dir)
assert len(layers) == 4

layer_names = ["allen_mouse_100um", "Boundaries", "Non cells", "Cells"]
layer_types = ["labels", "image", "points", "points"]
layer_shapes = [
DOWNSAMPLED_IMAGE_SIZE,
DOWNSAMPLED_IMAGE_SIZE,
(22, 3),
(103, 3),
]
for idx, layer in enumerate(layers):
assert layer[1]["name"] == layer_names[idx]
assert layer[2] == layer_types[idx]
assert layer[0].shape == layer_shapes[idx]


def test_load_registration(metadata):
layers = brainmapper_reader_dir.load_registration(
[], registration_dir, metadata
)
assert len(layers) == 2
assert layers[0][0].shape == DOWNSAMPLED_IMAGE_SIZE
assert layers[1][0].shape == DOWNSAMPLED_IMAGE_SIZE

assert layers[0][1]["name"] == "allen_mouse_100um"
assert layers[1][1]["name"] == "Boundaries"
2 changes: 1 addition & 1 deletion tests/tests/test_integration/test_brainreg_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
brainreg_dir = (
pathlib.Path(__file__).parent.parent.parent
/ "data"
/ "wholebrain_cell_output"
/ "brainmapper_output"
/ "registration"
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
brainreg_dir = (
pathlib.Path(__file__).parent.parent.parent
/ "data"
/ "wholebrain_cell_output"
/ "brainmapper_output"
/ "registration"
)

Expand Down
83 changes: 0 additions & 83 deletions tests/tests/test_integration/test_wholebrain_cell_reader.py

This file was deleted.

2 changes: 1 addition & 1 deletion tests/tests/test_unit/test_brainreg_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
brainreg_dir = (
pathlib.Path(__file__).parent.parent.parent
/ "data"
/ "wholebrain_cell_output"
/ "brainmapper_output"
/ "registration"
)

Expand Down