Skip to content

Commit

Permalink
WIP: autoformatting
Browse files Browse the repository at this point in the history
  • Loading branch information
tbirdso committed Nov 7, 2023
1 parent 2f760bf commit 974e198
Show file tree
Hide file tree
Showing 15 changed files with 576 additions and 439 deletions.
73 changes: 48 additions & 25 deletions src/itk_dreg/base/image_block_interface.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#!/usr/bin/env python3

import numpy as np
import chunk
from dataclasses import dataclass
from enum import IntEnum
from typing import Optional, List
Expand Down Expand Up @@ -59,14 +58,20 @@ class BlockInfo:
@property
def ndim(self) -> int:
if len(self.chunk_index) != len(self.array_slice):
raise ValueError('Observed mismatch between chunk and slice index dimensions')
raise ValueError(
"Observed mismatch between chunk and slice index dimensions"
)
return len(self.chunk_index)

@property
def shape(self) -> List[int]:
if any([slice_val.step and slice_val.step != 1 for slice_val in self.array_slice]):
if any(
[slice_val.step and slice_val.step != 1 for slice_val in self.array_slice]
):
print()
raise ValueError('Illegal step size in `BlockInfo`, expected step size of 1')
raise ValueError(
"Illegal step size in `BlockInfo`, expected step size of 1"
)
return [slice_val.stop - slice_val.start for slice_val in self.array_slice]


Expand Down Expand Up @@ -94,12 +99,12 @@ class BlockPairRegistrationResult:
"""Encapsulate result of fixed-to-moving registration over one block pair."""

def __init__(
self,
status: BlockRegStatus,
transform: Optional[TransformType]=None,
transform_domain: Optional[ImageType]=None,
inv_transform: Optional[TransformType]=None,
inv_transform_domain: Optional[ImageType]=None
self,
status: BlockRegStatus,
transform: Optional[TransformType] = None,
transform_domain: Optional[ImageType] = None,
inv_transform: Optional[TransformType] = None,
inv_transform_domain: Optional[ImageType] = None,
):
"""
:param status: Status code indicating registration success or failure.
Expand All @@ -120,22 +125,39 @@ def __init__(
`inv_transform_domain` must be available if and only if `inv_transform` is available.
"""
if status == BlockRegStatus.SUCCESS and not transform:
raise ValueError(f'Pairwise registration indicated success ({status})'
f' but no forward transform was provided')
raise ValueError(
f"Pairwise registration indicated success ({status})"
f" but no forward transform was provided"
)
if transform and not transform_domain:
raise ValueError(f'Pairwise registration returned incomplete forward transform:'
f' failed to provide forward transform domain')
raise ValueError(
"Pairwise registration returned incomplete forward transform:"
" failed to provide forward transform domain"
)
if transform_domain and itk.template(transform_domain)[0] != itk.Image:
raise TypeError(f'Received invalid transform domain type: {type(transform_domain)}')
if transform_domain and np.product(transform_domain.GetLargestPossibleRegion().GetSize()) == 0:
raise ValueError(f'Received invalid transform domain with size 0')
raise TypeError(
f"Received invalid transform domain type: {type(transform_domain)}"
)
if (
transform_domain
and np.product(transform_domain.GetLargestPossibleRegion().GetSize()) == 0
):
raise ValueError("Received invalid transform domain with size 0")
if inv_transform and not inv_transform_domain:
raise ValueError(f'Pairwise registration returned incomplete inverse transform:'
f' failed to provide inverse transform domain')
raise ValueError(
"Pairwise registration returned incomplete inverse transform:"
" failed to provide inverse transform domain"
)
if inv_transform_domain and itk.template(inv_transform_domain)[0] != itk.Image:
raise TypeError(f'Received invalid transform domain type: {type(transform_domain)}')
if inv_transform_domain and np.product(inv_transform_domain.GetLargestPossibleRegion().GetSize()) == 0:
raise ValueError(f'Received invalid transform domain with size 0')
raise TypeError(
f"Received invalid transform domain type: {type(transform_domain)}"
)
if (
inv_transform_domain
and np.product(inv_transform_domain.GetLargestPossibleRegion().GetSize())
== 0
):
raise ValueError("Received invalid transform domain with size 0")
self.status = status
self.transform = transform
self.transform_domain = transform_domain
Expand All @@ -150,13 +172,14 @@ class LocatedBlockResult:
information describing how the fixed subimage in registration
relates to the greater fixed image.
"""
result:BlockPairRegistrationResult

result: BlockPairRegistrationResult
"""
The result of pairwise subimage registration.
May include extended information for specific implementations.
"""

fixed_info:BlockInfo
fixed_info: BlockInfo
"""
Oriented representation of the fixed image block over which
pairwise registration was performed to produce the encapsulated
Expand Down
10 changes: 5 additions & 5 deletions src/itk_dreg/base/registration_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

import itk
from abc import ABC, abstractmethod
from typing import Optional, Iterable, Tuple
from typing import Iterable

from .image_block_interface import (
BlockPairRegistrationResult,
LocatedBlockResult,
RegistrationTransformResult,
BlockInfo
BlockInfo,
)
from .itk_typing import ImageType, ImageReaderType, ImageRegionType, TransformType
from .itk_typing import ImageType, ImageReaderType, TransformType

"""
Defines extensible components to extend with concrete implementations.
Expand Down Expand Up @@ -69,7 +69,7 @@ def __call__(
moving_subimage: ImageType,
initial_transform: TransformType,
block_info: BlockInfo,
**kwargs
**kwargs,
) -> BlockPairRegistrationResult:
"""
Run image-to-image pairwise registration.
Expand Down Expand Up @@ -115,7 +115,7 @@ def __call__(
block_results: Iterable[LocatedBlockResult],
fixed_reader_ctor: ConstructReaderMethod,
initial_transform: itk.Transform,
**kwargs
**kwargs,
) -> RegistrationTransformResult:
"""
:param block_results: An iterable collection of subimages in fixed space
Expand Down
35 changes: 16 additions & 19 deletions src/itk_dreg/block/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
# reversed (np.flip) from NumPy conventional access order.
#


def arr_to_continuous_index(index: Union[List, npt.ArrayLike]) -> itk.ContinuousIndex:
r"""
Convert Python array-like representation of a continuous index into
Expand All @@ -55,7 +56,7 @@ def arr_to_continuous_index(index: Union[List, npt.ArrayLike]) -> itk.Continuous
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ValueError: Expecting a sequence of int (or long)
```
:param arr: The list or array representing a continuous index.
The list or array must be a one dimensional collection of floating point scalar values.
:returns: An `itk.ContinuousIndex` object representing the index.
Expand All @@ -64,12 +65,13 @@ def arr_to_continuous_index(index: Union[List, npt.ArrayLike]) -> itk.Continuous
"""
index = np.array(index, dtype=np.float32)
if index.ndim != 1:
raise ValueError(f'Expected 1D input index but received {index}')
raise ValueError(f"Expected 1D input index but received {index}")
itk_index = itk.ContinuousIndex[itk.D, len(index)]()
for dim, val in enumerate(index):
itk_index.SetElement(dim, float(val))
return itk_index


def estimate_bounding_box(
physical_region: npt.ArrayLike, transform: itk.Transform
) -> npt.ArrayLike:
Expand Down Expand Up @@ -97,9 +99,7 @@ def estimate_bounding_box(
physical_region[:, 0], physical_region[:, 1], physical_region[:, 2]
)
):
pt = np.array(
transform.TransformPoint([float(val) for val in (i, j, k)])
)
pt = np.array(transform.TransformPoint([float(val) for val in (i, j, k)]))
arr[index, :] = pt
return np.array([np.min(arr, axis=0), np.max(arr, axis=0)])

Expand Down Expand Up @@ -127,8 +127,7 @@ def block_to_physical_size(
)

return np.abs(
ref_image.TransformIndexToPhysicalPoint(block_index)
- itk.origin(ref_image)
ref_image.TransformIndexToPhysicalPoint(block_index) - itk.origin(ref_image)
)


Expand All @@ -137,17 +136,17 @@ def physical_to_block_size(
) -> npt.ArrayLike:
"""Convert from physical size to corresponding voxel size"""
return np.abs(
ref_image.TransformPhysicalPointToIndex(
itk.origin(ref_image) + physical_size
)
ref_image.TransformPhysicalPointToIndex(itk.origin(ref_image) + physical_size)
)


def block_to_physical_region(
block_region: npt.ArrayLike,
ref_image: itk.Image,
transform: itk.Transform = None,
estimate_bounding_box_method: Callable[[npt.ArrayLike, itk.Transform], npt.ArrayLike] = estimate_bounding_box,
estimate_bounding_box_method: Callable[
[npt.ArrayLike, itk.Transform], npt.ArrayLike
] = estimate_bounding_box,
) -> npt.ArrayLike:
"""Convert from voxel region to corresponding physical space"""
# block region is a 2x3 matrix where row 0 is the lower bound and row 1 is the upper bound
Expand All @@ -160,11 +159,11 @@ def block_to_physical_region(

adjusted_block_region = block_region - HALF_VOXEL_STEP

index_to_physical_func = (
lambda row: ref_image.TransformContinuousIndexToPhysicalPoint(
def index_to_physical_func(row: npt.ArrayLike) -> npt.ArrayLike:
return ref_image.TransformContinuousIndexToPhysicalPoint(
arr_to_continuous_index(row)
)
)

physical_region = np.apply_along_axis(
index_to_physical_func, 1, adjusted_block_region
)
Expand All @@ -190,14 +189,12 @@ def physical_to_block_region(
# block region is a 2x3 matrix where row 0 is the lower bound and row 1 is the upper bound
assert physical_region.ndim == 2 and physical_region.shape == (2, 3)

physical_to_index_func = (
def physical_to_index_func(row: npt.ArrayLike) -> npt.ArrayLike:
lambda row: ref_image.TransformPhysicalPointToContinuousIndex(
[float(val) for val in row]
)
)
block_region = np.apply_along_axis(
physical_to_index_func, 1, physical_region
)

block_region = np.apply_along_axis(physical_to_index_func, 1, physical_region)
adjusted_block_region = np.array(
[np.min(block_region, axis=0), np.max(block_region, axis=0)]
)
Expand Down
20 changes: 10 additions & 10 deletions src/itk_dreg/block/dask.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@

from .convert import get_target_block_size

def rechunk_to_physical_block(array:dask.array.core.Array,
array_image:itk.Image,
reference_array:dask.array.core.Array,
reference_image:itk.Image) -> dask.array.core.Array:

def rechunk_to_physical_block(
array: dask.array.core.Array,
array_image: itk.Image,
reference_array: dask.array.core.Array,
reference_image: itk.Image,
) -> dask.array.core.Array:
"""
Rechunk the given array/image so that the physical size of each block
approximately matches the physical size of chunks in the reference array/image.
"""
# Determine approximate physical size of a reference image chunk
itk_ref_chunksize = np.flip(reference_array.chunksize)
arr_chunksize = \
get_target_block_size(
itk_ref_chunksize,
reference_image,
array_image
arr_chunksize = get_target_block_size(
itk_ref_chunksize, reference_image, array_image
)

# Rechunk the input array to match physical chunk size
return dask.array.rechunk(array, chunks=np.flip(arr_chunksize))
17 changes: 8 additions & 9 deletions src/itk_dreg/block/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"""

import logging
import itertools
from typing import List, Union

import itk
Expand Down Expand Up @@ -85,9 +84,9 @@ def block_to_itk_image(
def physical_region_to_itk_image(
physical_region: npt.ArrayLike,
spacing: List[float],
direction: Union[itk.Matrix,npt.ArrayLike],
direction: Union[itk.Matrix, npt.ArrayLike],
extend_beyond: bool = True,
image_type: type[itk.Image]=None
image_type: type[itk.Image] = None,
) -> itk.Image:
"""
Represent a physical region as an unallocated itk.Image object.
Expand Down Expand Up @@ -115,9 +114,11 @@ def physical_region_to_itk_image(
orientation mapping from I,J,K to X,Y,Z axes.
"""
direction = np.array(direction)
image_type = image_type or itk.Image[itk.F,3]
assert not np.any(np.isclose(spacing, 0)), f'Invalid spacing: {spacing}'
assert np.all((direction == 0) | (direction == 1) | (direction == -1)), f'Invalid direction: {direction}'
image_type = image_type or itk.Image[itk.F, 3]
assert not np.any(np.isclose(spacing, 0)), f"Invalid spacing: {spacing}"
assert np.all(
(direction == 0) | (direction == 1) | (direction == -1)
), f"Invalid direction: {direction}"

# Set up unit vectors mapping from voxel to physical space
voxel_step_vecs = np.matmul(np.array(direction), np.eye(3) * spacing)
Expand All @@ -135,9 +136,7 @@ def physical_region_to_itk_image(
np.max(physical_region, axis=0) - np.min(physical_region, axis=0)
) / np.abs(physical_step)
output_grid_size = (
np.ceil(output_grid_size_f)
if extend_beyond
else np.floor(output_grid_size_f)
np.ceil(output_grid_size_f) if extend_beyond else np.floor(output_grid_size_f)
)

centerpoint = np.mean(physical_region, axis=0)
Expand Down
Loading

0 comments on commit 974e198

Please sign in to comment.