cornucopia 0.3.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cornucopia-0.4.0/PKG-INFO +93 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/README.md +1 -1
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/_version.py +3 -3
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/base.py +22 -4
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/baseutils.py +23 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/contrast.py +1 -1
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/geometric.py +223 -69
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/intensity.py +87 -18
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/kspace.py +29 -17
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/labels.py +28 -22
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/noise.py +18 -12
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/psf.py +7 -6
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/qmri.py +74 -69
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/random.py +60 -14
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/synth.py +6 -2
- cornucopia-0.4.0/cornucopia/tests/test_backward_geometric.py +173 -0
- cornucopia-0.4.0/cornucopia/tests/test_backward_intensity.py +243 -0
- cornucopia-0.4.0/cornucopia/tests/test_backward_kspace.py +115 -0
- cornucopia-0.4.0/cornucopia/tests/test_backward_noise.py +169 -0
- cornucopia-0.4.0/cornucopia/tests/test_backward_psf.py +143 -0
- cornucopia-0.4.0/cornucopia/tests/test_backward_qmri.py +249 -0
- cornucopia-0.4.0/cornucopia/tests/test_backward_random.py +44 -0
- cornucopia-0.4.0/cornucopia/tests/test_backward_synth.py +72 -0
- cornucopia-0.4.0/cornucopia/tests/test_geometric.py +26 -0
- cornucopia-0.4.0/cornucopia/tests/test_intensity.py +9 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/utils/b0.py +23 -23
- cornucopia-0.4.0/cornucopia/utils/compat.py +30 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/utils/conv.py +14 -9
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/utils/kernels.py +124 -115
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/utils/py.py +19 -2
- cornucopia-0.4.0/cornucopia/utils/smart_inplace.py +163 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/utils/warps.py +6 -3
- cornucopia-0.4.0/cornucopia.egg-info/PKG-INFO +93 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia.egg-info/SOURCES.txt +12 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/setup.cfg +1 -1
- cornucopia-0.3.0/PKG-INFO +0 -87
- cornucopia-0.3.0/cornucopia.egg-info/PKG-INFO +0 -87
- {cornucopia-0.3.0 → cornucopia-0.4.0}/LICENSE +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/__init__.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/ctx.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/fov.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/io.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/special.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/tests/__init__.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/tests/test_run_contrast.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/tests/test_run_fov.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/tests/test_run_geometric.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/tests/test_run_intensity.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/tests/test_run_kspace.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/tests/test_run_labels.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/tests/test_run_noise.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/tests/test_run_psf.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/tests/test_run_qmri.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/tests/test_run_synth.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/utils/__init__.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/utils/bounds.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/utils/gmm.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/utils/indexing.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/utils/io.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/utils/jit.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/utils/morpho.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/utils/padding.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/utils/patch.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia/utils/version.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia.egg-info/dependency_links.txt +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia.egg-info/requires.txt +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/cornucopia.egg-info/top_level.txt +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/pyproject.toml +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/setup.py +0 -0
- {cornucopia-0.3.0 → cornucopia-0.4.0}/versioneer.py +0 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cornucopia
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: An abundance of augmentation layers
|
|
5
|
+
Author: Yael Balbastre
|
|
6
|
+
Author-email: yael.balbastre@gmail.com
|
|
7
|
+
License: MIT
|
|
8
|
+
Project-URL: Source Code, https://github.com/balbasty/cornucopia
|
|
9
|
+
Platform: OS Independent
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
|
|
16
|
+
Requires-Python: >=3.6
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: torch>=1.8
|
|
20
|
+
Requires-Dist: numpy
|
|
21
|
+
Requires-Dist: nibabel
|
|
22
|
+
Requires-Dist: torch-interpol>=0.2.4
|
|
23
|
+
Requires-Dist: torch-distmap
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
<picture align="center">
|
|
27
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/icons/cornucopia_lightorange.svg">
|
|
28
|
+
<source media="(prefers-color-scheme: light)" srcset="docs/icons/cornucopia_orange.svg">
|
|
29
|
+
<img alt="Cornucopia logo" src="https://github.com/balbasty/cornucopia/raw/main/docs/icons/cornucopia_orange.svg">
|
|
30
|
+
</picture>
|
|
31
|
+
|
|
32
|
+
The `cornucopia` package provides a generic framework for preprocessing,
|
|
33
|
+
augmentation, and domain randomization; along with an abundance of specific layers,
|
|
34
|
+
mostly targeted at (medical) imaging. `cornucopia` is written using a PyTorch
|
|
35
|
+
backend, and therefore runs **on the CPU or GPU**.
|
|
36
|
+
|
|
37
|
+
Cornucopia is *intended* to be used on the GPU for on-line augmentation.
|
|
38
|
+
A quick [benchmark](docs/examples/benchmark.ipynb) of affine and elastic augmentation
|
|
39
|
+
shows that while cornucopia is slower than [TorchIO](https://github.com/fepegar/torchio)
|
|
40
|
+
on the CPU (~ 3s vs 1s), it is greatly accelerated on the GPU (~ 50ms).
|
|
41
|
+
|
|
42
|
+
Since gradients are not expected to backpropagate through its layers, it can
|
|
43
|
+
theoretically be used within any dataloader pipeline,
|
|
44
|
+
independent of the downstream learning framework (pytorch, tensorflow, jax, ...).
|
|
45
|
+
|
|
46
|
+
## Installation
|
|
47
|
+
|
|
48
|
+
### Dependencies
|
|
49
|
+
|
|
50
|
+
- `pytorch >= 1.8`
|
|
51
|
+
- `numpy`
|
|
52
|
+
- `nibabel`
|
|
53
|
+
- `torch-interpol`
|
|
54
|
+
- `torch-distmap`
|
|
55
|
+
|
|
56
|
+
### Conda
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
conda install cornucopia -c balbasty -c pytorch -c conda-forge
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Pip (release)
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
pip install cornucopia
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Pip (dev)
|
|
69
|
+
|
|
70
|
+
```sh
|
|
71
|
+
pip install cornucopia@git+https://github.com/balbasty/cornucopia
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Documentation
|
|
75
|
+
|
|
76
|
+
Read the [documentation](https://cornucopia.readthedocs.io) and in particular:
|
|
77
|
+
- [installation](https://cornucopia.readthedocs.io/en/latest/install/)
|
|
78
|
+
- [get started](https://cornucopia.readthedocs.io/en/latest/start/)
|
|
79
|
+
- [examples](https://cornucopia.readthedocs.io/en/latest/examples/overview/)
|
|
80
|
+
- [API](https://cornucopia.readthedocs.io/en/latest/api/overview/)
|
|
81
|
+
|
|
82
|
+
## Other augmentation packages
|
|
83
|
+
|
|
84
|
+
There are other great, and much more mature, augmentation packages
|
|
85
|
+
out-there (although few run on the GPU). Here's a non-exhaustive list:
|
|
86
|
+
- [MONAI](https://github.com/Project-MONAI/MONAI)
|
|
87
|
+
- [TorchIO](https://github.com/fepegar/torchio)
|
|
88
|
+
- [Albumentations](https://github.com/albumentations-team/albumentations) (2D only)
|
|
89
|
+
- [Volumentations](https://github.com/ZFTurbo/volumentations) (3D extension of Albumentations)
|
|
90
|
+
|
|
91
|
+
## Contributions
|
|
92
|
+
|
|
93
|
+
If you find this project useful and wish to contribute, please reach out!
|
|
@@ -10,7 +10,7 @@ mostly targeted at (medical) imaging. `cornucopia` is written using a PyTorch
|
|
|
10
10
|
backend, and therefore runs **on the CPU or GPU**.
|
|
11
11
|
|
|
12
12
|
Cornucopia is *intended* to be used on the GPU for on-line augmentation.
|
|
13
|
-
A quick [benchmark](examples/benchmark.ipynb) of affine and elastic augmentation
|
|
13
|
+
A quick [benchmark](docs/examples/benchmark.ipynb) of affine and elastic augmentation
|
|
14
14
|
shows that while cornucopia is slower than [TorchIO](https://github.com/fepegar/torchio)
|
|
15
15
|
on the CPU (~ 3s vs 1s), it is greatly accelerated on the GPU (~ 50ms).
|
|
16
16
|
|
|
@@ -8,11 +8,11 @@ import json
|
|
|
8
8
|
|
|
9
9
|
version_json = '''
|
|
10
10
|
{
|
|
11
|
-
"date": "
|
|
11
|
+
"date": "2025-04-16T18:13:05+0100",
|
|
12
12
|
"dirty": false,
|
|
13
13
|
"error": null,
|
|
14
|
-
"full-revisionid": "
|
|
15
|
-
"version": "0.
|
|
14
|
+
"full-revisionid": "6f8ab58dfcfe8978c9aa9e8b05898dcf7d75bb5b",
|
|
15
|
+
"version": "0.4.0"
|
|
16
16
|
}
|
|
17
17
|
''' # END VERSION_JSON
|
|
18
18
|
|
|
@@ -447,6 +447,8 @@ class SequentialTransform(SpecialMixin, SharedMixin, Transform):
|
|
|
447
447
|
def make_final(self, x, max_depth=float('inf')):
|
|
448
448
|
if max_depth == 0:
|
|
449
449
|
return self
|
|
450
|
+
if self.is_final:
|
|
451
|
+
return self
|
|
450
452
|
# x = VirtualTensor.from_any(x, compute_stats=True)
|
|
451
453
|
trf = []
|
|
452
454
|
for t in self:
|
|
@@ -477,12 +479,23 @@ class SequentialTransform(SpecialMixin, SharedMixin, Transform):
|
|
|
477
479
|
x = args[0]
|
|
478
480
|
else:
|
|
479
481
|
return None
|
|
480
|
-
for trf in self
|
|
482
|
+
for trf in self:
|
|
481
483
|
with IncludeKeysTransform(trf, self.include), \
|
|
482
484
|
ExcludeKeysTransform(trf, self.exclude):
|
|
483
485
|
x = trf(x)
|
|
484
486
|
return x
|
|
485
487
|
|
|
488
|
+
def xform(self, x):
|
|
489
|
+
# This should only be called when a Layer's `make_final` returns
|
|
490
|
+
# a `SequentialTransform`` (i.e., it is created implictly under
|
|
491
|
+
# the hood, not explicitly by the user).
|
|
492
|
+
# In such cases, `shared=False` and hopefully we can just fallback
|
|
493
|
+
# to `forward()`.
|
|
494
|
+
#
|
|
495
|
+
# FIXME
|
|
496
|
+
# what happens if there's weird stuff in returns/include/exclude?
|
|
497
|
+
return self(x)
|
|
498
|
+
|
|
486
499
|
def __len__(self):
|
|
487
500
|
return len(self.transforms)
|
|
488
501
|
|
|
@@ -556,9 +569,11 @@ class MaybeTransform(SpecialMixin, SharedMixin, Transform):
|
|
|
556
569
|
img = (0.2 * gauss)(img)
|
|
557
570
|
```
|
|
558
571
|
```
|
|
559
|
-
"""
|
|
560
572
|
|
|
561
|
-
|
|
573
|
+
!!! changedin " \
|
|
574
|
+
Default for `shared` changed from `False` to `True`"
|
|
575
|
+
"""
|
|
576
|
+
def __init__(self, transform, prob=0.5, *, shared=True, **kwargs):
|
|
562
577
|
"""
|
|
563
578
|
|
|
564
579
|
Parameters
|
|
@@ -617,9 +632,12 @@ class SwitchTransform(SpecialMixin, SharedMixin, Transform):
|
|
|
617
632
|
```python
|
|
618
633
|
img = cc.switch({gauss: 0.5, chi: 0.5})(img)
|
|
619
634
|
```
|
|
635
|
+
|
|
636
|
+
!!! changedin " \
|
|
637
|
+
Default for `shared` changed from `False` to `True`"
|
|
620
638
|
"""
|
|
621
639
|
|
|
622
|
-
def __init__(self, transforms, prob=0, *, shared=
|
|
640
|
+
def __init__(self, transforms, prob=0, *, shared=True, **kwargs):
|
|
623
641
|
"""
|
|
624
642
|
|
|
625
643
|
Parameters
|
|
@@ -117,6 +117,29 @@ def returns_find(flag, returned, returns):
|
|
|
117
117
|
return None
|
|
118
118
|
|
|
119
119
|
|
|
120
|
+
def returns_update(value, flag, returned, returns):
|
|
121
|
+
"""Find tensor corresponding to flag in returned structure"""
|
|
122
|
+
if returns is None:
|
|
123
|
+
if flag == 'output':
|
|
124
|
+
return value
|
|
125
|
+
else:
|
|
126
|
+
return None
|
|
127
|
+
if isinstance(returns, dict):
|
|
128
|
+
if flag in returns:
|
|
129
|
+
returned[flag] = value
|
|
130
|
+
return returned
|
|
131
|
+
elif isinstance(returns, (list, tuple)):
|
|
132
|
+
if flag in returns:
|
|
133
|
+
returned[returns.index(flag)] = value
|
|
134
|
+
return returned
|
|
135
|
+
else:
|
|
136
|
+
assert isinstance(returns, str)
|
|
137
|
+
if returns == flag:
|
|
138
|
+
return value
|
|
139
|
+
else:
|
|
140
|
+
return None
|
|
141
|
+
|
|
142
|
+
|
|
120
143
|
def flatstruct(x):
|
|
121
144
|
"""Flatten a nested structure of tensors"""
|
|
122
145
|
|
|
@@ -184,7 +184,7 @@ class ContrastLookupTransform(NonFinalTransform):
|
|
|
184
184
|
|
|
185
185
|
vmin, vmax = x.min(), x.max()
|
|
186
186
|
edges = torch.linspace(vmin, vmax, self.nk+1)
|
|
187
|
-
new_mu = torch.rand(self.nk) * (vmax - vmin) + vmin
|
|
187
|
+
new_mu = torch.rand(self.nk).to(x) * (vmax - vmin) + vmin
|
|
188
188
|
return self.LookupFinalTransform(
|
|
189
189
|
edges, new_mu, **self.get_prm()
|
|
190
190
|
).make_final(x, max_depth-1)
|