augmentrum 0.0.1__py3-none-any.whl

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 (42) hide show
  1. augmentrum/__init__.py +23 -0
  2. augmentrum/augmentation/__init__.py +32 -0
  3. augmentrum/augmentation/amplitude_scaling.py +170 -0
  4. augmentrum/augmentation/apodization.py +275 -0
  5. augmentrum/augmentation/artificial_peaks.py +334 -0
  6. augmentrum/augmentation/baseline_augmentation.py +544 -0
  7. augmentrum/augmentation/eddy_current.py +278 -0
  8. augmentrum/augmentation/gaussian_noise.py +211 -0
  9. augmentrum/augmentation/line_broadening.py +179 -0
  10. augmentrum/augmentation/phase_frequency.py +259 -0
  11. augmentrum/augmentation/residual_water.py +264 -0
  12. augmentrum/augmentation/spatial_augmentations.py +859 -0
  13. augmentrum/augmentation/spurious_echoes.py +378 -0
  14. augmentrum/augmentation/zero_fill.py +163 -0
  15. augmentrum/core/__init__.py +10 -0
  16. augmentrum/core/augmentrum.py +1172 -0
  17. augmentrum/core/base_module.py +423 -0
  18. augmentrum/core/dataset_utils.py +417 -0
  19. augmentrum/core/nifti_mrs_plus.py +1079 -0
  20. augmentrum/core/pipeline.py +358 -0
  21. augmentrum/dataset/brainbeats.py +537 -0
  22. augmentrum/dataset/cows.py +302 -0
  23. augmentrum/dataset/fmrsinpain.py +208 -0
  24. augmentrum/processing/bicubic_interpolator.py +296 -0
  25. augmentrum/processing/nifti_raw_processor.py +389 -0
  26. augmentrum/processing/tricubic_interpolator.py +293 -0
  27. augmentrum/processing/utils.py +414 -0
  28. augmentrum/resources/__init__.py +14 -0
  29. augmentrum/resources/scans/__init__.py +0 -0
  30. augmentrum/sampling/coil_average_sampler.py +274 -0
  31. augmentrum/sampling/kspace_reconstructor.py +275 -0
  32. augmentrum/sampling/kspace_sampling.py +2562 -0
  33. augmentrum/sampling/subject_splitter.py +131 -0
  34. augmentrum/utils/__init__.py +10 -0
  35. augmentrum/utils/philips.py +90 -0
  36. augmentrum/utils/plotting.py +651 -0
  37. augmentrum/utils/tensor_ops.py +203 -0
  38. augmentrum-0.0.1.dist-info/METADATA +189 -0
  39. augmentrum-0.0.1.dist-info/RECORD +42 -0
  40. augmentrum-0.0.1.dist-info/WHEEL +5 -0
  41. augmentrum-0.0.1.dist-info/licenses/LICENSE +202 -0
  42. augmentrum-0.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,131 @@
1
+ ####################################################################################################
2
+ # subject_splitter.py #
3
+ ####################################################################################################
4
+ # #
5
+ # Authors: J. P. Merkofer (j.p.merkofer@tue.nl) #
6
+ # #
7
+ # Created: 2025-10-07 #
8
+ # #
9
+ # Purpose: Implements SubjectSplitter for reproducible subject-wise train/val/test splits. #
10
+ # Supports stratified or random splitting modes. #
11
+ # #
12
+ ####################################################################################################
13
+
14
+
15
+ #*************#
16
+ # imports #
17
+ #*************#
18
+ import torch
19
+
20
+
21
+ #**************************************************************************************************#
22
+ # Class SubjectSampler #
23
+ #**************************************************************************************************#
24
+ # #
25
+ # Simplistic subject splitter for train/val/test splits. Supports random splitting. #
26
+ # #
27
+ #**************************************************************************************************#
28
+ class SubjectSplitter:
29
+ """
30
+ Splits subjects into train/val/test sets.
31
+
32
+ Works with any backend (NIfTI_MRS_Plus, lists, or raw data).
33
+ Returns splits in the same format as input.
34
+ """
35
+
36
+ def __init__(self, data, water=None, seed=0, val_frac=0.1, test_frac=0.1):
37
+ """
38
+ Initialization.
39
+
40
+ Args:
41
+ data: Input data (NIfTI_MRS_Plus, list, or other).
42
+ water: Water reference data (same format as data), optional.
43
+ seed (int): Random seed for reproducibility.
44
+ val_frac (float): Fraction of data for validation set.
45
+ test_frac (float): Fraction of data for test set.
46
+ """
47
+ self.data = data
48
+ self.water = water
49
+ self.val_frac = val_frac
50
+ self.test_frac = test_frac
51
+ self.seed = seed
52
+ torch.manual_seed(seed)
53
+
54
+ def __call__(self, **kwargs):
55
+ """
56
+ Perform the split and return the dictionary of splits.
57
+ """
58
+ return self.split()
59
+
60
+ def split(self):
61
+ """
62
+ Splits subjects into train/val/test sets.
63
+
64
+ Handles NIfTI_MRS_Plus with any backend by converting to list,
65
+ splitting, and optionally converting back.
66
+
67
+ Returns:
68
+ dict: Dictionary with 'train', 'val', and 'test' keys.
69
+ Each value is a tuple of (data, water).
70
+ """
71
+ # Import here to avoid circular imports
72
+ from augmentrum.core import NIfTI_MRS_Plus
73
+
74
+ # Store original type and backend for later reconstruction
75
+ is_nifti_plus = isinstance(self.data, NIfTI_MRS_Plus)
76
+ original_backend = self.data.backend if is_nifti_plus else None
77
+ original_volatile = self.data.volatile if is_nifti_plus else False
78
+
79
+ # Convert to list for splitting
80
+ if is_nifti_plus:
81
+ data_list = self.data.to_nifti_list()
82
+ else:
83
+ data_list = self.data if isinstance(self.data, list) else list(self.data)
84
+
85
+ if self.water is not None:
86
+ if isinstance(self.water, NIfTI_MRS_Plus):
87
+ water_list = self.water.to_nifti_list()
88
+ else:
89
+ water_list = self.water if isinstance(self.water, list) else list(self.water)
90
+
91
+ # Validate that water_list and data_list have the same length
92
+ if len(water_list) != len(data_list):
93
+ raise ValueError(
94
+ f"Mismatch between data and water lists: "
95
+ f"data has {len(data_list)} subjects but water has {len(water_list)} subjects. "
96
+ f"They must have the same length."
97
+ )
98
+ else:
99
+ water_list = None
100
+
101
+ # Perform random split
102
+ idxs = torch.randperm(len(data_list)).tolist()
103
+ n_total = len(idxs)
104
+ n_test = int(n_total * self.test_frac)
105
+ n_val = int(n_total * self.val_frac)
106
+
107
+ def get_lists(sel):
108
+ data_sel = [data_list[i] for i in sel]
109
+ water_sel = [water_list[i] for i in sel] if water_list is not None else None
110
+
111
+ # Optionally convert back to NIfTI_MRS_Plus with original backend
112
+ if is_nifti_plus and len(data_sel) > 0:
113
+ data_sel = NIfTI_MRS_Plus(
114
+ nifti_list=data_sel,
115
+ backend=original_backend,
116
+ volatile=original_volatile
117
+ )
118
+ if water_sel is not None:
119
+ water_sel = NIfTI_MRS_Plus(
120
+ nifti_list=water_sel,
121
+ backend=original_backend,
122
+ volatile=original_volatile
123
+ )
124
+
125
+ return data_sel, water_sel
126
+
127
+ return {
128
+ 'train': get_lists(idxs[n_test + n_val:]),
129
+ 'val': get_lists(idxs[n_test:n_test + n_val]),
130
+ 'test': get_lists(idxs[:n_test]),
131
+ }
@@ -0,0 +1,10 @@
1
+ """
2
+ Utility modules for Augmentrum.
3
+ """
4
+
5
+ from augmentrum.utils.tensor_ops import ( # noqa: F401
6
+ fft, ifft, fftshift, ifftshift, to_numpy, match_backend,
7
+ )
8
+
9
+ __all__ = ['fft', 'ifft', 'fftshift', 'ifftshift', 'to_numpy', 'match_backend']
10
+
@@ -0,0 +1,90 @@
1
+ ####################################################################################################
2
+ # philips.py #
3
+ ####################################################################################################
4
+ # #
5
+ # Authors: J. P. Merkofer (j.p.merkofer@tue.nl) #
6
+ # #
7
+ # Created: 20/06/22 #
8
+ # #
9
+ # Purpose: Contains various Philips specific utils. #
10
+ # #
11
+ ####################################################################################################
12
+
13
+
14
+ #*************#
15
+ # imports #
16
+ #*************#
17
+ import numpy as np
18
+
19
+
20
+ #****************#
21
+ # definition #
22
+ #****************#
23
+ index_options = ['STD', 'REJ', 'PHC', 'FRC', 'NOI', 'NAV']
24
+
25
+ index_headers = ['typ', 'mix', 'dyn', 'card', 'echo', 'loca', 'chan',
26
+ 'extr1', 'extr2', 'kx', 'ky', 'kz', 'aver', 'sign',
27
+ 'rf', 'grad', 'enc', 'rtop', 'rr', 'size', 'offset']
28
+
29
+ indices = ['chan', 'aver', 'dyn', 'card', 'echo', 'loca', 'extr1', 'extr2']
30
+
31
+ defaults = {'chan': 'DIM_COIL',
32
+ 'aver': 'DIM_DYN',
33
+ 'dyn': 'DIM_DYN',
34
+ 'echo': 'DIM_INDIRECT_0'}
35
+
36
+
37
+ #***********************#
38
+ # read a .data file #
39
+ #***********************#
40
+ def read_Philips_data(data_file, df):
41
+ """
42
+ Reads a .data file with given .list data frame. Parts of the code are taken from:
43
+ https://github.com/wtclarke/spec2nii/blob/master/spec2nii/philips_data_list.py
44
+
45
+ @param data_file -- The path to the data file.
46
+ @param df -- The data frame obtained from the .list file.
47
+
48
+ @returns -- A dict containing the data.
49
+ """
50
+ with open(data_file, 'rb') as f:
51
+ raw = np.fromfile(f, dtype='<f4')
52
+ raw = raw[0::2] + 1j * raw[1::2]
53
+
54
+ data_types = df.typ.unique()
55
+ output_dict = {}
56
+ for tt in data_types:
57
+ curr_df = df.loc[df.typ == tt, :]
58
+ if tt == 'NOI':
59
+ # special simple case for NOI
60
+ spec_res = int(curr_df['size'].max() / 8)
61
+ ncha = curr_df['chan'].max() + 1
62
+ nloca = curr_df['loca'].max() + 1
63
+ output_dict[tt] = np.zeros((spec_res, ncha, nloca), dtype=np.complex128)
64
+ else:
65
+ n_mix = curr_df['mix'].max() + 1
66
+ # other types might use all the loops
67
+ for mix in range(n_mix):
68
+ curr_mix_df = curr_df.loc[curr_df.mix == mix, :]
69
+ shape = []
70
+ shape.append(int(curr_mix_df['size'].max() / 8))
71
+ for ind in indices:
72
+ shape.append(curr_mix_df[ind].max() + 1)
73
+ output_dict[f'{tt}_{mix}'] = np.zeros(shape, dtype=np.complex128)
74
+
75
+ # now extract data
76
+ offset = 0
77
+ for ind in range(df.shape[0]):
78
+ cdf = df.iloc[ind]
79
+ tt = cdf.typ
80
+ dsize = int(cdf['size'].max() / 8)
81
+ if tt == 'NOI':
82
+ output_dict[tt][:, cdf.chan, cdf.loca] = raw[offset:(offset + dsize)]
83
+ else:
84
+ mix = cdf.mix
85
+ ind = [cdf[ii] for ii in indices]
86
+ ind = tuple([slice(None), ] + ind)
87
+ output_dict[f'{tt}_{mix}'][ind] = raw[offset:(offset + dsize)]
88
+ offset += dsize
89
+
90
+ return output_dict