Source code for ewoksndreg.intensities.registration
from typing import Dict
from typing import List
from typing import Optional
from typing import Sequence
from typing import Union
import numpy
from ..io.input_stack import InputStacks
from ..math.filter import preprocess
from ..math.indices import get_positive_index
from ..transformation.base import Transformation
from .base import IntensityMapping
[docs]
def calculate_transformations(
input_stacks: InputStacks,
mapper: IntensityMapping,
include: Optional[Sequence[int]] = None,
reference_image: Union[int, float] = 0,
block_size: int = 1,
preprocessing_options: Optional[Dict] = None,
) -> Dict[str, List[Transformation]]:
"""
Uses the mapper to calculate the transformation between the reference image and all other images in the stack.
param input_stacks: InputStacks of all the images
param mapper: An IntensityMapper to calculate transformations between the images
param include: Indices of images to include for the registration. Default: all.
param reference_image: The index of the reference image, if 0.5 the reference will be the middle of the stack.
param block_size: Included images get partitioned into blocks.Every image in one block gets aligned to the first element in the block.
The first elements of each block get sequentially aligned to the reference
"""
stack_len = input_stacks.stack_len
if include is None:
include = list(range(stack_len))
if block_size <= 0:
block_size = 1
reference_image = get_positive_index(reference_image, stack_len)
# ref_index is the index of the reference in include, as include might not contain all indices
ref_index = include.index(reference_image)
if preprocessing_options is None:
preprocessing_options = {}
transformations = dict()
for name, input_stack in input_stacks.items():
ref_image0 = preprocess(input_stack[reference_image], **preprocessing_options)
# calculate all transformations up to reference
# counter holds the position in one block, so goes from 0 to block_size-1
indices = list(reversed(include[:ref_index]))
transformations_ = [mapper.identity(ref_image0.ndim)]
transformations_ += _calculate_transformations(
input_stack, indices, mapper, ref_image0, block_size, preprocessing_options
)
transformations_ = list(reversed(transformations_))
# calculate all transformations after reference
indices = include[ref_index + 1 :]
transformations_ += _calculate_transformations(
input_stack, indices, mapper, ref_image0, block_size, preprocessing_options
)
transformations[name] = transformations_
return transformations
def _calculate_transformations(
input_stack: numpy.ndarray,
indices: List[int],
mapper: IntensityMapping,
ref_image: numpy.ndarray,
block_size: int,
preprocessing_options: dict,
):
counter = 0
dim = ref_image.ndim
current_ref_transfo = mapper.identity(dim)
transformations = list()
for i in indices:
next_img = preprocess(input_stack[i], **preprocessing_options)
next_transfo = mapper.calculate(next_img, ref_image) @ current_ref_transfo
transformations.append(next_transfo)
counter += 1
if counter % block_size == 0:
ref_image = next_img
current_ref_transfo = next_transfo
counter = 0
return transformations