Skip to content
Closed
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6c9e081
Pulling across more from standalone prototype
atbenmurray Jul 28, 2022
0b0670d
Applyd function
atbenmurray Aug 1, 2022
b1e6f3c
more atmostonce functionality; baseline atmostonce (non-dictionary) t…
atbenmurray Aug 11, 2022
02a95a4
Pulling across more from standalone prototype
atbenmurray Jul 28, 2022
4fa26c5
Applyd function
atbenmurray Aug 1, 2022
65fafa9
more atmostonce functionality; baseline atmostonce (non-dictionary) t…
atbenmurray Aug 11, 2022
3530432
Working on ground-up refactor of array transforms
atbenmurray Aug 15, 2022
d74fb56
Re-re-re-factored function / array / dict based rotate and others; re…
atbenmurray Aug 17, 2022
2dab7e5
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 17, 2022
6c41489
Resolving merge conflicts
atbenmurray Aug 18, 2022
999698e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 18, 2022
7af9558
Simplified array and dictionary transforms; working on generic translate
atbenmurray Aug 19, 2022
e47b221
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Aug 19, 2022
d53d95d
Base croppad debugged and tests added
atbenmurray Aug 19, 2022
b6a0b05
Partial implementation of mon-metatensor based lazy resampling
atbenmurray Aug 19, 2022
77756c8
Local changes on 034
atbenmurray Aug 29, 2022
73b185b
Resolving conflicts
atbenmurray Aug 29, 2022
886057e
Minor fix to Apply; minor fix to enumerate_results_of_op
atbenmurray Aug 29, 2022
f4ff23d
Merge branch 'lazy_resampling' of github.com:project-monai/monai into…
atbenmurray Aug 29, 2022
1421773
Working on transform based compose compilers
atbenmurray Aug 30, 2022
57ae027
Work on rotate_90 functional, and associated tests
atbenmurray Aug 31, 2022
2f1bf91
Work on apply
atbenmurray Sep 1, 2022
7a8f1de
Resolving conflicts
atbenmurray Sep 1, 2022
d0b490b
bug fixes
atbenmurray Sep 6, 2022
97216af
Removing dead code from apply
atbenmurray Sep 7, 2022
bb3a60e
Addition work on array
atbenmurray Sep 7, 2022
623889c
Merge branch 'lazy_resampling' of github.com:project-monai/monai into…
atbenmurray Sep 7, 2022
f53a56e
More lazy transforms
atbenmurray Sep 9, 2022
eb7692d
Further work on transforms
atbenmurray Sep 14, 2022
b353e3e
Fixes for zoom and rotate; rename of spaced to spacingd; introduction…
atbenmurray Oct 7, 2022
7653631
Merge branch 'lazy_resampling' of github.com:project-monai/monai into…
atbenmurray Oct 7, 2022
bcbfb68
Removing unnecessary comments in apply
atbenmurray Oct 7, 2022
af043e9
Adding utility transforms for compose compiler
atbenmurray Oct 12, 2022
6e8b745
Resolving merge conflicts
atbenmurray Oct 12, 2022
6295e02
Adding RandCropPad and RandCropPadMultiSample array implementations
atbenmurray Oct 14, 2022
b76e965
Compose compile; initial multisample generic croppad (array and dict)…
atbenmurray Oct 19, 2022
62f8172
More work towards lazy resampling
atbenmurray Oct 26, 2022
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
22 changes: 22 additions & 0 deletions monai/data/meta_tensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

from __future__ import annotations

import copy

import warnings
from copy import deepcopy
from typing import Any, Sequence
Expand Down Expand Up @@ -151,6 +153,26 @@ def __init__(
if MetaKeys.SPACE not in self.meta:
self.meta[MetaKeys.SPACE] = SpaceKeys.RAS # defaulting to the right-anterior-superior space

self._pending_transforms = list()

def push_pending_transform(self, meta_matrix):
self._pending_transforms.append(meta_matrix)

def peek_pending_transform(self):
return copy.deepcopy(self._pending_transforms[0])

def pop_pending_transform(self):
transform = self._pending_transforms[0]
self._pending_transforms.pop(0)
return transform

@property
def pending_transforms(self):
return copy.deepcopy(self._pending_transforms)

def clear_pending_transforms(self):
self._pending_transforms = list()

@staticmethod
def update_meta(rets: Sequence, func, args, kwargs) -> Sequence:
"""
Expand Down
Empty file.
142 changes: 142 additions & 0 deletions monai/transforms/atmostonce/apply.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
from typing import Sequence, Union

import itertools as it

import numpy as np


from monai.config import DtypeLike
from monai.data import MetaTensor
from monai.transforms.inverse import InvertibleTransform
from monai.transforms.transform import MapTransform
from monai.utils import GridSampleMode, GridSamplePadMode
from monai.utils.misc import get_backend_from_data, get_device_from_data
from monai.utils.mapping_stack import MatrixFactory

# TODO: This should move to a common place to be shared with dictionary
GridSampleModeSequence = Union[Sequence[Union[GridSampleMode, str]], GridSampleMode, str]
GridSamplePadModeSequence = Union[Sequence[Union[GridSamplePadMode, str]], GridSamplePadMode, str]
DtypeSequence = Union[Sequence[DtypeLike], DtypeLike]


# TODO: move to mapping_stack.py
def extents_from_shape(shape):
extents = [[0, shape[i]] for i in range(1, len(shape))]

extents = it.product(*extents)
return list(np.asarray(e + (1,)) for e in extents)


# TODO: move to mapping_stack.py
def shape_from_extents(extents):
aextents = np.asarray(extents)
mins = aextents.min(axis=0)
maxes = aextents.max(axis=0)
return np.ceil(maxes - mins)[:-1].astype(int)


def apply(data: MetaTensor):
pending = data.pending_transforms

if len(pending) == 0:
return data

dim_count = len(data) - 1
matrix_factory = MatrixFactory(dim_count,
get_backend_from_data(data),
get_device_from_data(data))

# set up the identity matrix and metadata
cumulative_matrix = matrix_factory.identity(dim_count)
cumulative_extents = extents_from_shape(data.shape)

# pre-translate origin to centre of image
translate_to_centre = matrix_factory.translate(dim_count)
cumulative_matrix = translate_to_centre @ cumulative_matrix
cumulative_extents = [e @ translate_to_centre for e in cumulative_extents]

for meta_matrix in pending:
next_matrix = meta_matrix.matrix
cumulative_matrix = next_matrix @ cumulative_matrix
cumulative_extents = [e @ translate_to_centre for e in cumulative_extents]

# TODO: figure out how to propagate extents properly
# TODO: resampling strategy: augment resample or perform multiple stages if necessary
# TODO: resampling strategy - antialiasing: can resample just be augmented?


data.clear_pending_transforms()


class Apply(InvertibleTransform):

def __init__(self):
super().__init__()


class Applyd(MapTransform, InvertibleTransform):

def __init__(self):
super().__init__()

# class Applyd(MapTransform, InvertibleTransform):
#
# def __init__(self,
# keys: KeysCollection,
# modes: GridSampleModeSequence,
# padding_modes: GridSamplePadModeSequence,
# normalized: bool = False,
# device: Optional[torch.device] = None,
# dtypes: Optional[DtypeSequence] = np.float32):
# self.keys = keys
# self.modes = modes
# self.padding_modes = padding_modes
# self.device = device
# self.dtypes = dtypes
# self.resamplers = dict()
#
# if isinstance(dtypes, (list, tuple)):
# if len(keys) != len(dtypes):
# raise ValueError("'keys' and 'dtypes' must be the same length if 'dtypes' is a sequence")
#
# # create a resampler for each output data type
# unique_resamplers = dict()
# for d in dtypes:
# if d not in unique_resamplers:
# unique_resamplers[d] = Resample(norm_coords=not normalized, device=device, dtype=d)
#
# # assign each named data input the appropriate resampler for that data type
# for k, d in zip(keys, dtypes):
# if k not in self.resamplers:
# self.resamplers[k] = unique_resamplers[d]
#
# else:
# # share the resampler across all named data inputs
# resampler = Resample(norm_coords=not normalized, device=device, dtype=dtypes)
# for k in keys:
# self.resamplers[k] = resampler
#
# def __call__(self,
# data: Mapping[Hashable, NdarrayOrTensor],
# allow_missing_keys: bool = False) -> Dict[Hashable, NdarrayOrTensor]:
# d = dict(data)
# mapping_stack = d["mappings"]
# keys = d.keys()
# for key_tuple in self.key_iterator(d,
# expand_scalar_to_tuple(self.modes, len(keys)),
# expand_scalar_to_tuple(self.padding_modes, len(keys)),
# expand_scalar_to_tuple(self.dtypes, len(keys))):
# key, mode, padding_mode, dtype = key_tuple
# affine = mapping_stack[key].transform()
# data = d[key]
# spatial_size = data.shape[1:]
# grid = create_grid(spatial_size, device=self.device, backend="torch", dtype=dtype)
# _device = grid.device
#
# _b = TransformBackends.TORCH if isinstance(grid, torch.Tensor) else TransformBackends.NUMPY
#
# grid, *_ = convert_data_type(grid, torch.Tensor, device=_device, dtype=grid.dtype)
# affine, *_ = convert_to_dst_type(affine, grid)
# d[key] = self.resamplers[key](data, grid=grid, mode=mode, padding_mode=padding_mode)
#
# return d
Loading