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

first draft of symmetrical 25um blackcap atlas #314

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
80 changes: 80 additions & 0 deletions brainglobe_atlasapi/atlas_generation/annotation_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
"""Helper functions to read annotation metadata from common formats."""

from pathlib import Path

Check warning on line 3 in brainglobe_atlasapi/atlas_generation/annotation_utils.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/annotation_utils.py#L3

Added line #L3 was not covered by tests


def split_label_text(name: str) -> str:
if name.endswith(")"):
name, acronym = name.split("(")
name = name[:-1] # ignore trailing space
acronym = acronym[:-1] # ignore trailing )

Check warning on line 10 in brainglobe_atlasapi/atlas_generation/annotation_utils.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/annotation_utils.py#L6-L10

Added lines #L6 - L10 were not covered by tests
else:
acronym = name[0]
return name, acronym

Check warning on line 13 in brainglobe_atlasapi/atlas_generation/annotation_utils.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/annotation_utils.py#L12-L13

Added lines #L12 - L13 were not covered by tests


def read_itk_labels(path: Path) -> dict:
labels = []
with open(path) as labels_file:
for line in labels_file:
if not line.startswith("#"):
raw_values = line.split(maxsplit=7)
id = int(raw_values[0])
rgb = tuple((int(r) for r in raw_values[1:4]))
if raw_values[7][-1] == "\n":
raw_values[7] = raw_values[7][:-1]
label_text = raw_values[7][1:-1]
if label_text != "Clear Label":
name, acronym = split_label_text(label_text)
labels.append(

Check warning on line 29 in brainglobe_atlasapi/atlas_generation/annotation_utils.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/annotation_utils.py#L16-L29

Added lines #L16 - L29 were not covered by tests
{
"id": id,
"name": name,
"rgb_triplet": rgb,
"acronym": acronym,
}
)
return labels

Check warning on line 37 in brainglobe_atlasapi/atlas_generation/annotation_utils.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/annotation_utils.py#L37

Added line #L37 was not covered by tests


ITK_SNAP_HEADER = """################################################

Check warning on line 40 in brainglobe_atlasapi/atlas_generation/annotation_utils.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/annotation_utils.py#L40

Added line #L40 was not covered by tests
# ITK-SnAP Label Description File
# File format:
# IDX -R- -G- -B- -A-- VIS MSH LABEL
# Fields:
# IDX: Zero-based index
# -R-: Red color component (0..255)
# -G-: Green color component (0..255)
# -B-: Blue color component (0..255)
# -A-: Label transparency (0.00 .. 1.00)
# VIS: Label visibility (0 or 1)
# IDX: Label mesh visibility (0 or 1)
# LABEL: Label description
################################################
"""

ITK_CLEAR_LABEL = '0 0 0 0 0 0 0 "Clear Label"\n'

Check warning on line 56 in brainglobe_atlasapi/atlas_generation/annotation_utils.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/annotation_utils.py#L56

Added line #L56 was not covered by tests


def write_itk_labels(path: Path, labels):
with open(path, "w") as labels_file:
labels_file.write(ITK_SNAP_HEADER)
labels_file.write(ITK_CLEAR_LABEL)
for label in labels:
labels_file.write(

Check warning on line 64 in brainglobe_atlasapi/atlas_generation/annotation_utils.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/annotation_utils.py#L59-L64

Added lines #L59 - L64 were not covered by tests
f"{label['id']} "
f"{label['rgb_triplet'][0]} "
f"{label['rgb_triplet'][1]} "
f"{label['rgb_triplet'][2]} 1.00 1 1 "
f"\"{label['name'] + ' (' + label['acronym']+')'}\"\n"
)


# TODO turn into test
if __name__ == "__main__":
path = Path.home() / "Downloads" / "corrected_LabelMainBrainAreas_SW.txt"
labels = read_itk_labels(path)
[print(label) for label in labels]
write_itk_labels(

Check warning on line 78 in brainglobe_atlasapi/atlas_generation/annotation_utils.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/annotation_utils.py#L74-L78

Added lines #L74 - L78 were not covered by tests
Path.home() / "Downloads" / "test-writing.txt", labels=labels
)
221 changes: 221 additions & 0 deletions brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
__version__ = "0"

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

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L1

Added line #L1 was not covered by tests

import csv
import glob as glob
import os
import time
from pathlib import Path

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

View check run for this annotation

Codecov / codecov/patch

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

Added lines #L3 - L7 were not covered by tests

import numpy as np
from brainglobe_utils.IO.image import load_nii
from rich.progress import track

Check warning on line 11 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L9-L11

Added lines #L9 - L11 were not covered by tests

from brainglobe_atlasapi.atlas_generation.annotation_utils import (

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

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L13

Added line #L13 was not covered by tests
read_itk_labels,
)
from brainglobe_atlasapi.atlas_generation.mesh_utils import (

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

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L16

Added line #L16 was 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/blackcap.py

View check run for this annotation

Codecov / codecov/patch

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

Added lines #L20 - L21 were not covered by tests


def create_atlas(working_dir, resolution):
ATLAS_NAME = "oldenburg_blackcap"
SPECIES = "Sylvia atricapilla"
ATLAS_LINK = "https://uol.de/en/ibu/animal-navigation"
CITATION = "unpublished"
ATLAS_FILE_URL = "https://uol.de/en/ibu/animal-navigation" # noqa
ORIENTATION = "asr"
ROOT_ID = 999
ATLAS_PACKAGER = "BrainGlobe Developers, [email protected]"
ADDITIONAL_METADATA = {}

Check warning on line 33 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L24-L33

Added lines #L24 - L33 were not covered by tests

# setup folder for downloading

atlas_path = Path(

Check warning on line 37 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L37

Added line #L37 was not covered by tests
"/media/ceph/margrie/sweiler/AnalyzedData/"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this atlas fail our "normal" requirement that all data is available online, and the script should run without access to any specific filesystem?

Should we create a blackcap repo on GIN and upload these files?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Bird_brain_project/black_cap/DH_checked/"
)

structures_file = atlas_path / "labels051224.txt"
annotations_file = atlas_path / "annotations_051224.nii.gz"
reference_file = atlas_path / "reference_res-25_hemi-right_IMAGE.nii.gz"
meshes_dir_path = Path.home() / "blackcap-meshes"

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

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L42-L45

Added lines #L42 - L45 were not covered by tests

try:
os.mkdir(meshes_dir_path)
except FileExistsError:
"mesh folder already exists"

Check warning on line 50 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L47-L50

Added lines #L47 - L50 were not covered by tests

print("Reading structures files")
hierarchy_path = atlas_path / "combined_structures.csv"
structure_to_parent_map = {}
with open(hierarchy_path, mode="r") as file:
reader = csv.reader(file)
next(reader) # Skip the header
for row in reader:
structure_to_parent_map[int(row[1])] = [

Check warning on line 59 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L52-L59

Added lines #L52 - L59 were not covered by tests
int(parent) for parent in row[2].split(",")
]

structure_data_list = read_itk_labels(structures_file)
for structure in structure_data_list:
structure_id = structure["id"]
structure["structure_id_path"] = structure_to_parent_map[structure_id]

Check warning on line 66 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L63-L66

Added lines #L63 - L66 were not covered by tests

# append root and pallium structures, which don't have their own voxels
# and are therefore not in itk file
structure_data_list.append(

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

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L70

Added line #L70 was not covered by tests
{
"id": 1,
"name": "Pallium",
"acronym": "P",
"structure_id_path": [999, 1],
"rgb_triplet": [0, 200, 100],
}
)
structure_data_list.append(

Check warning on line 79 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L79

Added line #L79 was not covered by tests
{
"id": 999,
"name": "root",
"acronym": "root",
"structure_id_path": [999],
"rgb_triplet": [255, 255, 255],
}
)

tree = get_structures_tree(structure_data_list)
print(

Check warning on line 90 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L89-L90

Added lines #L89 - L90 were not covered by tests
f"Number of brain regions: {tree.size()}, "
f"max tree depth: {tree.depth()}"
)
print(tree)
print(f"Saving atlas data at {atlas_path}")

Check warning on line 95 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L94-L95

Added lines #L94 - L95 were not covered by tests

# use tifffile to read annotated file
annotated_volume = load_nii(annotations_file, as_array=True).astype(

Check warning on line 98 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L98

Added line #L98 was not covered by tests
np.uint16
)
# Append a mirror image of the reference volume along axis 2
mirrored_volume = np.flip(annotated_volume, axis=2)
annotated_volume = np.concatenate(

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

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L102-L103

Added lines #L102 - L103 were not covered by tests
(annotated_volume, mirrored_volume), axis=2
)

# rescale reference volume into int16 range
reference_volume = load_nii(reference_file, as_array=True)
dmin = np.min(reference_volume)
dmax = np.max(reference_volume)
drange = dmax - dmin
dscale = (2**16 - 1) / drange
reference_volume = (reference_volume - dmin) * dscale
reference_volume = reference_volume.astype(np.uint16)

Check warning on line 114 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L108-L114

Added lines #L108 - L114 were not covered by tests
# Append a mirror image of the reference volume along axis 2
mirrored_volume = np.flip(reference_volume, axis=2)
reference_volume = np.concatenate(

Check warning on line 117 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L116-L117

Added lines #L116 - L117 were not covered by tests
(reference_volume, mirrored_volume), axis=2
)

has_label = annotated_volume > 0
reference_volume *= has_label

Check warning on line 122 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L121-L122

Added lines #L121 - L122 were not covered by tests

# generate binary mask for mesh creation
labels = np.unique(annotated_volume).astype(np.int_)
for key, node in tree.nodes.items():
if (

Check warning on line 127 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L125-L127

Added lines #L125 - L127 were not covered by tests
key in labels or key == 1
): # Pallium == 1 needs mesh but has no own voxels
is_label = True

Check warning on line 130 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L130

Added line #L130 was not covered by tests
else:
is_label = False

Check warning on line 132 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L132

Added line #L132 was not covered by tests

node.data = Region(is_label)

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

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L134

Added line #L134 was not covered by tests

# mesh creation
closing_n_iters = 1
decimate_fraction = 0.6 # higher = more triangles
smooth = False

Check warning on line 139 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L137-L139

Added lines #L137 - L139 were not covered by tests

start = time.time()

Check warning on line 141 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L141

Added line #L141 was not covered by tests

for node in track(

Check warning on line 143 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L143

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

Check warning on line 148 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L148

Added line #L148 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 162 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L162

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

# create meshes dict
meshes_dict = dict()
structures_with_mesh = []
for s in structure_data_list:

Check warning on line 171 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L169-L171

Added lines #L169 - L171 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 176 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L173-L176

Added lines #L173 - L176 were not covered by tests
else:
# check that the mesh actually exists and isn't empty
if mesh_path.stat().st_size < 512:
print(f"obj file for {s} is too small, ignoring it.")
continue
structures_with_mesh.append(s)
meshes_dict[s["id"]] = mesh_path

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

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L179-L183

Added lines #L179 - L183 were not covered by tests

print(

Check warning on line 185 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L185

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

output_filename = wrapup_atlas_from_data(

Check warning on line 190 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L190

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

return output_filename

Check warning on line 212 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L212

Added line #L212 was not covered by tests


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

Check warning on line 219 in brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L215-L219

Added lines #L215 - L219 were not covered by tests

create_atlas(bg_root_dir, res)

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

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/atlas_scripts/blackcap.py#L221

Added line #L221 was not covered by tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""One-off script to reproduce how we combined the first version of
the annotations provided by the bird anatomists"""

import csv
from pathlib import Path

import numpy as np
from brainglobe_utils.IO.image import load_nii, save_any

from brainglobe_atlasapi.atlas_generation.annotation_utils import (
read_itk_labels,
write_itk_labels,
)

if __name__ == "__main__":
# setup paths
annotations_root = Path(
"/media/ceph-neuroinformatics/neuroinformatics/atlas-forge/BlackCap"
/ "templates/template_sym_res-25um_n-18_average-trimean/for_atlas"
/ "annotations-right-hemisphere/"
)
main_annotation_path = (
annotations_root / "corrected_AnnotationsMainBrainAreas_SW.nii.gz"
)
small_annotation_path = annotations_root / "corrected_smallareas_SW.nii.gz"
main_labels_path = (
annotations_root / "corrected_LabelMainBrainAreas_SW.txt"
)
small_labels_path = annotations_root / "corrected_smallareas_SW.txt"
small_to_main_csv = annotations_root / "hierarchy_annotat1_annotat2.csv"

# combine annotation images
main_annotation_image = load_nii(main_annotation_path, as_array=True)
small_annotation_image = load_nii(small_annotation_path, as_array=True)
small_annotation_image *= (
10 # avoid label clashes, there are 6 main labels
)
small_annotation_image = small_annotation_image.astype(np.uint8)
combined_annotation_image = main_annotation_image.copy()

small_to_main_map = {}
with open(small_to_main_csv, mode="r") as file:
reader = csv.reader(file)
next(reader) # Skip the header
for row in reader:
print(row)
if row[3]:
small_to_main_map[10 * int(row[3])] = int(row[1])
for small, main in small_to_main_map.items():
is_main_value = main_annotation_image == main
is_small_value = small_annotation_image == small
combined_indices = is_main_value * is_small_value
combined_annotation_image[combined_indices] = small
save_any(
combined_annotation_image,
annotations_root / "combined_annotations.nii.gz",
)

# combine label data
main_annotation_labels = read_itk_labels(main_labels_path)
small_annotation_labels = read_itk_labels(small_labels_path)
for label in small_annotation_labels:
label["id"] = int(10 * label["id"])
combined_labels = main_annotation_labels + small_annotation_labels
write_itk_labels(
annotations_root / "combined_label_descriptions.txt", combined_labels
)
Loading
Loading