-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpreprocessing.py
More file actions
147 lines (117 loc) · 4.86 KB
/
Copy pathpreprocessing.py
File metadata and controls
147 lines (117 loc) · 4.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
"""
Supplementary code: intensity normalization of full-time and fast-acquisition images.
Self-contained script. Requires only numpy and SimpleITK:
pip install numpy SimpleITK
"""
import numpy as np
import SimpleITK as sitk
def CopyInfo(ReferenceImage, UpdatingImage, origin=True, spacing=True, direction=True):
"""Copy spatial metadata (origin/spacing/direction) from a reference image."""
if isinstance(ReferenceImage, str):
ReferenceImage = sitk.ReadImage(ReferenceImage)
if isinstance(UpdatingImage, str):
UpdatingImage = sitk.ReadImage(UpdatingImage)
UpdatedImage = UpdatingImage
if origin:
UpdatedImage.SetOrigin(ReferenceImage.GetOrigin())
if spacing:
UpdatedImage.SetSpacing(ReferenceImage.GetSpacing())
if direction:
UpdatedImage.SetDirection(ReferenceImage.GetDirection())
return UpdatedImage
def sitk_percentile(image, percentile: float = 99.0, segment=None):
"""
Compute the percentile of an image, optionally within a segmentation mask.
Parameters:
image: str, sitk.Image, or np.ndarray
percentile: float, default 99.0
segment: str, sitk.Image, or np.ndarray (optional mask)
Returns:
tuple: (percentile excluding zeros, percentile including zeros)
"""
# Convert input to numpy array
if isinstance(image, str):
image_array = sitk.GetArrayFromImage(sitk.ReadImage(image))
elif isinstance(image, sitk.Image):
image_array = sitk.GetArrayFromImage(image)
elif isinstance(image, np.ndarray):
image_array = image
else:
raise TypeError("Image must be a path (str), sitk.Image, or numpy array.")
# Apply segmentation mask if provided
if segment is not None and segment != "none":
if isinstance(segment, str):
segment_array = sitk.GetArrayFromImage(sitk.ReadImage(segment))
elif isinstance(segment, sitk.Image):
segment_array = sitk.GetArrayFromImage(segment)
elif isinstance(segment, np.ndarray):
segment_array = segment
else:
raise TypeError("Segment must be a path (str), sitk.Image, or numpy array.")
image_array = image_array[segment_array != 0]
# Calculate percentiles
non_zero_percentile = np.percentile(image_array[image_array != 0], percentile)
with_zero_percentile = np.percentile(image_array, percentile)
return non_zero_percentile, with_zero_percentile
def sitk_rescale(image, input_min="image-min", input_max="image-max",
output_min: float = 0.0, output_max: float = 1.0):
"""
Rescale image intensities to a new range [output_min, output_max].
Returns both clipped and unclipped versions.
"""
if isinstance(image, str):
image = sitk.ReadImage(image)
array = sitk.GetArrayFromImage(image).astype(np.float32, copy=False)
if input_min == "image-min":
input_min = np.min(array)
if input_max == "image-max":
input_max = np.max(array)
# Perform rescaling
scale = (output_max - output_min) / (input_max - input_min)
array = (array - input_min) * scale + output_min
# Unclipped version
image_no_clip = sitk.GetImageFromArray(array)
image_no_clip = CopyInfo(ReferenceImage=image, UpdatingImage=image_no_clip)
# Clipped version
image_clip = sitk.GetImageFromArray(np.clip(array, output_min, output_max))
image_clip = CopyInfo(ReferenceImage=image, UpdatingImage=image_clip)
return image_clip, image_no_clip
# =============================================================================
# Normalization of full-time and fast-acquisition images
# =============================================================================
# Define file paths (update these with your actual paths)
ft_url = "path/to/fulltime_image.nii.gz" # Full-time image
fast_10_url = "path/to/fast_10_image.nii.gz"
fast_20_url = "path/to/fast_20_image.nii.gz"
fast_25_url = "path/to/fast_25_image.nii.gz"
fast_50_url = "path/to/fast_50_image.nii.gz"
# Normalize using the 99th percentile (excluding zeros) as the upper bound.
# sitk_rescale returns (clipped, unclipped); [1] selects the unclipped version.
ft_normalized = sitk_rescale(
ft_url,
input_min=0,
input_max=sitk_percentile(ft_url, percentile=99)[0],
)[1]
fast_normalized_10 = sitk_rescale(
fast_10_url,
input_min=0,
input_max=sitk_percentile(fast_10_url, percentile=99)[0],
)[1]
fast_normalized_20 = sitk_rescale(
fast_20_url,
input_min=0,
input_max=sitk_percentile(fast_20_url, percentile=99)[0],
)[1]
fast_normalized_25 = sitk_rescale(
fast_25_url,
input_min=0,
input_max=sitk_percentile(fast_25_url, percentile=99)[0],
)[1]
fast_normalized_50 = sitk_rescale(
fast_50_url,
input_min=0,
input_max=sitk_percentile(fast_50_url, percentile=99)[0],
)[1]
###
#writting the full time and fast-acquisition normalized images to disk.
###