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

Lazy functionality 1 2 #6537

Merged
merged 210 commits into from
Jun 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
210 commits
Select commit Hold shift + click to select a range
06d5842
Initial commit
atbenmurray Mar 27, 2023
2507a0b
Refactors and simplification of api / calls
atbenmurray Mar 28, 2023
56b618e
Refactoring functional spatial transform to support lazy_evaluation p…
atbenmurray Mar 28, 2023
315e5b7
Making lazy_evaluation parameter consistent across spatial array lazy…
atbenmurray Mar 28, 2023
4e69313
Updating apply and dictionary spatial transforms to support
atbenmurray Mar 29, 2023
99fa35b
Missing changes to spatial dictionary
atbenmurray Mar 29, 2023
a798e0e
Enable call-time overriding of lazy_evaluation in croppad/functional and
atbenmurray Mar 29, 2023
114b8cc
Updating croppad dictionary and croppad array for call-time laziness
atbenmurray Mar 29, 2023
5df4261
Fix for push_transform; updating the lazy integration test
atbenmurray Mar 29, 2023
84d65f7
removing issue.txt
atbenmurray Mar 30, 2023
7ec442f
. Renaming apply_transform to apply_pending as it is more semantically
atbenmurray Mar 31, 2023
8f62776
Tweaked array ApplyPending and ApplyPendingd for array and dict data
atbenmurray Mar 31, 2023
2492223
Added missing license text.
atbenmurray Mar 31, 2023
0064326
Missing import for apply_pending
atbenmurray Mar 31, 2023
0646602
Merge branch 'dev' into lazy_eval_refactor
atbenmurray Apr 14, 2023
05eb3f9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 14, 2023
788cd74
Fixing syntax error created by merge of dev to PR
atbenmurray Apr 14, 2023
4bd22f8
Fixing issues with pad_func post merge
atbenmurray Apr 14, 2023
1e0510c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 14, 2023
c36b69f
Fixing issues in crop while running unit tests
atbenmurray Apr 14, 2023
8a4f310
Merge branch 'lazy_eval_refactor' of github.com:atbenmurray/monai int…
atbenmurray Apr 14, 2023
3c69776
Fixing issues with OneOf/SomeOf/RandomOrder after dev merge
atbenmurray Apr 14, 2023
6b94aa1
More croppad fixes post dev merge
atbenmurray Apr 14, 2023
bf1c01a
Fixing test_nvtx_decorator after def merge
atbenmurray Apr 14, 2023
19745f9
Removed use of **kwargs parameter in tests as it isn't supported by a…
atbenmurray Apr 23, 2023
b219f13
Setting use of lazy_evaluation to False for Rand2D/Rand3DElastic
atbenmurray Apr 23, 2023
6af8f24
Fixed test_spatial_pad
atbenmurray Apr 23, 2023
173c161
Renaming lazy_evaluation to lazy
atbenmurray Apr 23, 2023
2262ba9
Fixed all outstanding usages of apply_pending in tests. Removed the
atbenmurray Apr 23, 2023
aaaea13
Merge branch 'dev' into lazy_eval_refactor
atbenmurray Apr 24, 2023
088d14e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 24, 2023
3e6a637
Accepting formatting auto-fixes
atbenmurray Apr 24, 2023
98a53bf
Renaming surviving lazy_evaluation instances to lazy.
atbenmurray Apr 24, 2023
28a0175
Renamed the last errant 'lazy_evaluation' instances to 'lazy'
atbenmurray Apr 24, 2023
4e9b6c6
Fixing ruff errors for over-long line lengths
atbenmurray Apr 24, 2023
ad23bea
Fix for issue when the 'lazy' property is set to None
atbenmurray Apr 24, 2023
81549e2
Fix for _apply_transform when lazy is None, post merge tidy up
atbenmurray Apr 24, 2023
77eff5b
Removing the redundant check for log_stats from
atbenmurray Apr 24, 2023
7c53d26
Further formatting auto-fixes
atbenmurray Apr 24, 2023
ee5378f
Making default for overrides be None instead of {}.
atbenmurray Apr 24, 2023
28c05d0
Changed execute_pending_transforms to not make a shallow copy of dict…
atbenmurray Apr 24, 2023
d96fef0
Fixing docstring for Compose
atbenmurray Apr 24, 2023
654cf48
Fixing type complaints
atbenmurray Apr 24, 2023
64ec242
Fix for tests/tests_integration_lazy_samples. The modified lazy
atbenmurray Apr 25, 2023
f38eb9b
Flake8 fix
atbenmurray Apr 25, 2023
14349ff
Flake8 fixes
atbenmurray Apr 25, 2023
51fda45
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 25, 2023
c5742c0
Autoformat style fixes
atbenmurray Apr 25, 2023
ef5173e
Merge branch 'lazy_eval_refactor' of github.com:atbenmurray/monai int…
atbenmurray Apr 25, 2023
916b0a9
Fixing bug introduced by flake8 fix
atbenmurray Apr 25, 2023
20c1cfc
Merge branch 'dev' into lazy_eval_refactor
atbenmurray Apr 25, 2023
c94341f
Removal of obsolete lazy eval code
atbenmurray Apr 25, 2023
cc51f2f
Autoformat shuffle
atbenmurray Apr 25, 2023
06aad01
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 25, 2023
3ae46e9
Resolving mypy issues
atbenmurray Apr 25, 2023
95a6a5f
Merge branch 'lazy_eval_refactor' of github.com:atbenmurray/monai int…
atbenmurray Apr 25, 2023
81559fa
Finally got to grips with mypy troubles
atbenmurray Apr 25, 2023
af9cad1
Final mypy complaints
atbenmurray Apr 25, 2023
a9c8849
Chasing autofixes again
atbenmurray Apr 25, 2023
aadbae3
test_invert_warn_pending is now obsolete due to this no longer being an
atbenmurray Apr 25, 2023
1cccf9b
Adding documentation for ApplyPending/ApplyPendingd. Adding more
atbenmurray Apr 25, 2023
9ae1140
More autofix
atbenmurray Apr 25, 2023
bb2ad0f
Restoring lazy.setters for croppad and spatial lazy transforms
atbenmurray Apr 25, 2023
5abe294
Undoing the previous commit until I get to the bottom of the randaffined
atbenmurray Apr 25, 2023
c2bf4a7
Making apis for OneOf/SomeOf/RandomOrder consistent with Compose
atbenmurray Apr 26, 2023
b16a87f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 26, 2023
816666e
Removing partial docstring for 'lazy', which isn't on the init parameter
atbenmurray Apr 26, 2023
8318121
Merge branch 'lazy_eval_refactor' of github.com:atbenmurray/monai int…
atbenmurray Apr 26, 2023
0e10c24
Adding execute_pending_transforms to lazy/functional __all__
atbenmurray Apr 26, 2023
f323ff9
Removing LazyMode; lazy is now True / False / None
atbenmurray Apr 26, 2023
4b69ec6
Renamed execute_pending_transforms to apply_pending_transforms.
atbenmurray Apr 26, 2023
29ce2b7
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 26, 2023
6774aaa
Removed "LazyMode" from enums.py __all__
atbenmurray Apr 26, 2023
de5b9b8
Merge branch 'lazy_eval_refactor' of github.com:atbenmurray/monai int…
atbenmurray Apr 26, 2023
1c7d172
Modified ApplyPending/ApplyPendingd in the light of the override issue
atbenmurray Apr 26, 2023
bb22c13
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 26, 2023
2159ce8
Correction to type info for execute_compose lazy parameter.
atbenmurray Apr 26, 2023
2c3172d
Removal of comment in docstring about IdentityD being used to cause
atbenmurray Apr 26, 2023
bb1214c
Merge branch 'lazy_eval_refactor' of github.com:atbenmurray/monai int…
atbenmurray Apr 26, 2023
5a7820c
Logging refactored with pending pipeline logging enabled
atbenmurray Apr 26, 2023
503db85
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Apr 26, 2023
1af35fd
All logging_names are now None by default to prevent massive spam in
atbenmurray Apr 26, 2023
75771a8
Merge branch 'lazy_eval_refactor' of github.com:atbenmurray/monai int…
atbenmurray Apr 26, 2023
d97095a
Merge branch 'dev' into lazy_eval_refactor
atbenmurray Apr 26, 2023
af6cd62
More autofixes
atbenmurray Apr 26, 2023
cd246a8
Merge branch 'lazy_eval_refactor' of github.com:atbenmurray/monai int…
atbenmurray Apr 26, 2023
1403d77
Making apply_transform logger_name None by default
atbenmurray Apr 26, 2023
5c4c10a
Added a dictionary test to the compose logging test suite
atbenmurray Apr 26, 2023
5755a65
Updated docstring for _apply_transform
atbenmurray Apr 27, 2023
ca0905a
Removed spurious empty string at the end of one of the logging test case
atbenmurray Apr 27, 2023
e8fdf5a
All spatial transforms now initialize LazyTransform correctly
atbenmurray Apr 27, 2023
70d3517
Adding setters for lazy back in.
atbenmurray Apr 27, 2023
b361a13
Merge branch 'dev' into lazy_eval_refactor
atbenmurray Apr 27, 2023
a6ad51e
Sorting out line length complaint in compose logging tests
atbenmurray Apr 27, 2023
7ec8429
Merge branch 'lazy_eval_refactor' of github.com:atbenmurray/monai int…
atbenmurray Apr 27, 2023
305b88e
Fix for old lazy_evaluation name creeping in during merge
atbenmurray Apr 27, 2023
2aa0ada
Autofix
atbenmurray Apr 27, 2023
7b092ca
Merge branch 'Project-MONAI:dev' into lazy_eval_refactor
atbenmurray Apr 27, 2023
62431ff
Using get_logger so that named loggers all get set up correctly
atbenmurray Apr 27, 2023
6cdf4c6
Merge branch 'lazy_eval_refactor' of github.com:atbenmurray/monai int…
atbenmurray Apr 27, 2023
2ea89c1
Fixes for logging; additional compose logging tests; missing imports
atbenmurray Apr 28, 2023
628a7f8
Adding ApplyPending and ApplyPendingd to transforms.rst
atbenmurray Apr 28, 2023
5b34755
Fixed transforms.rst modifications
atbenmurray Apr 28, 2023
d547b81
Refactor of lazy to provide in_order and out_of_order lazy execution
atbenmurray May 2, 2023
03386dc
Merge branch 'lazy_eval_refactor' of github.com:atbenmurray/monai int…
atbenmurray May 2, 2023
d2fa521
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 2, 2023
eb641c6
Tidied up __all__ issues caused by refactor
atbenmurray May 2, 2023
d7d7cdb
Merge branch 'lazy_eval_refactor' of github.com:atbenmurray/monai int…
atbenmurray May 2, 2023
29b37bf
Removed can_invert flag from compose compiler policy
atbenmurray May 2, 2023
3194980
Moved to use of a TraceKey.STATUS flag. This can be used to track
atbenmurray May 3, 2023
5ff516d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 3, 2023
eebb3de
Formatting autofixes
atbenmurray May 3, 2023
d966856
Merge branch 'lazy_eval_refactor' of github.com:atbenmurray/monai int…
atbenmurray May 3, 2023
e39e0a3
Lazy {reorder: lazy_last_nosync} now passes
atbenmurray May 3, 2023
cf58b9f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 3, 2023
883f8c5
Fixed broken call to isinstance in lazy executors
atbenmurray May 4, 2023
e81f359
Autofix
atbenmurray May 4, 2023
db1486b
Resolving lint issue
atbenmurray May 4, 2023
b151607
Missing passing logger_name through to _apply_transform when mapping …
atbenmurray May 4, 2023
24286f1
Autofix
atbenmurray May 4, 2023
43f7bc0
Added missing lazy=None option from integration tests for lazy
atbenmurray May 4, 2023
b217dbe
Autofix
atbenmurray May 4, 2023
ed1d952
Fixing lint issues
atbenmurray May 5, 2023
e7f3a07
Autofixes
atbenmurray May 5, 2023
0751c52
lint fix
atbenmurray May 5, 2023
6114a67
started on the lazy resampling topic page
atbenmurray May 5, 2023
240059b
Merge branch 'lazy_eval_refactor' of github.com:atbenmurray/monai int…
atbenmurray May 5, 2023
23ff89c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 5, 2023
5e1b81d
Removing unused Sequence import from lazy/executors
atbenmurray May 6, 2023
5dd6113
Renaming ComposeCompiler to ExecuteOptions in test_compose
atbenmurray May 6, 2023
74bed34
Update tests/test_compose.py
atbenmurray May 10, 2023
76e4b85
Execution options is no longer a poltergeist. Refactored is_tensor_in…
atbenmurray May 10, 2023
1c4fa6c
Merge branch 'lazy_eval_refactor' of github.com:atbenmurray/monai int…
atbenmurray May 10, 2023
8dde40d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 10, 2023
7fd32e2
Removing unnecessary active_key property
atbenmurray May 10, 2023
10d95ce
Merge branch 'lazy_eval_refactor' of github.com:atbenmurray/monai int…
atbenmurray May 10, 2023
0d6a847
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 10, 2023
1ceeb1a
Fix for multi-sampled data for transforms that aceept *args; refactor…
atbenmurray May 11, 2023
38bdef6
Merge branch 'lazy_eval_refactor' of github.com:atbenmurray/monai int…
atbenmurray May 11, 2023
6e0cfd9
Renaming LazyTrait partially_lazy -> checks_data
atbenmurray May 21, 2023
f2fb06a
Merge branch 'Project-MONAI:dev' into lazy_eval_refactor
atbenmurray May 21, 2023
155ad90
Initial commit of reduced lazy resampling functionality for 1.2
atbenmurray May 22, 2023
ba33784
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 22, 2023
ab47030
Fixing isort complaint that doesn't show up when running --autofix on…
atbenmurray May 22, 2023
f5d332b
Homogenizing initialiser values for OneOf, RandomOrder, SomeOf wrt la…
atbenmurray May 22, 2023
5406a2b
DCO Remediation Commit for Ben Murray <[email protected]>
atbenmurray May 22, 2023
0ce6fa9
Simplify types for log_stats and logger_name
atbenmurray May 22, 2023
0c1613b
Resolving merge conflicts
atbenmurray May 22, 2023
0cf616a
Docstring fixes
atbenmurray May 22, 2023
8ffae00
monai/transforms/transform.py
atbenmurray May 22, 2023
1c19c31
Resolving circular import issue with Compose and utils in a way that …
atbenmurray May 23, 2023
4670f08
Work towards lazy resampling docs
atbenmurray May 23, 2023
4f8dbcb
Merge branch 'lazy_functionality_1_2' of github.com:atbenmurray/monai…
atbenmurray May 23, 2023
0838f91
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 23, 2023
f3f0dd1
autofix
atbenmurray May 23, 2023
700b046
Merge branch 'lazy_functionality_1_2' of github.com:atbenmurray/monai…
atbenmurray May 23, 2023
ed83504
autofix
atbenmurray May 24, 2023
4abab4d
docstring fixes for is_tensor_invertible
atbenmurray May 24, 2023
4e92eb0
lazy on init should have a default of False
atbenmurray May 24, 2023
0cfd098
Reworked text for Compose and subclasses for lazy resamping; added in…
atbenmurray May 24, 2023
fe56297
autofix
atbenmurray May 24, 2023
a58b91d
Updating docstrings for things that interact with lazy resampling
atbenmurray May 24, 2023
22f34a1
Fixing ref anchor; more work on the topic contents
atbenmurray May 24, 2023
ba58739
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 24, 2023
e201feb
Merge branch 'dev' into lazy_functionality_1_2
atbenmurray May 24, 2023
b6bdf22
Typo in docstring
atbenmurray May 25, 2023
4301452
Fixed typo in lazy/functional.py docstring
atbenmurray May 25, 2023
dd56b76
Improving tests for OneOf, RandomOrder and SomeOf based on review
atbenmurray May 25, 2023
e9b182e
Merge branch 'lazy_functionality_1_2' of github.com:atbenmurray/monai…
atbenmurray May 25, 2023
9649731
removal of dead code
atbenmurray May 25, 2023
5c1dbb2
simplification of tensor manipulation in test_compose
atbenmurray May 25, 2023
d4d6b2c
Refactoring compose tests to move initialiser out of assertRaises
atbenmurray May 25, 2023
ec3236f
Using Eric's logging refactor suggestion; fixing issue with integrati…
atbenmurray May 25, 2023
e840277
Refactored data_from_keys
atbenmurray May 25, 2023
f7c43b9
Removing dead logging code
atbenmurray May 25, 2023
77bb4e2
autofix
atbenmurray May 25, 2023
ff962ef
Dead code removal, doc fixes
atbenmurray May 25, 2023
dface19
Removing dead imports from lazy/functional.py
atbenmurray May 25, 2023
fc8ba59
lazy_resampling doc :ref: fix
atbenmurray May 25, 2023
e2a4d51
neater tensor manipulation
atbenmurray May 25, 2023
b2eeadd
autofixes
atbenmurray May 26, 2023
f5551f7
Additional documentation
atbenmurray May 26, 2023
c6957d4
Merge branch 'lazy_functionality_1_2' of github.com:atbenmurray/monai…
atbenmurray May 26, 2023
3ba57ce
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 26, 2023
8525e6d
Fixing doc typos
atbenmurray May 26, 2023
3be944e
Merge branch 'lazy_functionality_1_2' of github.com:atbenmurray/monai…
atbenmurray May 26, 2023
ee6751f
Removing accidentally added html files
atbenmurray May 26, 2023
4c84630
Removing dict check from ApplyPendingd
atbenmurray May 26, 2023
e0210b6
Adding extra documentation for apply_pending_transforms_in_order
atbenmurray May 26, 2023
fcbd9b7
Refactoring the code in monai.transforms.lazy.executors into monai.tr…
atbenmurray May 26, 2023
09477b0
Removing executors.py as it is no longer required
atbenmurray May 26, 2023
cf48aaf
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 26, 2023
f990a30
autofixes
atbenmurray May 26, 2023
bafde0e
Resolving whitespace conflict
atbenmurray May 26, 2023
769aec3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 26, 2023
64ed447
Implementation of review points: 1. Making RandRitateBox90d and Refer…
atbenmurray May 26, 2023
a6fcd96
Removing logger_name from Compose and related that already have log_s…
atbenmurray May 26, 2023
2658d4b
autofix
atbenmurray May 26, 2023
24a30eb
Additional content and doc fixes
atbenmurray May 30, 2023
21c9f84
Missing images for lazy resampling
atbenmurray May 30, 2023
8bb8b1e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 30, 2023
7495c07
Merge branch 'dev' into lazy_functionality_1_2
ericspod May 30, 2023
cd65152
Updating docs for has_status_key, removing dead import statement
atbenmurray May 31, 2023
2e5f23d
autofix
atbenmurray May 31, 2023
5a754c8
Removing erroneous arg from docstring
atbenmurray May 31, 2023
c3b8c1f
Renaming _raise_if_tensor_is_not_invertible
atbenmurray May 31, 2023
ff73762
Merge branch 'dev' into lazy_functionality_1_2
Nic-Ma Jun 1, 2023
0d4143c
[MONAI] code formatting
monai-bot Jun 1, 2023
e766652
Removing type: ignore from auto3dseg/data_analyser.py
atbenmurray Jun 1, 2023
1320aea
Merge branch 'lazy_functionality_1_2' of github.com:atbenmurray/monai…
atbenmurray Jun 1, 2023
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
1 change: 1 addition & 0 deletions docs/images/lazy_resampling_apply_pending_example.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/images/lazy_resampling_homogeneous_matrices.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/images/lazy_resampling_lazy_example_1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/images/lazy_resampling_none_example.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/images/lazy_resampling_trad_example_1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ Technical documentation is available at `docs.monai.io <https://docs.monai.io>`_
:caption: Specifications

bundle_intro
lazy_resampling

Model Zoo
---------
Expand Down
273 changes: 273 additions & 0 deletions docs/source/lazy_resampling.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
.. _lazy_resampling:

:github_url: https://github.com/Project-MONAI/MONAI

Lazy Resampling
===============

.. toctree::
:maxdepth: 2

Introduction
^^^^^^^^^^^^

Lazy Resampling is a new feature introduced in MONAI 1.2. This feature is still experimental at this time and it is
possible that behaviour and APIs will change in upcoming releases.

Lazy resampling reworks the way that preprocessing is performed. It improves upon standard preprocessing pipelines and
can provide significant benefits over traditional preprocessing. It can improve:
* pipeline execution time
* pipeline memory usage in CPU or GPU
* image and segmentation quality by reducing incidental noise and artifacts caused by resampling

The way it does this is by adopting the methods used in computer graphics pipelines, in which transformations to objects
in a scene are modified by composing together a sequence of "homogeneous matrices".

Rather than each transform being executed in isolation, potentially requiring the data to be resampled to make a new
tensor, transforms whose operations can be described in terms of homogeneous transforms do not execute their transforms
immediately. Instead, they create a "pending operation", which is added to a list of operations that will be fused
together and carried out at the point that they are required.


How Lazy Resampling changes preprocessing
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

In order to understand the difference between traditional pipelines and lazy pipelines, it is best to look at an example
pipeline and the differences between their execution strategies:


Traditional execution
+++++++++++++++++++++

With traditional resampling, found both in MONAI and many other preprocessing libraries, you typically define a sequence
of transforms and pass them to a ``Compose`` object, such as :class:`monai.transforms.compose.Compose`.

Example::

transforms = [
Spacingd(keys=["img", "seg"], ...),
Orientationd(keys=["img", "seg"], ...),
RandSpatialCropd(keys=["img", "seg"], ...),
RandRotate90d(keys=["img", "seg"], ...),
RandRotated(keys=["img", "seg"], ...),
RandZoomd(keys=["img", "seg"], ...),
RandGaussianNoised(keys="img", ...),
]
pipeline = Compose(transforms)

# elsewhere this will be called many times (such as in a Dataset instance)
outputs = pipeline(inputs)


The following will then happen when we call ``pipeline(inputs)``:

1. ``Spacingd`` is called and interpolates the data samples
2. ``Orientationd`` permutes the data samples so that their spatial dimensions are reorganised
3. ``RandSpatialCropd`` crops a random patch of the data samples, throwing away the rest of the data in the process
4. ``RandRotate90d`` has a chance of performing a tensor-based rotation of the data samples
5. ``RandRotated`` has a chance of performing a full resample of the data samples
6. ``RandZoomd`` has a chance of performing a interpolation of the data samples
7. ``RandGaussianNoised`` has a chance of adding noise to ``img``

.. figure:: ../images/lazy_resampling_trad_example_1.svg

Figure showing traditional pipeline execution. Tensors (the boxes in the main body of the image) are passed through
the pipeline, and the state of their `applied_operations` property is shown at each step. Tensors with a thick red
border have undergone some kind of resample operation at that stage.

Overall, there are up to three occasions where the data is either interpolated or resampled through spatial transforms
(``Spacingd``, ``RandRotated`` and ``RandZoomd``). Furthermore, the crop that occurs means that the output data
samples might contain pixels for which there is data but that show padding values, because the data was thrown away by
``RandSpatialCrop``.

Each of these operations takes time and memory, but, as we can see in the example above, also creates resampling
artifacts and can even destroy data in the resulting data samples.

Lazy execution
++++++++++++++

Lazy resampling works very differently. When you execute the same pipeline with `lazy=True`, the following happens:

#. ``Spacingd`` is executed lazily. It puts a description of the operation that it wants to perform onto a list of
pending operations
#. ``Orientationd`` is executed lazily. It adds a description of its own operation to the pending operation list so
now there are 2 pending operations
#. ``RandSpatialCropd`` is executed lazily. It adds a description of its own operation to the pending
operation list so now there are 3 pending operations
#. ``RandRotate90d`` is executed lazily. It adds a description of its own operation to the pending operation
list so now there are 4 pending operations
#. ``RandRotated`` is executed lazily. It adds a description of its own operation to the pending operation
list so now there are 5 pending operations
#. ``RandZoomd`` is executed lazily. It adds a description of its own operation to the pending operation
list so now there are 6 pending operations

#. [Spacingd, Orientationd, RandSpatialCropd, RandRotate90d, RandRotated, RandZoomd] are all on the pending
operations list but have yet to be carried out on the data
#. ``RandGaussianNoised`` is not a lazy transform. It is now time for the pending operations to be evaluated. Their
descriptions are mathematically composited together, to determine the operation that results from all of them being
carried out. This is then applied in a single resample operation. Once that is done, RandGaussianNoised operates on
the resulting data

.. figure:: ../images/lazy_resampling_lazy_example_1.svg

Figure showing lazy pipeline execution. We show the state of the `pending_operations` and `applied_operations`
properties of the tensor as it is processed by the pipeline. Thick red borders indicate some kind of resampling
operation has taken place at that step. Lazy resampling performs far fewer of these operations.

The single resampling operation has less noise induced by resampling, as it only occurs once in this pipeline rather
than three times in the traditional pipeline. More importantly, although the crop describes an operation to keep only a
subset of the data sample, the crop is not performed until after the spatial transforms are completed, which means that
all of the data sample that is within bounds is preserved and is part of the resulting output.


Composing homogeneous matrices
++++++++++++++++++++++++++++++

.. image:: ../images/lazy_resampling_homogeneous_matrices.svg


Although a full treatment of homogeneous matrices is outside the scope of this document, a brief overview of them is
useful to understand the mechanics of lazy resampling. Homogeneous matrices are used in computer graphics to describe
operations in cartesian space in a unified (homogeneous) fashion. Rotation, scaling, translation, and skewing are
amongst the operations that can be performed. Homogeneous matrices have the interesting property that they can be
composited together, thus describing the result of a sequence of operations. Note that ordering is important;
`scale -> rotate -> translation` gives a very different result to `translation -> rotate -> scale`.

The ability to composite homogeneous matrices together allows a sequence of operations to be carried out as a single
operation, which is the key mechanism by which lazy resampling functions.


API changes
^^^^^^^^^^^

A number of new arguments have been added to existing properties, which we'll go over in detail here. In particular,
we'll focus on :class:`Compose<monai.transforms.compose.Compose`> and
:class:`LazyTrait<monai.transforms.traits.LazyTrait>`/ :class:`LazyTransform<monai.transforms.transform.LazyTransform>`
and the way that they interact with each other.


Compose
+++++++

:class:`Compose<monai.transforms.compose.Compose>` gains a number of new arguments that can be used to control
resampling behaviour. Each of them is covered in its own section:


lazy
""""

``lazy`` controls whether execution is carried out in a lazy manner or not. It has three values that it can take:

* `lazy=False` forces the pipeline to be executed in the standard way with every transform applied immediately
* `lazy=True` forces the pipeline to be executed lazily. Every transform that implements
:class:`LazyTrait<monai.transforms.traits.LazyTrait>` (or inherits
:class:`LazyTransform<monai.transforms.transform.LazyTransform>`) will be executed lazily
* `lazy=None` means that the pipeline can execute lazily, but only on transforms that have their own `lazy` property
set to True.


overrides
"""""""""

``overrides`` allows the user to specify certain parameters that transforms can be overridden with when they are
executed lazily. This parameter is primarily provided to allow you to run a pipeline without having to modify fields
like ``mode`` and ``padding_mode``.
When executing dictionary-based transforms, you provide a dictionary containing overrides for each key, as follows. You
can omit keys that don't require overrides:

.. code-block::

{
"image": {"mode": "bilinear"},
"label": {"padding_mode": "zeros"}
}


log_stats
"""""""""

Logging of transform execution is provided if you wish to understand exactly how your pipelines execute. It can take a
``bool`` or ``str`` value, and is False by default, which disables logging. Otherwise, you can enable it by passing it
the name of a logger that you wish to use (note, you don't have to construct the logger beforehand).


LazyTrait / LazyTransform
+++++++++++++++++++++++++

Many transforms now implement either `LazyTrait<monai.transforms.traits.LazyTrait>` or
`LazyTransform<monai.transforms.transform.Transform>`. Doing so marks the transform for lazy execution. Lazy
transforms have the following in common:


``__init__`` has a ``lazy`` argument
""""""""""""""""""""""""""""""""""""

``lazy`` is a ``bool`` value that can be passed to the initialiser when a lazy transform is instantiated. This
indicates to the transform that it should execute lazily or not lazily. Note that this value can be overridden by
passing ``lazy`` to ``__init__``. ``lazy`` is ``False`` by default


``__call__`` has a ``lazy`` argument
""""""""""""""""""""""""""""""""""""

``lazy`` is an optional ``bool`` value that can be passed at call time to override the behaviour defined during
initialisation. It has a default value of ``None``. If it is not ``None``, then this value is used instead of
``self.lazy``. This allows the calling :class:`Compose<monai.transforms.compose.Compose>` instance to override
default values rather than having to set it on every lazy transform (unless the user sets
:class:`Compose.lazy<monai.transforms.compose.Compose>` to ``None``).


lazy property
"""""""""""""

The lazy property allows you to get or set the lazy status of a lazy transform after constructing it.


requires_current_data property (get only)
"""""""""""""""""""""""""""""""""""""""""

The ``requires_current_data`` property indicates that a transform makes use of the data in one or more of the tensors
that it is passed during its execution. Such transforms require that the tensors must therefore be up to date, even if
the transform itself is executing lazily. This is required for transforms such as ``CropForeground[d]``,
``RandCropByPosNegLabel[d]``, and ``RandCropByLabelClasses[d]``. This property is implemented to return ``False`` on
``LazyTransform`` and must be overridden to return ``True`` by transforms that check data values when executing.


Controlling laziness
^^^^^^^^^^^^^^^^^^^^

There are two ways that a user can provide more fine-grained control over laziness. One is to make use of lazy=None
when initialising or calling ``Compose`` instances. The other is to use the ``ApplyPending[d]`` transforms. These
techniques can be freely mixed and matched.


Using ``lazy=None``
+++++++++++++++++++

``Lazy=None`` tells ``Compose`` to honor the lazy flags set on each lazy transform. These are set to False by default
so the user must set lazy=True on the transforms that they still wish to execute lazily.


``lazy=None`` example:
""""""""""""""""""""""

.. figure:: ../images/lazy_resampling_none_example.svg

Figure shwoing the effect of using ``lazy=False`` when ``Compose`` is being executed with ``lazy=None``. Note that
the additional resamples that occur due to ``RandRotate90d`` being executed in a non-lazy fashion.


Using ``ApplyPending[d]``
+++++++++++++++++++++++++

``ApplyPending[d]`` causes all pending transforms to be executed before the following transform, regardless of whether
the following transform is a lazy transform, or is configured to execute lazily.


``ApplyPending`` Example:
"""""""""""""""""""""""""

.. figure:: ../images/lazy_resampling_apply_pending_example.svg

Figure showing the use of :class:`ApplyPendingd<monai.transforms.lazy.dictionary.ApplyPendingd>` to cause
resampling to occur in the midele of a chain of lazy transforms.
28 changes: 22 additions & 6 deletions docs/source/transforms.rst
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,17 @@ MRI Transforms
:special-members: __call__


Lazy
^^^^

`ApplyPending`
""""""""""""""

.. autoclass:: ApplyPending
:members:
:special-members: __call__


Utility
^^^^^^^

Expand Down Expand Up @@ -1912,6 +1923,17 @@ Smooth Field (Dict)
:special-members: __call__


Lazy (Dict)
^^^^^^^^^^^

`ApplyPendingd`
"""""""""""""""

.. autoclass:: ApplyPendingd
:members:
:special-members: __call__


Utility (Dict)
^^^^^^^^^^^^^^

Expand Down Expand Up @@ -2211,9 +2233,3 @@ Utilities

.. automodule:: monai.transforms.utils_pytorch_numpy_unification
:members:

Lazy
----
.. automodule:: monai.transforms.lazy
:members:
:imported-members:
16 changes: 13 additions & 3 deletions monai/apps/detection/transforms/dictionary.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
from monai.data.box_utils import COMPUTE_DTYPE, BoxMode, clip_boxes_to_image
from monai.data.meta_tensor import MetaTensor, get_track_meta
from monai.data.utils import orientation_ras_lps
from monai.transforms import Flip, RandFlip, RandRotate90d, RandZoom, Rotate90, SpatialCrop, Zoom
from monai.transforms import Flip, RandFlip, RandZoom, Rotate90, SpatialCrop, Zoom
from monai.transforms.inverse import InvertibleTransform
from monai.transforms.transform import MapTransform, Randomizable, RandomizableTransform
from monai.transforms.utils import generate_pos_neg_label_crop_centers, map_binary_to_indices
Expand Down Expand Up @@ -1291,7 +1291,7 @@ def inverse(self, data: Mapping[Hashable, torch.Tensor]) -> dict[Hashable, torch
return d


class RandRotateBox90d(RandRotate90d):
class RandRotateBox90d(RandomizableTransform, MapTransform, InvertibleTransform):
"""
With probability `prob`, input boxes and images are rotated by 90 degrees
in the plane specified by `spatial_axes`.
Expand Down Expand Up @@ -1323,7 +1323,13 @@ def __init__(
) -> None:
self.image_keys = ensure_tuple(image_keys)
self.box_keys = ensure_tuple(box_keys)
super().__init__(self.image_keys + self.box_keys, prob, max_k, spatial_axes, allow_missing_keys)

MapTransform.__init__(self, self.image_keys + self.box_keys, allow_missing_keys)
RandomizableTransform.__init__(self, prob)

self.max_k = max_k
self.spatial_axes = spatial_axes
self._rand_k = 0
self.box_ref_image_keys = ensure_tuple_rep(box_ref_image_keys, len(self.box_keys))

def __call__(self, data: Mapping[Hashable, torch.Tensor]) -> Mapping[Hashable, torch.Tensor]:
Expand Down Expand Up @@ -1364,6 +1370,10 @@ def __call__(self, data: Mapping[Hashable, torch.Tensor]) -> Mapping[Hashable, t
self.push_transform(d[key], extra_info=xform)
return d

def randomize(self, data: Any | None = None) -> None:
self._rand_k = self.R.randint(self.max_k) + 1
super().randomize(None)

def inverse(self, data: Mapping[Hashable, torch.Tensor]) -> dict[Hashable, torch.Tensor]:
d = dict(data)
if self._rand_k % 4 == 0:
Expand Down
6 changes: 3 additions & 3 deletions monai/apps/reconstruction/transforms/dictionary.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
from monai.apps.reconstruction.transforms.array import EquispacedKspaceMask, RandomKspaceMask
from monai.config import DtypeLike, KeysCollection
from monai.config.type_definitions import NdarrayOrTensor
from monai.transforms import InvertibleTransform
from monai.transforms.croppad.array import SpatialCrop
from monai.transforms.croppad.dictionary import Cropd
from monai.transforms.intensity.array import NormalizeIntensity
from monai.transforms.transform import MapTransform, RandomizableTransform
from monai.utils import FastMRIKeys
Expand Down Expand Up @@ -190,7 +190,7 @@ def set_random_state(
return self


class ReferenceBasedSpatialCropd(Cropd):
class ReferenceBasedSpatialCropd(MapTransform, InvertibleTransform):
"""
Dictionary-based wrapper of :py:class:`monai.transforms.SpatialCrop`.
This is similar to :py:class:`monai.transforms.SpatialCropd` which is a
Expand All @@ -213,7 +213,7 @@ class ReferenceBasedSpatialCropd(Cropd):
"""

def __init__(self, keys: KeysCollection, ref_key: str, allow_missing_keys: bool = False) -> None:
super().__init__(keys, cropper=None, allow_missing_keys=allow_missing_keys) # type: ignore
MapTransform.__init__(self, keys, allow_missing_keys)
self.ref_key = ref_key

def __call__(self, data: Mapping[Hashable, Tensor]) -> dict[Hashable, Tensor]:
Expand Down
Loading