spaces
lacuna.core.spaces
¶
Coordinate space representation and detection for neuroimaging data.
This module defines the core coordinate space abstractions and provides automatic detection from filenames and image headers.
CoordinateSpace
dataclass
¶
Immutable representation of a neuroimaging coordinate space.
Attributes:
| Name | Type | Description |
|---|---|---|
identifier |
str
|
Space identifier (e.g., 'MNI152NLin6Asym'). |
resolution |
float
|
Voxel resolution in mm (0.5, 1, or 2). |
reference_affine |
ndarray
|
4x4 affine transformation matrix. |
Source code in src/lacuna/core/spaces.py
__post_init__()
¶
Validate space identifier and resolution.
Source code in src/lacuna/core/spaces.py
SpaceDetectionError
¶
Bases: LacunaError
Raised when coordinate space cannot be detected from file.
Source code in src/lacuna/core/exceptions.py
SpaceMismatchError
¶
Bases: ValidationError
Raised when declared space doesn't match detected space.
Source code in src/lacuna/core/exceptions.py
SpaceValidator
¶
Validator for spatial consistency between datasets.
Source code in src/lacuna/core/spaces.py
523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 | |
can_transform(source_space, target_space)
¶
Check if transformation is possible between spaces.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source_space
|
CoordinateSpace
|
Source coordinate space. |
required |
target_space
|
CoordinateSpace
|
Target coordinate space. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if transformation is supported. |
Source code in src/lacuna/core/spaces.py
detect_mismatch(space1, space2)
¶
Check if two spaces are different.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
space1
|
CoordinateSpace
|
First space. |
required |
space2
|
CoordinateSpace
|
Second space. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if spaces differ, False if same. |
Source code in src/lacuna/core/spaces.py
validate_space_declaration(space, img, tolerance=0.001)
¶
Validate that image matches declared space.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
space
|
CoordinateSpace
|
Declared coordinate space. |
required |
img
|
Nifti1Image
|
Image to validate. |
required |
tolerance
|
float
|
Affine matching tolerance. |
0.001
|
Returns:
| Type | Description |
|---|---|
bool
|
True if valid, False otherwise. |
Source code in src/lacuna/core/spaces.py
SpatialMetadata
dataclass
¶
Container for spatial metadata attached to imaging data.
Attributes:
| Name | Type | Description |
|---|---|---|
space |
CoordinateSpace
|
CoordinateSpace instance. |
is_validated |
bool
|
Whether spatial consistency has been validated. |
validation_tolerance |
float
|
Tolerance used for affine validation (default 1e-3). |
Source code in src/lacuna/core/spaces.py
validate_consistency(img)
¶
Validate that image affine matches the declared space.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img
|
Nifti1Image
|
Nibabel image to validate. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if affine matches within tolerance, False otherwise. |
Source code in src/lacuna/core/spaces.py
TransformNotAvailableError
¶
Bases: LacunaError
Raised when spatial transform is not available.
Source code in src/lacuna/core/exceptions.py
detect_space_from_filename(filepath)
¶
Extract space identifier and resolution from filename.
Follows BIDS naming conventions (space- and res- entities).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filepath
|
str or Path
|
Path to neuroimaging file. |
required |
Returns:
| Type | Description |
|---|---|
tuple of (str, int) or None
|
Tuple of (space_identifier, resolution_mm) if detected, None otherwise. |
Examples:
>>> detect_space_from_filename("sub-01_space-MNI152NLin6Asym_res-2_mask.nii.gz")
('MNI152NLin6Asym', 2)
Source code in src/lacuna/core/spaces.py
detect_space_from_header(img, tolerance=0.001)
¶
Detect coordinate space from image affine matrix.
Compares the image affine against known reference affines. Handles radiological-convention images (negative strides) by canonicalizing to RAS+ orientation before comparison.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img
|
Nifti1Image
|
Nibabel image. |
required |
tolerance
|
float
|
Maximum difference for affine matching. |
0.001
|
Returns:
| Type | Description |
|---|---|
tuple of (str, float) or None
|
Tuple of (space_identifier, resolution) if matched, None otherwise. |
Examples:
Source code in src/lacuna/core/spaces.py
get_image_space(img, filepath=None, declared_space=None, declared_resolution=None, require_match=True)
¶
Unified space detection with validation.
Attempts detection from filename first, then header. If declared_space is provided, validates against detected space.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img
|
Nifti1Image
|
Nibabel image. |
required |
filepath
|
Path or None
|
Optional path for filename-based detection. |
None
|
declared_space
|
str or None
|
Optional explicit space declaration. |
None
|
declared_resolution
|
float or None
|
Optional explicit resolution declaration. |
None
|
require_match
|
bool
|
If True, raises error on mismatch. |
True
|
Returns:
| Type | Description |
|---|---|
CoordinateSpace
|
CoordinateSpace instance. |
Raises:
| Type | Description |
|---|---|
SpaceDetectionError
|
If space cannot be detected. |
SpaceMismatchError
|
If declared space doesn't match detected. |
Examples:
>>> img = nib.load("sub-01_space-MNI152NLin6Asym_res-2.nii.gz")
>>> space = get_image_space(img, filepath=Path("sub-01_space-MNI152NLin6Asym_res-2.nii.gz"))
>>> space.identifier
'MNI152NLin6Asym'
Source code in src/lacuna/core/spaces.py
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 | |
query_supported_spaces()
¶
Query all supported coordinate space identifiers.
Returns:
| Type | Description |
|---|---|
list[str]
|
Sorted list of space identifiers. |
Examples:
Source code in src/lacuna/core/spaces.py
spaces_are_equivalent(space1, space2)
¶
Check if two space identifiers refer to the same coordinate space.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
space1
|
str
|
First space identifier. |
required |
space2
|
str
|
Second space identifier. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if spaces are the same, False otherwise. |
Examples:
>>> spaces_are_equivalent("MNI152NLin6Asym", "MNI152NLin6Asym")
True
>>> spaces_are_equivalent("MNI152NLin2009bAsym", "MNI152NLin2009cAsym")
False
Source code in src/lacuna/core/spaces.py
validate_space_and_resolution(space, resolution, strict=True)
¶
Validate space identifier and resolution are consistent.
Ensures that if a space is specified, resolution is also provided, and both are valid values.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
space
|
str or None
|
Space identifier (can be None for native/unknown space). |
required |
resolution
|
float or None
|
Resolution in mm (can be None if space is None). |
required |
strict
|
bool
|
Whether to require resolution when space is provided. |
True
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If validation fails. |
Examples:
>>> validate_space_and_resolution("MNI152NLin6Asym", 2.0)
# No error
>>> validate_space_and_resolution("MNI152NLin6Asym", None)
ValueError: Resolution is required when space is specified
>>> validate_space_and_resolution(None, None)
# No error - both None is acceptable
Source code in src/lacuna/core/spaces.py
validate_space_compatibility(actual_space, expected_space, context='operation', suggest_transform=False)
¶
Validate that actual space is compatible with expected space.
Raises ValueError if spaces are incompatible (not equivalent). Handles space aliases automatically.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
actual_space
|
str
|
The actual space of the data. |
required |
expected_space
|
str
|
The expected/required space. |
required |
context
|
str
|
Description of operation for error messages. |
'operation'
|
suggest_transform
|
bool
|
Whether to suggest transformation in error message. |
False
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If spaces are incompatible. |
Examples:
>>> validate_space_compatibility("MNI152NLin6Asym", "MNI152NLin6Asym", "test")
# No error - spaces match
>>> validate_space_compatibility("native", "MNI152NLin6Asym", "test")
ValueError: Space mismatch in test: got 'native', expected 'MNI152NLin6Asym'