batchgeneratorsv2 0.3.6__tar.gz → 0.3.7__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.
Files changed (65) hide show
  1. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/PKG-INFO +1 -1
  2. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/intensity/contrast.py +3 -1
  3. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/spatial/spatial.py +36 -3
  4. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2.egg-info/PKG-INFO +1 -1
  5. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2.egg-info/SOURCES.txt +1 -0
  6. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/pyproject.toml +1 -1
  7. batchgeneratorsv2-0.3.7/tests/test_contrast.py +42 -0
  8. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/LICENSE +0 -0
  9. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/benchmarks/__init__.py +0 -0
  10. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/benchmarks/bg_comparison/__init__.py +0 -0
  11. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/benchmarks/bg_comparison/nnUNet_pipeline_bg.py +0 -0
  12. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/benchmarks/bg_comparison/nnUNet_pipeline_here.py +0 -0
  13. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/benchmarks/unique_values.py +0 -0
  14. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/dataloading/__init__.py +0 -0
  15. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/helpers/__init__.py +0 -0
  16. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/helpers/fft_conv.py +0 -0
  17. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/helpers/scalar_type.py +0 -0
  18. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/__init__.py +0 -0
  19. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/base/__init__.py +0 -0
  20. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/base/basic_transform.py +0 -0
  21. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/intensity/__init__.py +0 -0
  22. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/intensity/brightness.py +0 -0
  23. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/intensity/gamma.py +0 -0
  24. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/intensity/gaussian_noise.py +0 -0
  25. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/intensity/inversion.py +0 -0
  26. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/intensity/random_clip.py +0 -0
  27. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/local/__init__.py +0 -0
  28. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/local/brightness_gradient.py +0 -0
  29. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/local/local_contrast.py +0 -0
  30. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/local/local_gamma.py +0 -0
  31. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/local/local_smoothing.py +0 -0
  32. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/local/local_transform.py +0 -0
  33. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/nnunet/__init__.py +0 -0
  34. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/nnunet/random_binary_operator.py +0 -0
  35. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/nnunet/remove_connected_components.py +0 -0
  36. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/nnunet/seg_to_onehot.py +0 -0
  37. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/noise/__init__.py +0 -0
  38. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/noise/blank_rectangle.py +0 -0
  39. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/noise/gaussian_blur.py +0 -0
  40. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/noise/median_filter.py +0 -0
  41. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/noise/rician.py +0 -0
  42. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/noise/sharpen.py +0 -0
  43. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/spatial/__init__.py +0 -0
  44. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/spatial/channel_misalignment.py +0 -0
  45. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/spatial/low_resolution.py +0 -0
  46. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/spatial/mirroring.py +0 -0
  47. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/spatial/rot90.py +0 -0
  48. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/spatial/transpose.py +0 -0
  49. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/utils/__init__.py +0 -0
  50. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/utils/compose.py +0 -0
  51. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/utils/cropping.py +0 -0
  52. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/utils/deep_supervision_downsampling.py +0 -0
  53. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/utils/move_channels.py +0 -0
  54. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/utils/nnunet_masking.py +0 -0
  55. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/utils/pseudo2d.py +0 -0
  56. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/utils/random.py +0 -0
  57. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/utils/remove_label.py +0 -0
  58. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2/transforms/utils/seg_to_regions.py +0 -0
  59. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2.egg-info/dependency_links.txt +0 -0
  60. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2.egg-info/requires.txt +0 -0
  61. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/batchgeneratorsv2.egg-info/top_level.txt +0 -0
  62. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/readme.md +0 -0
  63. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/setup.cfg +0 -0
  64. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/setup.py +0 -0
  65. {batchgeneratorsv2-0.3.6 → batchgeneratorsv2-0.3.7}/tests/test_seg_sampling.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: batchgeneratorsv2
3
- Version: 0.3.6
3
+ Version: 0.3.7
4
4
  Summary: Batchgenerators but better
5
5
  Author: Helmholtz Imaging Applied Computer Vision Lab
6
6
  Author-email: Fabian Isensee <f.isensee@dkfz-heidelberg.de>
@@ -14,7 +14,9 @@ class BGContrast():
14
14
  factor = self.contrast_range()
15
15
  else:
16
16
  if np.random.random() < 0.5 and self.contrast_range[0] < 1:
17
- factor = np.random.uniform(self.contrast_range[0], 1)
17
+ factor = np.random.uniform(self.contrast_range[0], min(1, self.contrast_range[1]))
18
+ elif self.contrast_range[1] <= 1:
19
+ factor = np.random.uniform(self.contrast_range[0], self.contrast_range[1])
18
20
  else:
19
21
  factor = np.random.uniform(max(self.contrast_range[0], 1), self.contrast_range[1])
20
22
  return factor
@@ -5,7 +5,7 @@ from typing import Tuple, List, Union
5
5
  import numpy as np
6
6
  import pandas as pd
7
7
  import torch
8
- from scipy.ndimage import fourier_gaussian
8
+ from scipy.ndimage import find_objects, fourier_gaussian
9
9
  from torch.nn.functional import grid_sample
10
10
 
11
11
  from batchgeneratorsv2.helpers.scalar_type import RandomScalar, sample_scalar
@@ -462,14 +462,21 @@ class SpatialTransform(BasicTransform):
462
462
  nn_c = _nearest()[c]
463
463
  nn_score = torch.full(nn_c.shape, float('-inf'), dtype=torch.float16)
464
464
  is_nn = torch.empty(nn_c.shape, dtype=torch.bool)
465
+ # A label can only be the nearest neighbour's inside the bounding box of its nearest
466
+ # neighbour voxels, so that is all the bookkeeping has to look at: typically a few % of
467
+ # the patch per label instead of all of it. One pass over nn_c finds every box.
468
+ nn_boxes = _label_boxes(nn_c, int(labels[-1]))
465
469
  else:
466
470
  nn_c = None
467
471
  better = torch.empty(tuple(self.patch_size), dtype=torch.bool)
468
472
  for u in labels:
469
473
  cur = _score(u)
470
474
  if nn_c is not None:
471
- torch.eq(nn_c, u, out=is_nn)
472
- torch.where(is_nn, cur, nn_score, out=nn_score)
475
+ box = _label_box(nn_boxes, u)
476
+ if box is not None:
477
+ is_nn_b, nn_score_b = is_nn[box], nn_score[box]
478
+ torch.eq(nn_c[box], u, out=is_nn_b)
479
+ torch.where(is_nn_b, cur[box], nn_score_b, out=nn_score_b)
473
480
  if best_val is None:
474
481
  best_val = cur
475
482
  result_seg[c] = u.item()
@@ -498,6 +505,32 @@ class SpatialTransform(BasicTransform):
498
505
  raise NotImplementedError
499
506
 
500
507
 
508
+ def _label_boxes(labels: torch.Tensor, max_label: int):
509
+ """
510
+ {label: tuple of slices}, the bounding box of every positive label in an integer label map whose largest
511
+ label is max_label, from one pass over it (scipy's find_objects). Labels <= 0 and labels that do not occur
512
+ have no entry. None where that does not apply - float or bool label maps, tensors not on the CPU, or label
513
+ values so large (instance ids, say) that find_objects' list of max_label entries would cost more than it
514
+ saves: callers then use the whole volume.
515
+ """
516
+ if (labels.device.type != 'cpu' or labels.dtype.is_floating_point or labels.dtype == torch.bool
517
+ or max_label > 65535):
518
+ return None
519
+ return {i + 1: b for i, b in enumerate(find_objects(labels.numpy(), max_label=max(max_label, 1)))
520
+ if b is not None}
521
+
522
+
523
+ def _label_box(boxes, u):
524
+ """
525
+ Where label u can occur according to _label_boxes: its box, the whole volume (no boxes, or u <= 0, which
526
+ find_objects does not report), or None if it does not occur at all.
527
+ """
528
+ u = int(u)
529
+ if boxes is None or u <= 0:
530
+ return (slice(None),)
531
+ return boxes.get(u)
532
+
533
+
501
534
  def create_affine_matrix_3d(rotation_angles, scaling_factors):
502
535
  # Rotation matrices for each axis
503
536
  Rx = np.array([[1, 0, 0],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: batchgeneratorsv2
3
- Version: 0.3.6
3
+ Version: 0.3.7
4
4
  Summary: Batchgenerators but better
5
5
  Author: Helmholtz Imaging Applied Computer Vision Lab
6
6
  Author-email: Fabian Isensee <f.isensee@dkfz-heidelberg.de>
@@ -59,4 +59,5 @@ batchgeneratorsv2/transforms/utils/pseudo2d.py
59
59
  batchgeneratorsv2/transforms/utils/random.py
60
60
  batchgeneratorsv2/transforms/utils/remove_label.py
61
61
  batchgeneratorsv2/transforms/utils/seg_to_regions.py
62
+ tests/test_contrast.py
62
63
  tests/test_seg_sampling.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "batchgeneratorsv2"
3
- version = "0.3.6"
3
+ version = "0.3.7"
4
4
  requires-python = ">=3.9"
5
5
  description = "Batchgenerators but better"
6
6
  readme = "readme.md"
@@ -0,0 +1,42 @@
1
+ import unittest
2
+ from itertools import product
3
+
4
+ import numpy as np
5
+
6
+ from batchgeneratorsv2.transforms.intensity.contrast import BGContrast
7
+
8
+
9
+ class TestBGContrast(unittest.TestCase):
10
+ """
11
+ Ranges that end at or below one must be sampled from the range, as in batchgenerators' contrast, gamma and scale
12
+ sampling. A range ending at one used to return exactly one for half of the draws.
13
+ """
14
+
15
+ def setUp(self):
16
+ self.addCleanup(np.random.set_state, np.random.get_state())
17
+
18
+ def test_ranges_up_to_one_are_respected(self):
19
+ for value_range, seed in product(((0.7, 0.9), (0.8, 0.8), (0.7, 1)), range(50)):
20
+ with self.subTest(value_range=value_range, seed=seed):
21
+ np.random.seed(seed)
22
+ factor = BGContrast(value_range)()
23
+ self.assertGreaterEqual(factor, value_range[0])
24
+ self.assertLessEqual(factor, value_range[1])
25
+ # uniform never returns its upper bound, so a factor of exactly one comes from the old upper branch
26
+ self.assertLess(factor, 1)
27
+
28
+ def test_number_of_draws_is_unchanged(self):
29
+ # a branch choice and the factor
30
+ for value_range in ((0.7, 0.9), (0.8, 0.8), (0.75, 1.25), (0.7, 1.5), (0.5, 2), (1.1, 1.5), (0.7, 1), (1, 1)):
31
+ with self.subTest(value_range=value_range):
32
+ expected = np.random.RandomState(0)
33
+ expected.random_sample(2)
34
+ np.random.seed(0)
35
+ BGContrast(value_range)()
36
+ actual_state, expected_state = np.random.get_state(), expected.get_state()
37
+ np.testing.assert_array_equal(actual_state[1], expected_state[1])
38
+ self.assertEqual(actual_state[2:], expected_state[2:])
39
+
40
+
41
+ if __name__ == '__main__':
42
+ unittest.main()