dicube 0.2.2__cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.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 (35) hide show
  1. dicube/__init__.py +174 -0
  2. dicube/codecs/__init__.py +152 -0
  3. dicube/codecs/jph/__init__.py +15 -0
  4. dicube/codecs/jph/codec.py +161 -0
  5. dicube/codecs/jph/ojph_complete.cpython-310-aarch64-linux-gnu.so +0 -0
  6. dicube/codecs/jph/ojph_complete.cpython-311-aarch64-linux-gnu.so +0 -0
  7. dicube/codecs/jph/ojph_complete.cpython-312-aarch64-linux-gnu.so +0 -0
  8. dicube/codecs/jph/ojph_complete.cpython-38-aarch64-linux-gnu.so +0 -0
  9. dicube/codecs/jph/ojph_complete.cpython-39-aarch64-linux-gnu.so +0 -0
  10. dicube/codecs/jph/ojph_decode_complete.cpython-310-aarch64-linux-gnu.so +0 -0
  11. dicube/codecs/jph/ojph_decode_complete.cpython-311-aarch64-linux-gnu.so +0 -0
  12. dicube/codecs/jph/ojph_decode_complete.cpython-312-aarch64-linux-gnu.so +0 -0
  13. dicube/codecs/jph/ojph_decode_complete.cpython-38-aarch64-linux-gnu.so +0 -0
  14. dicube/codecs/jph/ojph_decode_complete.cpython-39-aarch64-linux-gnu.so +0 -0
  15. dicube/core/__init__.py +21 -0
  16. dicube/core/image.py +349 -0
  17. dicube/core/io.py +408 -0
  18. dicube/core/pixel_header.py +120 -0
  19. dicube/dicom/__init__.py +13 -0
  20. dicube/dicom/dcb_streaming.py +248 -0
  21. dicube/dicom/dicom_io.py +153 -0
  22. dicube/dicom/dicom_meta.py +740 -0
  23. dicube/dicom/dicom_status.py +259 -0
  24. dicube/dicom/dicom_tags.py +121 -0
  25. dicube/dicom/merge_utils.py +283 -0
  26. dicube/dicom/space_from_meta.py +70 -0
  27. dicube/exceptions.py +189 -0
  28. dicube/storage/__init__.py +17 -0
  29. dicube/storage/dcb_file.py +824 -0
  30. dicube/storage/pixel_utils.py +259 -0
  31. dicube/utils/__init__.py +6 -0
  32. dicube/validation.py +380 -0
  33. dicube-0.2.2.dist-info/METADATA +272 -0
  34. dicube-0.2.2.dist-info/RECORD +35 -0
  35. dicube-0.2.2.dist-info/WHEEL +6 -0
@@ -0,0 +1,70 @@
1
+ from spacetransformer import Space
2
+ from .dicom_status import DicomStatus, get_dicom_status
3
+ from .dicom_tags import CommonTags
4
+ import numpy as np
5
+
6
+
7
+ def get_space_from_DicomMeta(meta, axis_order="xyz"):
8
+ """
9
+ Create a Space object from DICOM metadata.
10
+
11
+ Extracts geometric information from DICOM tags including:
12
+ - Image Position (Patient) for origin
13
+ - Pixel Spacing and Slice Thickness for spacing
14
+ - Image Orientation (Patient) for direction cosines
15
+ - Rows, Columns, and number of slices for shape
16
+
17
+ Args:
18
+ meta: DicomMeta object containing DICOM metadata
19
+ Must support meta[Tag] -> (value, status) interface
20
+
21
+ Returns:
22
+ Space: A new Space instance with geometry matching the DICOM data
23
+
24
+ Raises:
25
+ ValueError: If required DICOM tags are missing or invalid
26
+ """
27
+
28
+ num_images = meta.slice_count
29
+ status = get_dicom_status(meta)
30
+ if status not in (DicomStatus.CONSISTENT, DicomStatus.NON_UNIFORM_RESCALE_FACTOR):
31
+ return None
32
+ spacing = meta.get_shared_value(CommonTags.PixelSpacing)
33
+ spacing = [float(s) for s in spacing]
34
+ positions = np.array(
35
+ meta.get_values(CommonTags.ImagePositionPatient)
36
+ )
37
+ orientation = meta.get_shared_value(CommonTags.ImageOrientationPatient)
38
+ orientation = [float(s) for s in orientation]
39
+ origin = positions[0].tolist()
40
+ if num_images > 1:
41
+ diff = positions[-1] - positions[0]
42
+ z_orientation = diff / np.linalg.norm(diff).tolist()
43
+ z_step_vector = diff / (num_images - 1)
44
+ spacing.append(float(np.linalg.norm(z_step_vector)))
45
+ else:
46
+ thickness = meta.get_shared_value(CommonTags.SliceThickness)
47
+ if thickness is None:
48
+ thickness = 1
49
+ spacing.append(float(thickness))
50
+ z_orientation = np.cross(orientation[:3], orientation[3:6]).tolist()
51
+ shape = [
52
+ int(meta.get_shared_value(CommonTags.Columns)),
53
+ int(meta.get_shared_value(CommonTags.Rows)),
54
+ num_images,
55
+ ]
56
+ space = Space(
57
+ origin=origin,
58
+ spacing=spacing,
59
+ x_orientation=orientation[:3],
60
+ y_orientation=orientation[3:6],
61
+ z_orientation=z_orientation,
62
+ shape=shape,
63
+ )
64
+ if axis_order == "xyz":
65
+ space = space
66
+ elif axis_order == "zyx":
67
+ space = space.reverse_axis_order()
68
+ else:
69
+ raise ValueError(f"Invalid axis order: {axis_order}")
70
+ return space
dicube/exceptions.py ADDED
@@ -0,0 +1,189 @@
1
+ """Exceptions module for DiCube.
2
+
3
+ This module defines the exception hierarchy used throughout the DiCube library.
4
+ All exceptions inherit from the base DicomCubeError class to allow for
5
+ easy catching of all DiCube-related exceptions.
6
+ """
7
+
8
+ from typing import Optional, Dict, Any
9
+
10
+
11
+ class DicomCubeError(Exception):
12
+ """Base exception class for all DicomCube-related errors.
13
+
14
+ All other exceptions in the DiCube library inherit from this class,
15
+ allowing applications to catch all DiCube-related exceptions with:
16
+
17
+ ```python
18
+ try:
19
+ # DiCube operations
20
+ except DicomCubeError:
21
+ # Handle any DiCube error
22
+ ```
23
+
24
+ This enhanced base class supports contextual error information and
25
+ helpful suggestions for resolving common issues.
26
+ """
27
+
28
+ def __init__(
29
+ self,
30
+ message: str,
31
+ context: Optional[str] = None,
32
+ suggestion: Optional[str] = None,
33
+ details: Optional[Dict[str, Any]] = None
34
+ ):
35
+ """Initialize a DicomCubeError with contextual information.
36
+
37
+ Args:
38
+ message (str): The primary error message.
39
+ context (str, optional): Context about the operation that failed.
40
+ suggestion (str, optional): Helpful suggestion for resolving the error.
41
+ details (dict, optional): Additional structured error details.
42
+ """
43
+ self.context = context
44
+ self.suggestion = suggestion
45
+ self.details = details or {}
46
+
47
+ formatted_message = self._format_message(message)
48
+ super().__init__(formatted_message)
49
+
50
+ def _format_message(self, message: str) -> str:
51
+ """Format the error message with context and suggestions.
52
+
53
+ Args:
54
+ message (str): The base error message.
55
+
56
+ Returns:
57
+ str: The formatted error message.
58
+ """
59
+ parts = []
60
+
61
+ # Add context if provided
62
+ if self.context:
63
+ parts.append(f"{self.context}: {message}")
64
+ else:
65
+ parts.append(message)
66
+
67
+ # Add details if provided
68
+ if self.details:
69
+ detail_strs = [f"{k}={repr(v)}" for k, v in self.details.items()]
70
+ parts.append(f"Details: {', '.join(detail_strs)}")
71
+
72
+ # Add suggestion if provided
73
+ if self.suggestion:
74
+ parts.append(f"Suggestion: {self.suggestion}")
75
+
76
+ return "\n".join(parts)
77
+
78
+
79
+ class InvalidCubeFileError(DicomCubeError):
80
+ """Raised when a file is not a valid DicomCube file.
81
+
82
+ This exception is raised when attempting to load a file that is not
83
+ in the expected DicomCube format. This could be due to incorrect
84
+ magic number, version mismatch, or a corrupted file structure.
85
+ """
86
+
87
+ def __init__(
88
+ self,
89
+ message: str,
90
+ context: Optional[str] = None,
91
+ suggestion: Optional[str] = None,
92
+ details: Optional[Dict[str, Any]] = None
93
+ ):
94
+ """Initialize InvalidCubeFileError with file-specific suggestions.
95
+
96
+ Args:
97
+ message (str): The primary error message.
98
+ context (str, optional): Context about the operation that failed.
99
+ suggestion (str, optional): Helpful suggestion for resolving the error.
100
+ details (dict, optional): Additional structured error details.
101
+ """
102
+ if suggestion is None:
103
+ suggestion = "Verify the file is a valid DicomCube file and not corrupted"
104
+
105
+ super().__init__(message, context, suggestion, details)
106
+
107
+
108
+ class CodecError(DicomCubeError):
109
+ """Raised when an error occurs in the encoding/decoding process.
110
+
111
+ This exception is raised when there are problems with image compression
112
+ or decompression, such as JPEG 2000 processing failures.
113
+ """
114
+
115
+ def __init__(
116
+ self,
117
+ message: str,
118
+ context: Optional[str] = None,
119
+ suggestion: Optional[str] = None,
120
+ details: Optional[Dict[str, Any]] = None
121
+ ):
122
+ """Initialize CodecError with codec-specific suggestions.
123
+
124
+ Args:
125
+ message (str): The primary error message.
126
+ context (str, optional): Context about the operation that failed.
127
+ suggestion (str, optional): Helpful suggestion for resolving the error.
128
+ details (dict, optional): Additional structured error details.
129
+ """
130
+ if suggestion is None:
131
+ suggestion = "Check image data format and codec compatibility"
132
+
133
+ super().__init__(message, context, suggestion, details)
134
+
135
+
136
+ class MetaDataError(DicomCubeError):
137
+ """Raised when metadata is missing or inconsistent.
138
+
139
+ This exception is raised when critical metadata (DicomMeta, Space, etc.)
140
+ is missing, corrupted, or inconsistent in a DicomCube file or operation.
141
+ """
142
+
143
+ def __init__(
144
+ self,
145
+ message: str,
146
+ context: Optional[str] = None,
147
+ suggestion: Optional[str] = None,
148
+ details: Optional[Dict[str, Any]] = None
149
+ ):
150
+ """Initialize MetaDataError with metadata-specific suggestions.
151
+
152
+ Args:
153
+ message (str): The primary error message.
154
+ context (str, optional): Context about the operation that failed.
155
+ suggestion (str, optional): Helpful suggestion for resolving the error.
156
+ details (dict, optional): Additional structured error details.
157
+ """
158
+ if suggestion is None:
159
+ suggestion = "Verify metadata completeness and consistency in the source data"
160
+
161
+ super().__init__(message, context, suggestion, details)
162
+
163
+
164
+ class DataConsistencyError(DicomCubeError):
165
+ """Raised when data arrays have consistency issues.
166
+
167
+ This exception is raised when image data arrays have mismatched
168
+ shapes, incompatible types, or other consistency-related issues.
169
+ """
170
+
171
+ def __init__(
172
+ self,
173
+ message: str,
174
+ context: Optional[str] = None,
175
+ suggestion: Optional[str] = None,
176
+ details: Optional[Dict[str, Any]] = None
177
+ ):
178
+ """Initialize DataConsistencyError with data-specific suggestions.
179
+
180
+ Args:
181
+ message (str): The primary error message.
182
+ context (str, optional): Context about the operation that failed.
183
+ suggestion (str, optional): Helpful suggestion for resolving the error.
184
+ details (dict, optional): Additional structured error details.
185
+ """
186
+ if suggestion is None:
187
+ suggestion = "Check data array shapes, types, and dimensional consistency"
188
+
189
+ super().__init__(message, context, suggestion, details)
@@ -0,0 +1,17 @@
1
+ """Storage module for DiCube library.
2
+
3
+ This module provides implementations of DiCube binary file formats (.dcb)
4
+ and utilities for pixel data processing. It handles the storage and retrieval
5
+ of 3D medical images along with their metadata.
6
+
7
+ Classes:
8
+ DcbFile: Base class for DiCube file implementations.
9
+ DcbSFile: Speed-optimized implementation of DiCube file format.
10
+ """
11
+
12
+ from .dcb_file import DcbFile, DcbSFile
13
+
14
+ __all__ = [
15
+ "DcbFile",
16
+ "DcbSFile",
17
+ ]