Skip to content
Merged
Show file tree
Hide file tree
Changes from 66 commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
52947cc
add test for scale intensity range percentiles transform
ziw-liu Aug 19, 2025
0ac55f6
randomize test data
ziw-liu Aug 19, 2025
12c0d3a
add decollate
ziw-liu Aug 20, 2025
ea36a11
detect leading slashes
ziw-liu Aug 20, 2025
cdee3f4
configurable label column
ziw-liu Aug 20, 2025
e6024cd
fix typo
ziw-liu Aug 20, 2025
cdeb907
configurable example shape
ziw-liu Aug 20, 2025
2a90c69
type hint
ziw-liu Aug 20, 2025
1061fbf
fix example array
ziw-liu Aug 20, 2025
91984c5
format
ziw-liu Aug 20, 2025
e6874e8
auto-align validation fov names
ziw-liu Aug 21, 2025
b56b334
Adding some batched transforms for MAE training (#284)
ritvikvasan Aug 24, 2025
cca6299
wip: random crop
ziw-liu Aug 24, 2025
0fedf2b
Merge remote-tracking branch 'origin/batched-transforms' into batched…
ziw-liu Aug 24, 2025
4de0c6f
format
ziw-liu Aug 24, 2025
9de5dc9
use gather operation for cropping
ziw-liu Aug 24, 2025
6e7ee27
register batched random crop
ziw-liu Aug 24, 2025
482eee7
use unfold and bench
ziw-liu Aug 24, 2025
16e07c7
add dict version for random spatial crop
ziw-liu Aug 25, 2025
2b0b3eb
lint
ziw-liu Aug 25, 2025
b0f5d50
benchmark crop
ziw-liu Aug 26, 2025
e4faf05
rename flip file
ziw-liu Aug 26, 2025
2255b6c
use tensorstore to stack
ziw-liu Aug 26, 2025
69be4bc
rename in register
ziw-liu Aug 26, 2025
17d0f79
add notebook to showcase transforms
ziw-liu Aug 26, 2025
eb20a13
batched center crop
ziw-liu Aug 26, 2025
722cf86
batched gaussian noise
ziw-liu Aug 27, 2025
e1f22e1
test and add to notebook
ziw-liu Aug 27, 2025
b5b92ec
fix docstring
ziw-liu Aug 27, 2025
c82993a
test random flip
ziw-liu Aug 27, 2025
95e6451
add map version of batched gaussian noise
ziw-liu Aug 27, 2025
339b50b
fix noise scaling and shifting
ziw-liu Aug 27, 2025
7caec53
per-sample random flip
ziw-liu Aug 28, 2025
9edcc6f
fix gaussian blur
ziw-liu Aug 29, 2025
68fe3a6
rename blur to smooth to match monai
ziw-liu Aug 29, 2025
66453ec
update smoothing tests
ziw-liu Aug 29, 2025
70ca63a
sigma-based truncation
ziw-liu Aug 29, 2025
61f19e1
print timer results
ziw-liu Aug 30, 2025
3896e46
random adjust contrast
ziw-liu Aug 30, 2025
1f93b8f
wrap monai
ziw-liu Aug 30, 2025
d6cc1a3
random scale intensity
ziw-liu Aug 30, 2025
9c0890b
update tests
ziw-liu Aug 30, 2025
36912e9
allow final crop override
ziw-liu Sep 1, 2025
5f13966
add center crop to example
ziw-liu Sep 1, 2025
78c386a
remove redundant call method
ziw-liu Sep 1, 2025
879ed6e
check gamma value
ziw-liu Sep 1, 2025
ef00126
use batched center crop
ziw-liu Sep 2, 2025
ac3849f
fix import
ziw-liu Sep 2, 2025
f896d22
wip: fix gathering
ziw-liu Sep 2, 2025
a56e486
limit worker to 1
ziw-liu Sep 4, 2025
2811e4b
wip: execute augmentations in data hook
ziw-liu Sep 5, 2025
ef47733
use the full loop for profiling
ziw-liu Sep 5, 2025
f90d097
wip: update concat wrapper
ziw-liu Sep 5, 2025
79bfe7d
fix negative sampling
ziw-liu Sep 5, 2025
4e97fca
update tests
ziw-liu Sep 5, 2025
3d91a78
revert to use threads
ziw-liu Sep 5, 2025
824d988
cache tensorstore arrays
ziw-liu Sep 5, 2025
d21e9e0
update default num_workers
ziw-liu Sep 5, 2025
b601880
skip transforms for example array
ziw-liu Sep 5, 2025
5ded39d
relax flaky randomness test
ziw-liu Sep 6, 2025
8f1ec34
explicitly configure cache pool
ziw-liu Sep 9, 2025
97e70ee
use new iohub API
ziw-liu Sep 10, 2025
31bf164
only check cache when opening
ziw-liu Sep 10, 2025
781048d
Merge branch 'main' into batched-transforms
ziw-liu Sep 11, 2025
2aa1051
fix transform initialization
ziw-liu Sep 15, 2025
e230fbd
remove unecessary tipletdatamodule inits
edyoshikun Sep 16, 2025
236ab5f
explain num_workers in the docstring
ziw-liu Sep 16, 2025
f288bb9
Merge remote-tracking branch 'origin/batched-transforms' into batched…
ziw-liu Sep 16, 2025
81ece14
updating paths for profiling
edyoshikun Sep 16, 2025
4eb7802
fixed batch randintensityscale in the notebook
edyoshikun Sep 16, 2025
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
622 changes: 622 additions & 0 deletions examples/transforms/batched_transforms.ipynb

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ classifiers = [
"Programming Language :: Python :: 3.13",
]
dependencies = [
"iohub[tensorstore]>=0.2.2rc0",
"iohub[tensorstore]>=0.3.0a2",
"kornia",
"torch>=2.4.1",
"timm>=0.9.5",
Expand Down
2 changes: 2 additions & 0 deletions tests/data/test_triplet.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def test_datamodule_setup_fit(
assert fov_name not in exclude_fovs
assert len(all_tracks) == len_total
for batch in dm.train_dataloader():
dm.on_after_batch_transfer(batch, 0)
assert batch["anchor"].shape == (
batch_size,
len(channel_names),
Expand Down Expand Up @@ -95,6 +96,7 @@ def test_datamodule_z_window_size(
else:
expected_z_shape = z_window_size
for batch in dm.train_dataloader():
dm.on_after_batch_transfer(batch, 0)
assert batch["anchor"].shape == (
batch_size,
len(channel_names),
Expand Down
Empty file added tests/transforms/__init__.py
Empty file.
119 changes: 119 additions & 0 deletions tests/transforms/test_adjust_contrast.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import pytest
import torch
from monai.transforms import AdjustContrast, Compose

from viscy.transforms import BatchedRandAdjustContrast, BatchedRandAdjustContrastd


@pytest.mark.parametrize("ndim", [4, 5])
@pytest.mark.parametrize("prob", [0.0, 0.5, 1.0])
@pytest.mark.parametrize(
"device", ["cpu", "cuda"] if torch.cuda.is_available() else ["cpu"]
)
@pytest.mark.parametrize("compose", [True, False])
def test_batched_adjust_contrast(device, ndim, prob, compose):
img = torch.rand([16] + [2] * (ndim - 1), device=device) + 0.1
transform = BatchedRandAdjustContrast(prob=prob, gamma=(0.5, 2.0))
if compose:
transform = Compose([transform])
result = transform(img)
assert result.shape == img.shape
changed = ~torch.isclose(result, img, atol=1e-6).all(
dim=list(range(1, result.ndim))
)
if prob == 1.0:
assert changed.all()
elif prob == 0.5:
assert changed.any()
assert not changed.all()
elif prob == 0.0:
assert not changed.any()
assert result.device == img.device
if not compose:
repeat = transform(img, randomize=False)
assert torch.equal(result, repeat)


@pytest.mark.parametrize("gamma", [0.8, 1.5, (0.5, 2.0)])
@pytest.mark.parametrize("retain_stats", [True, False])
@pytest.mark.parametrize("invert_image", [True, False])
def test_batched_adjust_contrast_options(gamma, retain_stats, invert_image):
img = torch.rand(8, 1, 8, 8, 8) + 0.1
original_mean = img.mean()
original_std = img.std()

transform = BatchedRandAdjustContrast(
prob=1.0, gamma=gamma, retain_stats=retain_stats, invert_image=invert_image
)
result = transform(img)

assert result.shape == img.shape

if retain_stats:
assert torch.isclose(result.mean(), original_mean, atol=1e-5)
assert torch.isclose(result.std(), original_std, atol=1e-5)

if not (isinstance(gamma, (int, float)) and gamma == 1.0):
assert not torch.equal(result, img)


def test_batched_adjust_contrast_dict():
img = torch.rand([16, 1, 4, 8, 8]) + 0.1
data = {"a": img, "b": img.clone()}
transform = BatchedRandAdjustContrastd(keys=["a", "b"], prob=1.0, gamma=(0.5, 2.0))
result = transform(data)
assert not torch.equal(result["a"], img)
assert torch.equal(result["a"], result["b"])


def test_batched_adjust_contrast_gamma_validation():
with pytest.raises(ValueError):
BatchedRandAdjustContrast(gamma=0.0)

with pytest.raises(ValueError):
BatchedRandAdjustContrast(gamma=-0.5)

with pytest.raises(ValueError):
BatchedRandAdjustContrast(gamma=(0.5, 2.0, 1.0))

with pytest.raises(ValueError):
BatchedRandAdjustContrast(gamma=(-0.1, 2.0))

BatchedRandAdjustContrast(gamma=0.1)
BatchedRandAdjustContrast(gamma=0.3)
BatchedRandAdjustContrast(gamma=1.5)
BatchedRandAdjustContrast(gamma=(0.2, 0.8))
BatchedRandAdjustContrast(gamma=(0.5, 2.0))


@pytest.mark.parametrize("gamma_value", [0.2, 0.5, 0.8, 1.2, 2.0])
@pytest.mark.parametrize("retain_stats", [True, False])
@pytest.mark.parametrize("invert_image", [True, False])
def test_batched_adjust_contrast_vs_monai(gamma_value, retain_stats, invert_image):
torch.manual_seed(42)

batch_size = 4
img_batch = torch.rand(batch_size, 1, 8, 8, 8) + 0.1

batched_transform = BatchedRandAdjustContrast(
prob=1.0,
gamma=(gamma_value, gamma_value),
retain_stats=retain_stats,
invert_image=invert_image,
)

torch.manual_seed(42)
batched_result = batched_transform(img_batch)

monai_transform = AdjustContrast(
gamma=gamma_value, retain_stats=retain_stats, invert_image=invert_image
)

monai_results = []
for i in range(batch_size):
individual_result = monai_transform(img_batch[i])
monai_results.append(individual_result)

monai_batch_result = torch.stack(monai_results)

assert torch.allclose(batched_result, monai_batch_result, atol=1e-6, rtol=1e-5)
Loading