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

Integrating atlas validation in wrapup.py #445

Merged
merged 16 commits into from
Feb 11, 2025
Merged
Show file tree
Hide file tree
Changes from 9 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
64 changes: 48 additions & 16 deletions brainglobe_atlasapi/atlas_generation/validate_atlases.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,25 @@
from brainglobe_atlasapi.update_atlases import update_atlas


def validate_atlas_files(atlas: BrainGlobeAtlas):
"""Checks if basic files exist in the atlas folder"""
def validate_atlas_files(
atlas: BrainGlobeAtlas, custom_atlas_path: Path = None
):
"""
Checks if basic files exist in the atlas folder

custom_atlas_path is used when the function is called as part of
the wrapup function in the atlas packaging script. The expected
input is working_dir
"""

if custom_atlas_path is None:
atlas_path = (
Path(get_brainglobe_dir()) / f"{atlas.atlas_name}_v"
f"{get_local_atlas_version(atlas.atlas_name)}"
)
else:
atlas_path = custom_atlas_path

Check warning on line 36 in brainglobe_atlasapi/atlas_generation/validate_atlases.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/validate_atlases.py#L36

Added line #L36 was not covered by tests

atlas_path = (
Path(get_brainglobe_dir())
/ f"{atlas.atlas_name}_v{get_local_atlas_version(atlas.atlas_name)}"
)
assert atlas_path.is_dir(), f"Atlas path {atlas_path} not found"
expected_files = [
"annotation.tiff",
Expand Down Expand Up @@ -143,17 +155,27 @@
return True


def catch_missing_mesh_files(atlas: BrainGlobeAtlas):
def catch_missing_mesh_files(
atlas: BrainGlobeAtlas, custom_atlas_path: Path = None
):
"""
Checks if all the structures in the atlas have a corresponding mesh file

custom_atlas_path is used when the function is called as part of
the wrapup function in the atlas packaging script. The expected
input is working_dir
"""

ids_from_bg_atlas_api = list(atlas.structures.keys())

atlas_path = (
Path(get_brainglobe_dir())
/ f"{atlas.atlas_name}_v{get_local_atlas_version(atlas.atlas_name)}"
)
if custom_atlas_path is None:
atlas_path = (
Path(get_brainglobe_dir()) / f"{atlas.atlas_name}_v"
f"{get_local_atlas_version(atlas.atlas_name)}"
)
else:
atlas_path = custom_atlas_path

Check warning on line 177 in brainglobe_atlasapi/atlas_generation/validate_atlases.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/validate_atlases.py#L177

Added line #L177 was not covered by tests

obj_path = Path(atlas_path / "meshes")

ids_from_mesh_files = [
Expand All @@ -174,18 +196,28 @@
)


def catch_missing_structures(atlas: BrainGlobeAtlas):
def catch_missing_structures(
atlas: BrainGlobeAtlas, custom_atlas_path: Path = None
):
"""
Checks if all the mesh files in the atlas folder
are listed as a structure in the atlas.

custom_atlas_path is used when the function is called as part of
the wrapup function in the atlas packaging script. The expected
input is working_dir
"""

ids_from_bg_atlas_api = list(atlas.structures.keys())

atlas_path = (
Path(get_brainglobe_dir())
/ f"{atlas.atlas_name}_v{get_local_atlas_version(atlas.atlas_name)}"
)
if custom_atlas_path is None:
atlas_path = (
Path(get_brainglobe_dir()) / f"{atlas.atlas_name}_v"
f"{get_local_atlas_version(atlas.atlas_name)}"
)
else:
atlas_path = custom_atlas_path

Check warning on line 219 in brainglobe_atlasapi/atlas_generation/validate_atlases.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/validate_atlases.py#L219

Added line #L219 was not covered by tests

obj_path = Path(atlas_path / "meshes")

ids_from_mesh_files = [
Expand Down
80 changes: 79 additions & 1 deletion brainglobe_atlasapi/atlas_generation/wrapup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import tifffile

import brainglobe_atlasapi.atlas_generation
from brainglobe_atlasapi import descriptors
from brainglobe_atlasapi import BrainGlobeAtlas, descriptors

Check warning on line 11 in brainglobe_atlasapi/atlas_generation/wrapup.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/wrapup.py#L11

Added line #L11 was not covered by tests
from brainglobe_atlasapi.atlas_generation.metadata_utils import (
create_metadata_files,
generate_metadata_dict,
Expand All @@ -22,6 +22,16 @@
from brainglobe_atlasapi.atlas_generation.structures import (
check_struct_consistency,
)
from brainglobe_atlasapi.atlas_generation.validate_atlases import (

Check warning on line 25 in brainglobe_atlasapi/atlas_generation/wrapup.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/wrapup.py#L25

Added line #L25 was not covered by tests
catch_missing_mesh_files,
catch_missing_structures,
open_for_visual_check,
validate_additional_references,
validate_atlas_files,
validate_checksum,
validate_image_dimensions,
validate_mesh_matches_image_extents,
)
from brainglobe_atlasapi.utils import atlas_name_from_repr

# This should be changed every time we make changes in the atlas
Expand Down Expand Up @@ -129,6 +139,7 @@
atlas_dir_name = atlas_name_from_repr(
atlas_name, resolution[0], ATLAS_VERSION, atlas_minor_version
)

dest_dir = Path(working_dir) / atlas_dir_name

# exist_ok would be more permissive but error-prone here as there might
Expand Down Expand Up @@ -231,6 +242,72 @@
additional_metadata=additional_metadata,
)

atlas_name_for_validation = atlas_name_from_repr(atlas_name, resolution[0])

Check warning on line 245 in brainglobe_atlasapi/atlas_generation/wrapup.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/wrapup.py#L245

Added line #L245 was not covered by tests

# creating BrainGlobe object from local folder (working_dir)
atlas_to_validate = BrainGlobeAtlas(

Check warning on line 248 in brainglobe_atlasapi/atlas_generation/wrapup.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/wrapup.py#L248

Added line #L248 was not covered by tests
atlas_name=atlas_name_for_validation,
brainglobe_dir=working_dir,
check_latest=False,
)

# Run validation functions
print(f"Running atlas validation on {atlas_dir_name}")

Check warning on line 255 in brainglobe_atlasapi/atlas_generation/wrapup.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/wrapup.py#L255

Added line #L255 was not covered by tests

validation_results = {}

Check warning on line 257 in brainglobe_atlasapi/atlas_generation/wrapup.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/wrapup.py#L257

Added line #L257 was not covered by tests

functions = [

Check warning on line 259 in brainglobe_atlasapi/atlas_generation/wrapup.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/wrapup.py#L259

Added line #L259 was not covered by tests
(validate_atlas_files, atlas_to_validate, atlas_to_validate.root_dir),
(
catch_missing_structures,
atlas_to_validate,
atlas_to_validate.root_dir,
),
(
catch_missing_mesh_files,
atlas_to_validate,
atlas_to_validate.root_dir,
),
(validate_mesh_matches_image_extents, atlas_to_validate),
(open_for_visual_check, atlas_to_validate),
(validate_checksum, atlas_to_validate),
(validate_image_dimensions, atlas_to_validate),
(validate_additional_references, atlas_to_validate),
]

for func, *args in functions:
try:
func(*args)
validation_results[func.__name__] = "Pass"
except AssertionError as e:
validation_results[func.__name__] = f"Fail: {str(e)}"

Check warning on line 283 in brainglobe_atlasapi/atlas_generation/wrapup.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/wrapup.py#L278-L283

Added lines #L278 - L283 were not covered by tests

def _check_validations(validation_results):

Check warning on line 285 in brainglobe_atlasapi/atlas_generation/wrapup.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/wrapup.py#L285

Added line #L285 was not covered by tests
# Helper function to check if all validations passed
all_passed = all(

Check warning on line 287 in brainglobe_atlasapi/atlas_generation/wrapup.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/wrapup.py#L287

Added line #L287 was not covered by tests
result == "Pass" for result in validation_results.values()
)

if all_passed:
print("This atlas is valid")

Check warning on line 292 in brainglobe_atlasapi/atlas_generation/wrapup.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/wrapup.py#L291-L292

Added lines #L291 - L292 were not covered by tests
else:
failed_functions = [

Check warning on line 294 in brainglobe_atlasapi/atlas_generation/wrapup.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/wrapup.py#L294

Added line #L294 was not covered by tests
func
for func, result in validation_results.items()
if result != "Pass"
]
error_messages = [

Check warning on line 299 in brainglobe_atlasapi/atlas_generation/wrapup.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/wrapup.py#L299

Added line #L299 was not covered by tests
result.split(": ")[1]
for result in validation_results.values()
if result != "Pass"
]

print("These validation functions have failed:")
for func, error in zip(failed_functions, error_messages):
print(f"- {func}: {error}")

Check warning on line 307 in brainglobe_atlasapi/atlas_generation/wrapup.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/wrapup.py#L305-L307

Added lines #L305 - L307 were not covered by tests

_check_validations(validation_results)

Check warning on line 309 in brainglobe_atlasapi/atlas_generation/wrapup.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/wrapup.py#L309

Added line #L309 was not covered by tests

# Compress if required:
if compress:
output_filename = dest_dir.parent / f"{dest_dir.name}.tar.gz"
Expand All @@ -240,6 +317,7 @@

# Cleanup if required:
if cleanup_files:
print(f"Cleaning up atlas data at: {dest_dir}")

Check warning on line 320 in brainglobe_atlasapi/atlas_generation/wrapup.py

View check run for this annotation

Codecov / codecov/patch

brainglobe_atlasapi/atlas_generation/wrapup.py#L320

Added line #L320 was not covered by tests
# Clean temporary directory and remove it:
shutil.rmtree(dest_dir)

Expand Down
Loading