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

Add praire vole atlas packaging script #336

Merged
merged 20 commits into from
Oct 30, 2024
Merged
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
266 changes: 266 additions & 0 deletions brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
__version__ = "0"

Check warning on line 1 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L1

Added line #L1 was not covered by tests

import random
import shutil
import time
import zipfile
from pathlib import Path

Check warning on line 7 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L3-L7

Added lines #L3 - L7 were not covered by tests

import numpy as np
import pandas as pd
import pooch
import tifffile
from rich.progress import track

Check warning on line 13 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L9-L13

Added lines #L9 - L13 were not covered by tests

from brainglobe_atlasapi import utils
from brainglobe_atlasapi.atlas_generation.mesh_utils import (

Check warning on line 16 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L15-L16

Added lines #L15 - L16 were not covered by tests
Region,
create_region_mesh,
)
from brainglobe_atlasapi.atlas_generation.wrapup import wrapup_atlas_from_data
from brainglobe_atlasapi.structure_tree_util import get_structures_tree

Check warning on line 21 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L20-L21

Added lines #L20 - L21 were not covered by tests


def create_atlas(working_dir):
ATLAS_NAME = "prairie_vole"
SPECIES = "Microtus ochrogaster"
ATLAS_LINK = "https://doi.org/10.7554/eLife.87029"
CITATION = (

Check warning on line 28 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L24-L28

Added lines #L24 - L28 were not covered by tests
"Morgan L Gustison, Rodrigo Muñoz-Castañeda, Pavel Osten, "
"Steven M Phelps (2024) Sexual coordination "
"in a whole-brain map of prairie vole pair bonding eLife 12:RP87029 "
"https://doi.org/10.7554/eLife.87029.3"
)
ATLAS_BASE_URL = "https://ndownloader.figshare.com/files/"
ORIENTATION = "asr"
ROOT_ID = 997
ATLAS_PACKAGER = "Sacha Hadaway-Andreae"
ADDITIONAL_METADATA = {}

Check warning on line 38 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L34-L38

Added lines #L34 - L38 were not covered by tests

# setup folder for downloading
download_dir_path = working_dir / "downloads"
download_dir_path.mkdir(exist_ok=True)
atlas_path = download_dir_path / "atlas_files"

Check warning on line 43 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L41-L43

Added lines #L41 - L43 were not covered by tests

files = {

Check warning on line 45 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L45

Added line #L45 was not covered by tests
"PrV_ReferenceBrain_bilateral.tif": "42917449",
"PrV_Annotation_bilateral.tif": "42917452",
"PrV_Atlas_Ontology.csv": "42917443",
"PrV_results_datasets.zip": "42501327",
}

utils.check_internet_connection()
pooch.create(

Check warning on line 53 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L52-L53

Added lines #L52 - L53 were not covered by tests
path=atlas_path,
base_url=ATLAS_BASE_URL,
registry={},
)

for filename, file_id in files.items():
url = f"{ATLAS_BASE_URL}{file_id}"
pooch.retrieve(

Check warning on line 61 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L59-L61

Added lines #L59 - L61 were not covered by tests
url=url,
fname=filename,
path=atlas_path,
known_hash=None,
)

zip_file_path = atlas_path / "PrV_results_datasets.zip"
with zipfile.ZipFile(zip_file_path, "r") as zip_ref:
zip_ref.extract(

Check warning on line 70 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L68-L70

Added lines #L68 - L70 were not covered by tests
"results_datasets/neural_nomenclature_hierarchy.csv", atlas_path
)

if not (atlas_path / "neural_nomenclature_hierarchy.csv").exists():
shutil.move(

Check warning on line 75 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L74-L75

Added lines #L74 - L75 were not covered by tests
(
atlas_path
/ "results_datasets"
/ "neural_nomenclature_hierarchy.csv"
),
atlas_path,
)
else:
print(

Check warning on line 84 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L84

Added line #L84 was not covered by tests
f"File '{(atlas_path / 'neural_nomenclature_hierarchy.csv')}' "
f"already exists, skipping move operation."
)

shutil.rmtree(atlas_path / r"results_datasets")

Check warning on line 89 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L89

Added line #L89 was not covered by tests

annotations_file = atlas_path / "PrV_Annotation_bilateral.tif"
reference_file = atlas_path / "PrV_ReferenceBrain_bilateral.tif"
meshes_dir_path = atlas_path / "meshes"
meshes_dir_path.mkdir(exist_ok=True)

Check warning on line 94 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L91-L94

Added lines #L91 - L94 were not covered by tests

nomenclature_hierarchy = pd.read_csv(

Check warning on line 96 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L96

Added line #L96 was not covered by tests
atlas_path / "neural_nomenclature_hierarchy.csv"
).values
reference_id = pd.read_csv(atlas_path / "PrV_Atlas_Ontology.csv")

Check warning on line 99 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L99

Added line #L99 was not covered by tests

acronyms = reference_id["acronym"].values
names = reference_id["name"].values
ids = reference_id["id"].values

Check warning on line 103 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L101-L103

Added lines #L101 - L103 were not covered by tests

acronym_to_id = dict(zip(acronyms, ids))
name_to_id = dict(zip(names, ids))

Check warning on line 106 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L105-L106

Added lines #L105 - L106 were not covered by tests

ids = list(ids)
hierarchy = [

Check warning on line 109 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L108-L109

Added lines #L108 - L109 were not covered by tests
{
"acronym": "root",
"id": 997,
"name": "root",
"structure_id_path": [997],
"rgb_triplet": [255, 255, 255],
}
]

for row in nomenclature_hierarchy:
structure_hierarchy = []
unique_pairs = []
pairs = [(row[i], row[i + 1]) for i in range(0, len(row), 2)]
pairs_seen = set()

Check warning on line 123 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L119-L123

Added lines #L119 - L123 were not covered by tests

for pair in pairs:
if pair not in pairs_seen:
unique_pairs.append(pair)
pairs_seen.add(pair)

Check warning on line 128 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L125-L128

Added lines #L125 - L128 were not covered by tests

for acronym, name in unique_pairs:
if acronym in acronym_to_id:
structure_hierarchy.append(acronym_to_id[acronym])
elif name in name_to_id:
structure_hierarchy.append(name_to_id[name])

Check warning on line 134 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L130-L134

Added lines #L130 - L134 were not covered by tests

structure_hierarchy = [ROOT_ID] + structure_hierarchy

Check warning on line 136 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L136

Added line #L136 was not covered by tests

result = [

Check warning on line 138 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L138

Added line #L138 was not covered by tests
structure_hierarchy[: i + 1]
for i in range(len(structure_hierarchy))
]

for a in result:
structure_template = {

Check warning on line 144 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L143-L144

Added lines #L143 - L144 were not covered by tests
"acronym": acronyms[ids.index(a[-1])],
"id": a[-1],
"name": names[ids.index(a[-1])],
"structure_id_path": a,
"rgb_triplet": [random.randint(0, 255) for _ in range(3)],
}

hierarchy.append(structure_template)

Check warning on line 152 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L152

Added line #L152 was not covered by tests

hierarchy = list(

Check warning on line 154 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L154

Added line #L154 was not covered by tests
{tuple(d["structure_id_path"]): d for d in hierarchy}.values()
)

# use tifffile to read annotated file
annotated_volume = tifffile.imread(annotations_file)
reference_volume = tifffile.imread(reference_file)

Check warning on line 160 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L159-L160

Added lines #L159 - L160 were not covered by tests

print(f"Saving atlas data at {atlas_path}")

Check warning on line 162 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L162

Added line #L162 was not covered by tests

tree = get_structures_tree(hierarchy)
print(

Check warning on line 165 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L164-L165

Added lines #L164 - L165 were not covered by tests
f"Number of brain regions: {tree.size()}, "
f"max tree depth: {tree.depth()}"
)
labels = np.unique(annotated_volume).astype(np.int32)
for key, node in tree.nodes.items():
if key in labels:
is_label = True

Check warning on line 172 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L169-L172

Added lines #L169 - L172 were not covered by tests
else:
is_label = False
node.data = Region(is_label)

Check warning on line 175 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L174-L175

Added lines #L174 - L175 were not covered by tests

# Mesh creation
closing_n_iters = 2
decimate_fraction = 0.2
smooth = False # smooth meshes after creation
start = time.time()

Check warning on line 181 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L178-L181

Added lines #L178 - L181 were not covered by tests

for node in track(

Check warning on line 183 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L183

Added line #L183 was not covered by tests
tree.nodes.values(),
total=tree.size(),
description="Creating meshes",
):
create_region_mesh(

Check warning on line 188 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L188

Added line #L188 was not covered by tests
(
meshes_dir_path,
node,
tree,
labels,
annotated_volume,
ROOT_ID,
closing_n_iters,
decimate_fraction,
smooth,
)
)
print(

Check warning on line 201 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L201

Added line #L201 was not covered by tests
"Finished mesh extraction in: ",
round((time.time() - start) / 60, 2),
" minutes",
)

# Create meshes dict & hierarchy to match
hierarchy_with_mesh = []
meshes_dict = dict()
structs_with_mesh = []
for s in hierarchy:

Check warning on line 211 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L208-L211

Added lines #L208 - L211 were not covered by tests
# Check if a mesh was created
mesh_path = meshes_dir_path / f'{s["id"]}.obj'
if not mesh_path.exists():
print(f"No mesh file exists for: {s}, ignoring it")
continue

Check warning on line 216 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L213-L216

Added lines #L213 - L216 were not covered by tests
else:
# Check that the mesh actually exists (i.e. not empty)
if mesh_path.stat().st_size < 512:
print(f"obj file for {s} is too small, ignoring it.")
continue

Check warning on line 221 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L219-L221

Added lines #L219 - L221 were not covered by tests

structs_with_mesh.append(s)
meshes_dict[s["id"]] = mesh_path

Check warning on line 224 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L223-L224

Added lines #L223 - L224 were not covered by tests

hierarchy_with_mesh.append(s)

Check warning on line 226 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L226

Added line #L226 was not covered by tests

print(

Check warning on line 228 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L228

Added line #L228 was not covered by tests
f"In the end, {len(structs_with_mesh)} structures with mesh are kept"
)

for item in hierarchy_with_mesh:
item["id"] = int(item["id"])
item["structure_id_path"] = [int(i) for i in item["structure_id_path"]]

Check warning on line 234 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L232-L234

Added lines #L232 - L234 were not covered by tests

output_filename = wrapup_atlas_from_data(

Check warning on line 236 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L236

Added line #L236 was not covered by tests
atlas_name=ATLAS_NAME,
atlas_minor_version=__version__,
citation=CITATION,
atlas_link=ATLAS_LINK,
species=SPECIES,
orientation=ORIENTATION,
root_id=ROOT_ID,
reference_stack=reference_volume,
annotation_stack=annotated_volume,
structures_list=hierarchy_with_mesh,
working_dir=working_dir,
hemispheres_stack=None,
cleanup_files=False,
compress=True,
atlas_packager=ATLAS_PACKAGER,
additional_metadata=ADDITIONAL_METADATA,
resolution=(25, 25, 25),
meshes_dict=meshes_dict,
scale_meshes=True,
)

return output_filename

Check warning on line 258 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L258

Added line #L258 was not covered by tests


if __name__ == "__main__":
home = str(Path.home())
bg_root_dir = Path.home() / "brainglobe_workingdir"
bg_root_dir.mkdir(exist_ok=True, parents=True)

Check warning on line 264 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L261-L264

Added lines #L261 - L264 were not covered by tests

create_atlas(bg_root_dir)

Check warning on line 266 in brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/praire_vole.py#L266

Added line #L266 was not covered by tests
Loading