dicube 0.1.4__cp312-cp312-macosx_11_0_arm64.whl → 0.2.2__cp312-cp312-macosx_11_0_arm64.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.
- dicube/__init__.py +49 -15
- dicube/core/image.py +6 -6
- dicube/core/io.py +75 -21
- dicube/core/pixel_header.py +50 -47
- dicube/dicom/dcb_streaming.py +56 -58
- dicube/dicom/dicom_io.py +16 -16
- dicube/storage/dcb_file.py +68 -49
- dicube/storage/pixel_utils.py +151 -33
- {dicube-0.1.4.dist-info → dicube-0.2.2.dist-info}/METADATA +2 -1
- {dicube-0.1.4.dist-info → dicube-0.2.2.dist-info}/RECORD +11 -11
- {dicube-0.1.4.dist-info → dicube-0.2.2.dist-info}/WHEEL +0 -0
dicube/__init__.py
CHANGED
@@ -39,27 +39,47 @@ except PackageNotFoundError:
|
|
39
39
|
# editable install / source tree
|
40
40
|
__version__ = "0.1.0+unknown"
|
41
41
|
|
42
|
+
# Default to the number of CPU cores, but cap at 8 threads to avoid excessive resource usage
|
43
|
+
# Fall back to 4 if cpu_count() returns None (which can happen in some environments)
|
44
|
+
_num_threads = 4
|
45
|
+
|
46
|
+
def get_num_threads() -> int:
|
47
|
+
"""Get the global number of threads for parallel processing.
|
48
|
+
|
49
|
+
Returns:
|
50
|
+
int: Current number of threads setting.
|
51
|
+
"""
|
52
|
+
global _num_threads
|
53
|
+
return _num_threads
|
54
|
+
|
55
|
+
def set_num_threads(num_threads: int) -> None:
|
56
|
+
"""Set the global number of threads for parallel processing.
|
57
|
+
|
58
|
+
Args:
|
59
|
+
num_threads (int): Number of threads for parallel processing tasks.
|
60
|
+
"""
|
61
|
+
global _num_threads
|
62
|
+
if num_threads < 1:
|
63
|
+
raise ValueError("Number of threads must be at least 1")
|
64
|
+
_num_threads = num_threads
|
65
|
+
|
42
66
|
# Top-level convenience methods
|
43
|
-
def load(file_path: str
|
67
|
+
def load(file_path: str) -> DicomCubeImage:
|
44
68
|
"""Load a DicomCubeImage from a file.
|
45
69
|
|
46
70
|
Args:
|
47
71
|
file_path (str): Path to the input file.
|
48
|
-
num_threads (int): Number of parallel decoding threads. Defaults to 4.
|
49
|
-
**kwargs: Additional parameters passed to the underlying reader.
|
50
72
|
|
51
73
|
Returns:
|
52
74
|
DicomCubeImage: The loaded image object.
|
53
75
|
"""
|
54
|
-
return DicomCubeImageIO.load(file_path
|
76
|
+
return DicomCubeImageIO.load(file_path)
|
55
77
|
|
56
78
|
|
57
79
|
def save(
|
58
80
|
image: DicomCubeImage,
|
59
81
|
file_path: str,
|
60
82
|
file_type: str = "s",
|
61
|
-
num_threads: int = 4,
|
62
|
-
**kwargs
|
63
83
|
) -> None:
|
64
84
|
"""Save a DicomCubeImage to a file.
|
65
85
|
|
@@ -68,16 +88,13 @@ def save(
|
|
68
88
|
file_path (str): Output file path.
|
69
89
|
file_type (str): File type, "s" (speed priority), "a" (compression priority),
|
70
90
|
or "l" (lossy compression). Defaults to "s".
|
71
|
-
num_threads (int): Number of parallel encoding threads. Defaults to 4.
|
72
|
-
**kwargs: Additional parameters passed to the underlying writer.
|
73
91
|
"""
|
74
|
-
return DicomCubeImageIO.save(image, file_path, file_type
|
92
|
+
return DicomCubeImageIO.save(image, file_path, file_type)
|
75
93
|
|
76
94
|
|
77
95
|
def load_from_dicom_folder(
|
78
96
|
folder_path: str,
|
79
97
|
sort_method: SortMethod = SortMethod.INSTANCE_NUMBER_ASC,
|
80
|
-
**kwargs
|
81
98
|
) -> DicomCubeImage:
|
82
99
|
"""Load a DicomCubeImage from a DICOM folder.
|
83
100
|
|
@@ -90,10 +107,10 @@ def load_from_dicom_folder(
|
|
90
107
|
Returns:
|
91
108
|
DicomCubeImage: The loaded image object.
|
92
109
|
"""
|
93
|
-
return DicomCubeImageIO.load_from_dicom_folder(folder_path, sort_method
|
110
|
+
return DicomCubeImageIO.load_from_dicom_folder(folder_path, sort_method)
|
94
111
|
|
95
112
|
|
96
|
-
def load_from_nifti(file_path: str
|
113
|
+
def load_from_nifti(file_path: str) -> DicomCubeImage:
|
97
114
|
"""Load a DicomCubeImage from a NIfTI file.
|
98
115
|
|
99
116
|
Args:
|
@@ -103,24 +120,38 @@ def load_from_nifti(file_path: str, **kwargs) -> DicomCubeImage:
|
|
103
120
|
Returns:
|
104
121
|
DicomCubeImage: The loaded image object.
|
105
122
|
"""
|
106
|
-
return DicomCubeImageIO.load_from_nifti(file_path
|
123
|
+
return DicomCubeImageIO.load_from_nifti(file_path)
|
107
124
|
|
108
125
|
|
109
126
|
def save_to_dicom_folder(
|
110
127
|
image: DicomCubeImage,
|
111
128
|
folder_path: str,
|
112
|
-
**kwargs
|
113
129
|
) -> None:
|
114
130
|
"""Save a DicomCubeImage as a DICOM folder.
|
115
131
|
|
116
132
|
Args:
|
117
133
|
image (DicomCubeImage): The image object to save.
|
118
134
|
folder_path (str): Output directory path.
|
119
|
-
**kwargs: Additional parameters.
|
120
135
|
"""
|
121
136
|
return DicomCubeImageIO.save_to_dicom_folder(image, folder_path)
|
122
137
|
|
123
138
|
|
139
|
+
def save_to_nifti(
|
140
|
+
image: DicomCubeImage,
|
141
|
+
file_path: str,
|
142
|
+
) -> None:
|
143
|
+
"""Save a DicomCubeImage as a NIfTI file.
|
144
|
+
|
145
|
+
Args:
|
146
|
+
image (DicomCubeImage): The image object to save.
|
147
|
+
file_path (str): Output file path.
|
148
|
+
|
149
|
+
Raises:
|
150
|
+
ImportError: When nibabel is not installed.
|
151
|
+
"""
|
152
|
+
return DicomCubeImageIO.save_to_nifti(image, file_path)
|
153
|
+
|
154
|
+
|
124
155
|
__all__ = [
|
125
156
|
"DicomCubeImage",
|
126
157
|
"DicomMeta",
|
@@ -135,6 +166,9 @@ __all__ = [
|
|
135
166
|
"load_from_dicom_folder",
|
136
167
|
"load_from_nifti",
|
137
168
|
"save_to_dicom_folder",
|
169
|
+
"save_to_nifti",
|
170
|
+
"set_num_threads",
|
171
|
+
"get_num_threads",
|
138
172
|
# IO class (for direct use if needed)
|
139
173
|
"DicomCubeImageIO",
|
140
174
|
]
|
dicube/core/image.py
CHANGED
@@ -35,7 +35,7 @@ class DicomCubeImage:
|
|
35
35
|
pixel_header (PixelDataHeader): Pixel data header containing metadata about the image pixels.
|
36
36
|
dicom_meta (DicomMeta, optional): DICOM metadata associated with the image.
|
37
37
|
space (Space, optional): Spatial information describing the image dimensions and orientation.
|
38
|
-
dicom_status (
|
38
|
+
dicom_status (DicomStatus): DICOM status enumeration. Defaults to DicomStatus.CONSISTENT.
|
39
39
|
"""
|
40
40
|
|
41
41
|
def __init__(
|
@@ -44,7 +44,7 @@ class DicomCubeImage:
|
|
44
44
|
pixel_header: PixelDataHeader,
|
45
45
|
dicom_meta: Optional[DicomMeta] = None,
|
46
46
|
space: Optional[Space] = None,
|
47
|
-
dicom_status:
|
47
|
+
dicom_status: DicomStatus = DicomStatus.CONSISTENT,
|
48
48
|
):
|
49
49
|
"""Initialize a DicomCubeImage instance.
|
50
50
|
|
@@ -226,13 +226,13 @@ class DicomCubeImage:
|
|
226
226
|
meta.set_shared_item(CommonTags.PixelRepresentation, 0)
|
227
227
|
|
228
228
|
# Rescale Information from pixel_header
|
229
|
-
if self.pixel_header.
|
229
|
+
if self.pixel_header.RescaleSlope is not None:
|
230
230
|
meta.set_shared_item(
|
231
|
-
CommonTags.RescaleSlope, float(self.pixel_header.
|
231
|
+
CommonTags.RescaleSlope, float(self.pixel_header.RescaleSlope)
|
232
232
|
)
|
233
|
-
if self.pixel_header.
|
233
|
+
if self.pixel_header.RescaleIntercept is not None:
|
234
234
|
meta.set_shared_item(
|
235
|
-
CommonTags.RescaleIntercept, float(self.pixel_header.
|
235
|
+
CommonTags.RescaleIntercept, float(self.pixel_header.RescaleIntercept)
|
236
236
|
)
|
237
237
|
|
238
238
|
def init_meta(
|
dicube/core/io.py
CHANGED
@@ -16,7 +16,7 @@ from ..dicom import (
|
|
16
16
|
)
|
17
17
|
from ..dicom.dicom_io import save_to_dicom_folder
|
18
18
|
from ..storage.dcb_file import DcbSFile, DcbFile, DcbAFile, DcbLFile
|
19
|
-
from ..storage.pixel_utils import derive_pixel_header_from_array
|
19
|
+
from ..storage.pixel_utils import derive_pixel_header_from_array, determine_optimal_nifti_dtype
|
20
20
|
from .pixel_header import PixelDataHeader
|
21
21
|
|
22
22
|
from ..validation import (
|
@@ -52,7 +52,6 @@ class DicomCubeImageIO:
|
|
52
52
|
image: "DicomCubeImage",
|
53
53
|
file_path: str,
|
54
54
|
file_type: str = "s",
|
55
|
-
num_threads: int = 4,
|
56
55
|
) -> None:
|
57
56
|
"""Save DicomCubeImage to a file.
|
58
57
|
|
@@ -61,7 +60,6 @@ class DicomCubeImageIO:
|
|
61
60
|
file_path (str): Output file path.
|
62
61
|
file_type (str): File type, "s" (speed priority), "a" (compression priority),
|
63
62
|
or "l" (lossy compression). Defaults to "s".
|
64
|
-
num_threads (int): Number of parallel encoding threads. Defaults to 4.
|
65
63
|
|
66
64
|
Raises:
|
67
65
|
InvalidCubeFileError: If the file_type is not supported.
|
@@ -69,7 +67,6 @@ class DicomCubeImageIO:
|
|
69
67
|
# Validate required parameters
|
70
68
|
validate_not_none(image, "image", "save operation", DataConsistencyError)
|
71
69
|
validate_string_not_empty(file_path, "file_path", "save operation", InvalidCubeFileError)
|
72
|
-
validate_numeric_range(num_threads, "num_threads", min_value=1, context="save operation")
|
73
70
|
|
74
71
|
# Validate file_type parameter
|
75
72
|
if file_type not in ("s", "a", "l"):
|
@@ -82,6 +79,7 @@ class DicomCubeImageIO:
|
|
82
79
|
|
83
80
|
try:
|
84
81
|
# Choose appropriate writer based on file type
|
82
|
+
# The writer will automatically ensure correct file extension
|
85
83
|
if file_type == "s":
|
86
84
|
writer = DcbSFile(file_path, mode="w")
|
87
85
|
elif file_type == "a":
|
@@ -89,14 +87,16 @@ class DicomCubeImageIO:
|
|
89
87
|
elif file_type == "l":
|
90
88
|
writer = DcbLFile(file_path, mode="w")
|
91
89
|
|
90
|
+
# Update file_path to the corrected path from writer
|
91
|
+
file_path = writer.filename
|
92
|
+
|
92
93
|
# Write to file
|
93
94
|
writer.write(
|
94
95
|
images=image.raw_image,
|
95
96
|
pixel_header=image.pixel_header,
|
96
97
|
dicom_meta=image.dicom_meta,
|
97
98
|
space=image.space,
|
98
|
-
|
99
|
-
dicom_status=image.dicom_status
|
99
|
+
dicom_status=image.dicom_status,
|
100
100
|
)
|
101
101
|
except Exception as e:
|
102
102
|
if isinstance(e, (InvalidCubeFileError, CodecError)):
|
@@ -108,13 +108,11 @@ class DicomCubeImageIO:
|
|
108
108
|
) from e
|
109
109
|
|
110
110
|
@staticmethod
|
111
|
-
def load(file_path: str
|
111
|
+
def load(file_path: str) -> 'DicomCubeImage':
|
112
112
|
"""Load DicomCubeImage from a file.
|
113
113
|
|
114
114
|
Args:
|
115
115
|
file_path (str): Input file path.
|
116
|
-
num_threads (int): Number of parallel decoding threads. Defaults to 4.
|
117
|
-
**kwargs: Additional parameters passed to the underlying reader.
|
118
116
|
|
119
117
|
Returns:
|
120
118
|
DicomCubeImage: The loaded object from the file.
|
@@ -152,7 +150,7 @@ class DicomCubeImageIO:
|
|
152
150
|
pixel_header = reader.read_pixel_header()
|
153
151
|
dicom_status = reader.read_dicom_status()
|
154
152
|
|
155
|
-
images = reader.read_images(
|
153
|
+
images = reader.read_images()
|
156
154
|
if isinstance(images, list):
|
157
155
|
# Convert list to ndarray if needed
|
158
156
|
images = np.stack(images)
|
@@ -180,7 +178,6 @@ class DicomCubeImageIO:
|
|
180
178
|
def load_from_dicom_folder(
|
181
179
|
folder_path: str,
|
182
180
|
sort_method: SortMethod = SortMethod.INSTANCE_NUMBER_ASC,
|
183
|
-
**kwargs
|
184
181
|
) -> 'DicomCubeImage':
|
185
182
|
"""Load DicomCubeImage from a DICOM folder.
|
186
183
|
|
@@ -188,7 +185,6 @@ class DicomCubeImageIO:
|
|
188
185
|
folder_path (str): Path to the DICOM folder.
|
189
186
|
sort_method (SortMethod): Method to sort DICOM files.
|
190
187
|
Defaults to SortMethod.INSTANCE_NUMBER_ASC.
|
191
|
-
**kwargs: Additional parameters.
|
192
188
|
|
193
189
|
Returns:
|
194
190
|
DicomCubeImage: The object created from the DICOM folder.
|
@@ -243,15 +239,21 @@ class DicomCubeImageIO:
|
|
243
239
|
intercept = meta.get_shared_value(CommonTags.RescaleIntercept)
|
244
240
|
wind_center = meta.get_shared_value(CommonTags.WindowCenter)
|
245
241
|
wind_width = meta.get_shared_value(CommonTags.WindowWidth)
|
242
|
+
try:
|
243
|
+
wind_center = float(wind_center)
|
244
|
+
wind_width = float(wind_width)
|
245
|
+
except:
|
246
|
+
wind_center = None
|
247
|
+
wind_width = None
|
246
248
|
|
247
249
|
# Create pixel_header
|
248
250
|
pixel_header = PixelDataHeader(
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
251
|
+
RescaleSlope=float(slope) if slope is not None else 1.0,
|
252
|
+
RescaleIntercept=float(intercept) if intercept is not None else 0.0,
|
253
|
+
OriginalPixelDtype=str(images[0].dtype),
|
254
|
+
PixelDtype=str(images[0].dtype),
|
255
|
+
WindowCenter=wind_center,
|
256
|
+
WindowWidth=wind_width,
|
255
257
|
)
|
256
258
|
|
257
259
|
# Validate PixelDataHeader initialization success
|
@@ -282,12 +284,11 @@ class DicomCubeImageIO:
|
|
282
284
|
) from e
|
283
285
|
|
284
286
|
@staticmethod
|
285
|
-
def load_from_nifti(file_path: str
|
287
|
+
def load_from_nifti(file_path: str) -> 'DicomCubeImage':
|
286
288
|
"""Load DicomCubeImage from a NIfTI file.
|
287
289
|
|
288
290
|
Args:
|
289
291
|
file_path (str): Path to the NIfTI file.
|
290
|
-
**kwargs: Additional parameters.
|
291
292
|
|
292
293
|
Returns:
|
293
294
|
DicomCubeImage: The object created from the NIfTI file.
|
@@ -351,4 +352,57 @@ class DicomCubeImageIO:
|
|
351
352
|
dicom_meta=image.dicom_meta,
|
352
353
|
pixel_header=image.pixel_header,
|
353
354
|
output_dir=folder_path,
|
354
|
-
)
|
355
|
+
)
|
356
|
+
|
357
|
+
@staticmethod
|
358
|
+
def save_to_nifti(
|
359
|
+
image: 'DicomCubeImage',
|
360
|
+
file_path: str,
|
361
|
+
) -> None:
|
362
|
+
"""Save DicomCubeImage as a NIfTI file.
|
363
|
+
|
364
|
+
Args:
|
365
|
+
image (DicomCubeImage): The DicomCubeImage object to save.
|
366
|
+
file_path (str): Output file path.
|
367
|
+
|
368
|
+
Raises:
|
369
|
+
ImportError: When nibabel is not installed.
|
370
|
+
InvalidCubeFileError: When saving fails.
|
371
|
+
"""
|
372
|
+
# Validate required parameters
|
373
|
+
validate_not_none(image, "image", "save_to_nifti operation", DataConsistencyError)
|
374
|
+
validate_string_not_empty(file_path, "file_path", "save_to_nifti operation", InvalidCubeFileError)
|
375
|
+
|
376
|
+
try:
|
377
|
+
import nibabel as nib
|
378
|
+
except ImportError:
|
379
|
+
raise ImportError("nibabel is required to write NIfTI files")
|
380
|
+
|
381
|
+
try:
|
382
|
+
if image.space is None:
|
383
|
+
raise InvalidCubeFileError(
|
384
|
+
"Cannot save to NIfTI without space information",
|
385
|
+
context="save_to_nifti operation",
|
386
|
+
suggestion="Ensure the DicomCubeImage has valid space information"
|
387
|
+
)
|
388
|
+
|
389
|
+
# Get affine matrix from space
|
390
|
+
affine = image.space.to_nifti_affine()
|
391
|
+
|
392
|
+
# 根据像素数据和metadata确定最佳的数据类型
|
393
|
+
optimal_data, dtype_name = determine_optimal_nifti_dtype(image.raw_image, image.pixel_header)
|
394
|
+
|
395
|
+
# Create NIfTI image with optimized data type
|
396
|
+
nii = nib.Nifti1Image(optimal_data, affine)
|
397
|
+
|
398
|
+
# Save to file
|
399
|
+
nib.save(nii, file_path)
|
400
|
+
except Exception as e:
|
401
|
+
if isinstance(e, (ImportError, InvalidCubeFileError)):
|
402
|
+
raise
|
403
|
+
raise InvalidCubeFileError(
|
404
|
+
f"Failed to save NIfTI file: {str(e)}",
|
405
|
+
context="save_to_nifti operation",
|
406
|
+
details={"file_path": file_path},
|
407
|
+
suggestion="Check file permissions and ensure space information is valid"
|
408
|
+
) from e
|
dicube/core/pixel_header.py
CHANGED
@@ -12,42 +12,42 @@ class PixelDataHeader:
|
|
12
12
|
- Original pixel data type
|
13
13
|
- Window settings (center/width)
|
14
14
|
- Value range (min/max)
|
15
|
-
- Additional metadata in
|
15
|
+
- Additional metadata in extras
|
16
16
|
|
17
17
|
Attributes:
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
18
|
+
RescaleSlope (float): Slope for linear transformation.
|
19
|
+
RescaleIntercept (float): Intercept for linear transformation.
|
20
|
+
PixelDtype (str): Pixel data type string (after convert to dcb file).
|
21
|
+
OriginalPixelDtype (str): Original pixel data type string (before convert to dcb file).
|
22
|
+
WindowCenter (float, optional): Window center value for display.
|
23
|
+
WindowWidth (float, optional): Window width value for display.
|
24
|
+
MaxVal (float, optional): Maximum pixel value.
|
25
|
+
MinVal (float, optional): Minimum pixel value.
|
26
|
+
Extras (Dict[str, any]): Dictionary for additional metadata.
|
27
27
|
"""
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
29
|
+
RescaleSlope: float = 1.0
|
30
|
+
RescaleIntercept: float = 0.0
|
31
|
+
OriginalPixelDtype: str = "uint16"
|
32
|
+
PixelDtype: str = "uint16"
|
33
|
+
WindowCenter: Optional[float] = None
|
34
|
+
WindowWidth: Optional[float] = None
|
35
|
+
MaxVal: Optional[float] = None
|
36
|
+
MinVal: Optional[float] = None
|
37
|
+
Extras: Dict[str, any] = field(default_factory=dict)
|
38
38
|
|
39
39
|
def to_dict(self) -> dict:
|
40
40
|
"""Convert the header to a dictionary for serialization.
|
41
41
|
|
42
|
-
Merges
|
43
|
-
the redundant
|
42
|
+
Merges extras field into the main dictionary and removes
|
43
|
+
the redundant extras key.
|
44
44
|
|
45
45
|
Returns:
|
46
46
|
dict: Dictionary representation of the header.
|
47
47
|
"""
|
48
48
|
data = asdict(self)
|
49
|
-
data.update(self.
|
50
|
-
data.pop("
|
49
|
+
data.update(self.Extras) # Merge Extras into dictionary
|
50
|
+
data.pop("Extras", None) # Remove redundant Extras field
|
51
51
|
return data
|
52
52
|
|
53
53
|
@classmethod
|
@@ -60,39 +60,42 @@ class PixelDataHeader:
|
|
60
60
|
Returns:
|
61
61
|
PixelDataHeader: A new instance with values from the dictionary.
|
62
62
|
"""
|
63
|
-
rescale_slope = d.get("
|
64
|
-
rescale_intercept = d.get("
|
65
|
-
original_pixel_dtype = d.get("
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
63
|
+
rescale_slope = d.get("RescaleSlope", 1.0)
|
64
|
+
rescale_intercept = d.get("RescaleIntercept", 0.0)
|
65
|
+
original_pixel_dtype = d.get("OriginalPixelDtype", "uint16")
|
66
|
+
pixel_dtype = d.get("PixelDtype", "uint16")
|
67
|
+
window_center = d.get("WindowCenter") # Defaults to None
|
68
|
+
window_width = d.get("WindowWidth") # Defaults to None
|
69
|
+
max_val = d.get("MaxVal") # Defaults to None
|
70
|
+
min_val = d.get("MinVal") # Defaults to None
|
71
|
+
|
72
|
+
# All other keys go into Extras
|
72
73
|
extras = {
|
73
74
|
k: v
|
74
75
|
for k, v in d.items()
|
75
76
|
if k
|
76
77
|
not in {
|
77
|
-
"
|
78
|
-
"
|
79
|
-
"
|
80
|
-
"
|
81
|
-
"
|
82
|
-
"
|
83
|
-
"
|
78
|
+
"RescaleSlope",
|
79
|
+
"RescaleIntercept",
|
80
|
+
"OriginalPixelDtype",
|
81
|
+
"PixelDtype",
|
82
|
+
"WindowCenter",
|
83
|
+
"WindowWidth",
|
84
|
+
"MaxVal",
|
85
|
+
"MinVal",
|
84
86
|
}
|
85
87
|
}
|
86
88
|
|
87
89
|
return cls(
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
90
|
+
RescaleSlope=rescale_slope,
|
91
|
+
RescaleIntercept=rescale_intercept,
|
92
|
+
OriginalPixelDtype=original_pixel_dtype,
|
93
|
+
PixelDtype=pixel_dtype,
|
94
|
+
WindowCenter=window_center,
|
95
|
+
WindowWidth=window_width,
|
96
|
+
MaxVal=max_val,
|
97
|
+
MinVal=min_val,
|
98
|
+
Extras=extras,
|
96
99
|
)
|
97
100
|
|
98
101
|
def to_json(self) -> str:
|