dicube 0.2.2__cp311-cp311-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.
- dicube/__init__.py +174 -0
- dicube/codecs/__init__.py +152 -0
- dicube/codecs/jph/__init__.py +15 -0
- dicube/codecs/jph/codec.py +161 -0
- dicube/codecs/jph/ojph_complete.cpython-310-aarch64-linux-gnu.so +0 -0
- dicube/codecs/jph/ojph_complete.cpython-311-aarch64-linux-gnu.so +0 -0
- dicube/codecs/jph/ojph_complete.cpython-38-aarch64-linux-gnu.so +0 -0
- dicube/codecs/jph/ojph_complete.cpython-39-aarch64-linux-gnu.so +0 -0
- dicube/codecs/jph/ojph_decode_complete.cpython-310-aarch64-linux-gnu.so +0 -0
- dicube/codecs/jph/ojph_decode_complete.cpython-311-aarch64-linux-gnu.so +0 -0
- dicube/codecs/jph/ojph_decode_complete.cpython-38-aarch64-linux-gnu.so +0 -0
- dicube/codecs/jph/ojph_decode_complete.cpython-39-aarch64-linux-gnu.so +0 -0
- dicube/core/__init__.py +21 -0
- dicube/core/image.py +349 -0
- dicube/core/io.py +408 -0
- dicube/core/pixel_header.py +120 -0
- dicube/dicom/__init__.py +13 -0
- dicube/dicom/dcb_streaming.py +248 -0
- dicube/dicom/dicom_io.py +153 -0
- dicube/dicom/dicom_meta.py +740 -0
- dicube/dicom/dicom_status.py +259 -0
- dicube/dicom/dicom_tags.py +121 -0
- dicube/dicom/merge_utils.py +283 -0
- dicube/dicom/space_from_meta.py +70 -0
- dicube/exceptions.py +189 -0
- dicube/storage/__init__.py +17 -0
- dicube/storage/dcb_file.py +824 -0
- dicube/storage/pixel_utils.py +259 -0
- dicube/utils/__init__.py +6 -0
- dicube/validation.py +380 -0
- dicube-0.2.2.dist-info/METADATA +272 -0
- dicube-0.2.2.dist-info/RECORD +33 -0
- dicube-0.2.2.dist-info/WHEEL +6 -0
@@ -0,0 +1,272 @@
|
|
1
|
+
Metadata-Version: 2.2
|
2
|
+
Name: dicube
|
3
|
+
Version: 0.2.2
|
4
|
+
Summary: Medical Image Storage Library with DICOM compatibility
|
5
|
+
Author: Fangzhou Liao
|
6
|
+
License: MIT
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
8
|
+
Classifier: Intended Audience :: Healthcare Industry
|
9
|
+
Classifier: Intended Audience :: Science/Research
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
11
|
+
Classifier: Operating System :: OS Independent
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
13
|
+
Classifier: Programming Language :: Python :: 3.8
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
20
|
+
Project-URL: Homepage, https://github.com/fastdiag-toolbox/dicube
|
21
|
+
Project-URL: Bug Reports, https://github.com/fastdiag-toolbox/dicube/issues
|
22
|
+
Project-URL: Source, https://github.com/fastdiag-toolbox/dicube
|
23
|
+
Requires-Python: >=3.8
|
24
|
+
Requires-Dist: numpy>=1.21.0
|
25
|
+
Requires-Dist: pydicom>=2.3.0
|
26
|
+
Requires-Dist: zstandard>=0.18.0
|
27
|
+
Requires-Dist: spacetransformer-core>=0.1.0
|
28
|
+
Provides-Extra: jph
|
29
|
+
Requires-Dist: pybind11>=2.10.0; extra == "jph"
|
30
|
+
Provides-Extra: nifti
|
31
|
+
Requires-Dist: nibabel>=3.2.0; extra == "nifti"
|
32
|
+
Provides-Extra: dev
|
33
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
34
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
35
|
+
Requires-Dist: black>=22.0.0; extra == "dev"
|
36
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
37
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
38
|
+
Requires-Dist: build>=0.8.0; extra == "dev"
|
39
|
+
Requires-Dist: pylibjpeg>=2.0; extra == "dev"
|
40
|
+
Requires-Dist: pylibjpeg-openjpeg>=2.0; extra == "dev"
|
41
|
+
Requires-Dist: nibabel>=3.2.0; extra == "dev"
|
42
|
+
Provides-Extra: all
|
43
|
+
Requires-Dist: pybind11>=2.10.0; extra == "all"
|
44
|
+
Requires-Dist: nibabel>=3.2.0; extra == "all"
|
45
|
+
Description-Content-Type: text/markdown
|
46
|
+
|
47
|
+
# DiCube: Medical Image Storage Library
|
48
|
+
|
49
|
+
DiCube is a Python library for efficient storage and processing of 3D medical images with complete DICOM metadata preservation. It provides a high-compression, single-file format that combines DICOM compatibility with modern compression techniques.
|
50
|
+
|
51
|
+
## Overview
|
52
|
+
|
53
|
+
DiCube was extracted from the larger DICOMCube project to focus specifically on medical image storage. It works alongside:
|
54
|
+
- **spacetransformer**: For 3D spatial transformations and coordinate systems
|
55
|
+
- **medmask**: For medical image segmentation mask processing
|
56
|
+
|
57
|
+
## Why DiCube?
|
58
|
+
|
59
|
+
Although the DICOM standard is indispensable for clinical interoperability, it was never designed for today’s high-volume, AI-driven workflows. In practice it exposes four chronic pain-points:
|
60
|
+
|
61
|
+
1. **Fragmented storage → slow I/O** A single CT/MR study can contain hundreds of small `.dcm` files. Traversing the file system and parsing each header one-by-one wastes precious milliseconds that quickly add up when training deep-learning models/ building realtime application.
|
62
|
+
2. **Redundant metadata** Every slice repeats identical patient/study/series tags, inflating storage size and network traffic with no benefit.
|
63
|
+
3. **Too many transfer syntaxes** Vendors ship proprietary or rarely-used encodings; no open-source decoder reliably supports *all* of them, so pipelines break on edge-cases.
|
64
|
+
|
65
|
+
DiCube mitigates these issues by:
|
66
|
+
|
67
|
+
* **Single-file design** All slices, metadata and spatial information are consolidated into one `.dcbs` file, eliminating filesystem overhead.
|
68
|
+
* **Deduplicated metadata** A compact JSON schema separates *shared* and *per-slice* tags, then compresses them with Zstandard.
|
69
|
+
* **Conservative codec policy** Only codecs that pass extensive performance and stability tests are adopted. Currently `.dcbs` uses HTJ2K for fast, lossless compression. Archive (`.dcba`) and lossy (`.dcbl`) variants are planned but not yet released. This package is a self-contained lib, users do not need to install codecs independently.
|
70
|
+
* **Round-trip safety** Every DiCube file can always be converted back to standard DICOM, preserving full clinical fidelity.
|
71
|
+
|
72
|
+
> In typical benchmarks DiCube cuts CT series load time from ~150 ms (PyDICOM) to <40 ms and shrinks storage by up to **3×**, all while remaining 100 % DICOM-compatible.
|
73
|
+
|
74
|
+
## Architecture
|
75
|
+
|
76
|
+
### Core Modules
|
77
|
+
|
78
|
+
```
|
79
|
+
dicube/
|
80
|
+
├── core/ # Core data structures
|
81
|
+
│ ├── image.py # DicomCubeImage (main interface)
|
82
|
+
| ├── io.py # DicomCubeImageIO (from and to many file formats)
|
83
|
+
│ └── pixel_header.py # PixelDataHeader (image metadata)
|
84
|
+
├── storage/ # File storage formats
|
85
|
+
│ ├── dcb_file.py # DCB file format implementations
|
86
|
+
│ └── pixel_utils.py # Pixel processing utilities
|
87
|
+
├── dicom/ # DICOM functionality
|
88
|
+
│ ├── dicom_meta.py # DicomMeta (metadata container)
|
89
|
+
│ ├── dicom_status.py # DICOM consistency checking
|
90
|
+
│ ├── dicom_tags.py # DICOM tag definitions
|
91
|
+
│ ├── dicom_io.py # DICOM file I/O
|
92
|
+
│ └── merge_utils.py # Metadata merging utilities
|
93
|
+
├── codecs/ # Compression codecs
|
94
|
+
│ └── jph/ # HTJ2K codec (dcbs format)
|
95
|
+
└── exceptions.py # Custom exceptions
|
96
|
+
```
|
97
|
+
|
98
|
+
## File Formats
|
99
|
+
|
100
|
+
DiCube defines three file format specifications for different use cases:
|
101
|
+
|
102
|
+
### .dcbs (Speed format) - **Currently Implemented**
|
103
|
+
- **Magic**: `DCMCUBES`
|
104
|
+
- **Target**: I/O speed suitable for deep learning training while high compression ratio.
|
105
|
+
- **Codec**: High Throughput JPEG 2000 (HTJ2K)
|
106
|
+
- **Use case**: High-speed encoding/decoding for processing pipelines
|
107
|
+
- **Features**: Optimized for throughput, lossless compression
|
108
|
+
|
109
|
+
### .dcba (Archive format) - **Placeholder**
|
110
|
+
- **Magic**: `DCMCUBEA`
|
111
|
+
- **Target**: 20% better compression ratio than dcbs
|
112
|
+
- **Use case**: Long-term storage and archiving
|
113
|
+
- **Status**: Awaiting suitable codec that meets compression targets
|
114
|
+
|
115
|
+
### .dcbl (Lossy format) - **Placeholder**
|
116
|
+
- **Magic**: `DCMCUBEL`
|
117
|
+
- **Target**: 60%+ compression ratio with imperceptible quality loss
|
118
|
+
- **Use case**: High-compression scenarios where minor quality trade-offs are acceptable
|
119
|
+
- **Status**: Awaiting suitable codec that meets quality/compression targets
|
120
|
+
|
121
|
+
> **Codec Selection Philosophy**: We take a conservative approach to codec adoption, requiring extensive testing and clear performance benefits before implementation. This avoids the complexity issues seen in DICOM's numerous format variations.
|
122
|
+
|
123
|
+
## Key Classes and Interfaces
|
124
|
+
|
125
|
+
### DicomCubeImage
|
126
|
+
Main interface for medical image handling:
|
127
|
+
|
128
|
+
```python
|
129
|
+
import dicube
|
130
|
+
|
131
|
+
# Create from DICOM directory
|
132
|
+
image = dicube.load_from_dicom_folder('path/to/dicom/')
|
133
|
+
|
134
|
+
# Create from NIfTI file
|
135
|
+
image = dicube.load_from_nifti('image.nii.gz')
|
136
|
+
|
137
|
+
# Save to compressed format (currently only dcbs is implemented)
|
138
|
+
dicube.save(image, 'output.dcbs', file_type='s') # HTJ2K (Speed format)
|
139
|
+
|
140
|
+
# Load from file
|
141
|
+
loaded_image = dicube.load('output.dcbs')
|
142
|
+
|
143
|
+
# Export back to DICOM
|
144
|
+
dicube.save_to_dicom_folder(image, 'output_dicom/')
|
145
|
+
|
146
|
+
# Get pixel data
|
147
|
+
pixel_data = image.get_fdata() # Returns float array
|
148
|
+
raw_data = image.raw_image # Returns original dtype
|
149
|
+
```
|
150
|
+
|
151
|
+
### DicomMeta
|
152
|
+
DICOM metadata container with efficient shared/non-shared value handling:
|
153
|
+
|
154
|
+
```python
|
155
|
+
from dicube import DicomMeta, read_dicom_dir
|
156
|
+
|
157
|
+
# Read DICOM directory
|
158
|
+
meta = read_dicom_dir('dicom_folder/')
|
159
|
+
|
160
|
+
# Access shared values (same across all slices)
|
161
|
+
patient_name = meta.get('PatientName') # Returns single value
|
162
|
+
|
163
|
+
# Access non-shared values (different per slice)
|
164
|
+
positions = meta.get('ImagePositionPatient') # Returns list
|
165
|
+
|
166
|
+
# Check status
|
167
|
+
from dicube import get_dicom_status
|
168
|
+
status = get_dicom_status(meta)
|
169
|
+
```
|
170
|
+
|
171
|
+
|
172
|
+
|
173
|
+
## Integration with spacetransformer
|
174
|
+
|
175
|
+
DiCube uses `spacetransformer.Space` for 3D coordinate system handling:
|
176
|
+
|
177
|
+
```python
|
178
|
+
from spacetransformer import Space, warp_image
|
179
|
+
|
180
|
+
# DicomCubeImage automatically creates Space from DICOM
|
181
|
+
image = dicube.load_from_dicom_folder('dicom/')
|
182
|
+
space = image.space # spacetransformer.Space object
|
183
|
+
|
184
|
+
# Apply spatial transformations
|
185
|
+
space2 = space.apply_flip(axis=2)
|
186
|
+
space2 = space2.apply_rotate(axis=0, angle=90, unit='degree')
|
187
|
+
|
188
|
+
# Update image with new space
|
189
|
+
image2 = warp_image(image, space, space2)
|
190
|
+
```
|
191
|
+
|
192
|
+
## DICOM Status Checking
|
193
|
+
|
194
|
+
DiCube provides comprehensive DICOM consistency checking:
|
195
|
+
|
196
|
+
```python
|
197
|
+
from dicube import DicomStatus, get_dicom_status
|
198
|
+
|
199
|
+
status = get_dicom_status(meta)
|
200
|
+
|
201
|
+
# Possible status values:
|
202
|
+
# DicomStatus.CONSISTENT - All checks pass
|
203
|
+
# DicomStatus.MISSING_SERIES_UID - No series UID
|
204
|
+
# DicomStatus.DUPLICATE_INSTANCE_NUMBERS - Non-unique instance numbers
|
205
|
+
# DicomStatus.NON_UNIFORM_SPACING - Inconsistent pixel spacing
|
206
|
+
# DicomStatus.GAP_LOCATION - Missing slices in Z direction
|
207
|
+
# ... and more
|
208
|
+
```
|
209
|
+
|
210
|
+
## Compression Codecs
|
211
|
+
|
212
|
+
### HTJ2K (jph/)
|
213
|
+
- **Status**: Currently implemented for .dcbs format
|
214
|
+
- **Files**: `_encode.py`, `_decode.py`, pybind11 bindings
|
215
|
+
- **Functions**: `imencode_jph()`, `imdecode_jph()`
|
216
|
+
- **Build**: Uses pybind11 for C++ bindings to OpenJPH library
|
217
|
+
- **Performance**: Optimized for high-speed encoding/decoding
|
218
|
+
|
219
|
+
## Best Practices
|
220
|
+
|
221
|
+
### For Medical Images
|
222
|
+
1. Always preserve DICOM metadata when possible
|
223
|
+
2. Currently use `.dcbs` format for all storage needs (fast HTJ2K)
|
224
|
+
3. Check DICOM status before processing: `get_dicom_status(meta)`
|
225
|
+
4. Monitor for updates as `.dcba` and `.dcbl` formats become available
|
226
|
+
|
227
|
+
### For Integration
|
228
|
+
1. Use spacetransformer for all spatial operations
|
229
|
+
2. Use medmask for segmentation mask processing
|
230
|
+
3. Convert coordinates between voxel and world space using `Space` transforms
|
231
|
+
4. Validate file format compatibility with `dicube.load()`
|
232
|
+
|
233
|
+
### Performance Tips
|
234
|
+
1. Use `num_threads` parameter for parallel compression
|
235
|
+
2. For large datasets, process in chunks to manage memory
|
236
|
+
3. Check DicomStatus before processing to avoid corrupted data
|
237
|
+
4. Use HTJ2K's high-speed capabilities for processing pipelines
|
238
|
+
|
239
|
+
## Error Handling
|
240
|
+
|
241
|
+
```python
|
242
|
+
from dicube.exceptions import (
|
243
|
+
DicomCubeError,
|
244
|
+
InvalidCubeFileError,
|
245
|
+
CodecError,
|
246
|
+
MetaDataError,
|
247
|
+
DataConsistencyError
|
248
|
+
)
|
249
|
+
|
250
|
+
try:
|
251
|
+
image = dicube.load('corrupted.dcbs')
|
252
|
+
except InvalidCubeFileError:
|
253
|
+
print("Not a valid DiCube file")
|
254
|
+
except CodecError:
|
255
|
+
print("Compression/decompression failed")
|
256
|
+
except MetaDataError:
|
257
|
+
print("Missing or invalid metadata")
|
258
|
+
```
|
259
|
+
|
260
|
+
## Dependencies
|
261
|
+
|
262
|
+
### Required
|
263
|
+
- numpy: Array operations
|
264
|
+
- pydicom: DICOM file handling
|
265
|
+
- spacetransformer: Spatial transformations
|
266
|
+
- zstandard: Metadata compression
|
267
|
+
|
268
|
+
### Optional (for full functionality)
|
269
|
+
- OpenJPH library: For .dcbs format implementation
|
270
|
+
- nibabel: For NIfTI file support
|
271
|
+
|
272
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
dicube/__init__.py,sha256=TK2-JGOB_aPa6ilHw4WUc9l5Whc3Fb-tlZSPzbf5HIw,4886
|
2
|
+
dicube/exceptions.py,sha256=YrwBD93oWI4yhvFfO-SOPCNMQ4z_1FSVL2gCVSnx-LU,6689
|
3
|
+
dicube/validation.py,sha256=Edmx3yKhRShdzvM7uRK6N9j58GNV8rUv_k9w43JcaMs,12478
|
4
|
+
dicube/core/io.py,sha256=g8uKbcX7zz9LCq65spBeeodZEf6l4HSF9jzl60HZVyw,15629
|
5
|
+
dicube/core/__init__.py,sha256=tU9vaPHbTkF8V78T8D6werr0nC7k6bMPIlatEIEdHU4,656
|
6
|
+
dicube/core/image.py,sha256=DAyBwKlWeCU6oDWsmdSdAzVW3IieHNLUINIAhS_ZtRg,14177
|
7
|
+
dicube/core/pixel_header.py,sha256=x3-gNiyL4lFRQ6c1TVdvsm2mG36xCQx78hq4vjYkqJI,4005
|
8
|
+
dicube/storage/__init__.py,sha256=q36sJqdI9acURBXjOW_g3QiyHw0XLGFCukMsQ-qioZc,465
|
9
|
+
dicube/storage/pixel_utils.py,sha256=-xMMnjSMzYk6WRvLAPktMELhSXJPmLBnt5wxKgOw5zg,9759
|
10
|
+
dicube/storage/dcb_file.py,sha256=GfOx2C6fexKojxwzak3_Q0K3gRBHB_UTMNVBY4NPRzg,31232
|
11
|
+
dicube/codecs/__init__.py,sha256=NNus-iAv4JXsNH1kALf5vnLYnESFBoYaN72yJ7kQoqk,3754
|
12
|
+
dicube/codecs/jph/__init__.py,sha256=wLwzqAHCKT_7CdNrcEUtM2AyfvYgPJOj9nsm5CC_3F0,392
|
13
|
+
dicube/codecs/jph/ojph_complete.cpython-311-aarch64-linux-gnu.so,sha256=uwYEKQn7n1AlZ60FuwcMIGruAXL4RZC3N0eiAUCkb3E,530600
|
14
|
+
dicube/codecs/jph/codec.py,sha256=d4bAoVAatSrWiC1k7gQLzWODZZTGo_1xeRRXO0NAtqo,5460
|
15
|
+
dicube/codecs/jph/ojph_decode_complete.cpython-311-aarch64-linux-gnu.so,sha256=My28Uk161m0LILSrq7cERe3SoB1kYvsPqvcYgeoc6TE,596136
|
16
|
+
dicube/codecs/jph/ojph_complete.cpython-39-aarch64-linux-gnu.so,sha256=R1jPK5ANaElndf8RyHR2zecNuwNRB5acGpYELDB-d-0,530592
|
17
|
+
dicube/codecs/jph/ojph_decode_complete.cpython-310-aarch64-linux-gnu.so,sha256=lnbheGgtn1FhLxj3sX82u2PQuh04812KpB2NXn9ANFY,530592
|
18
|
+
dicube/codecs/jph/ojph_complete.cpython-38-aarch64-linux-gnu.so,sha256=qTvke7It1vJCp230evgY6akylHBs34QuzJ9SHyC8zik,530576
|
19
|
+
dicube/codecs/jph/ojph_decode_complete.cpython-39-aarch64-linux-gnu.so,sha256=aRQJ2ALKfJRfLzcoLWLJyFyw0XOvfl8ae_t8J9CLWdQ,530592
|
20
|
+
dicube/codecs/jph/ojph_complete.cpython-310-aarch64-linux-gnu.so,sha256=e1Vcq-iaJNiAhf5Yb1Sd229CNqUoeUzI3tYb70KhMBI,530592
|
21
|
+
dicube/codecs/jph/ojph_decode_complete.cpython-38-aarch64-linux-gnu.so,sha256=PVCp6XBUFMktMyACVWaqpLGvUNYhFtXQIgm0Sowj2rQ,530568
|
22
|
+
dicube/utils/__init__.py,sha256=m3pYJfuk4hISVes_cfG2eDjTyGF-y40xbxV07IOjbi0,149
|
23
|
+
dicube/dicom/__init__.py,sha256=9b7liSXx5vlpEYAr59GZGkcUw16kULELTX5SlLfcXPw,371
|
24
|
+
dicube/dicom/dicom_io.py,sha256=EBa72RGHfifFKygBwCWf6r2YCTNxE9onO8d65ws_5VU,4917
|
25
|
+
dicube/dicom/dicom_meta.py,sha256=Iv-kEcV39vhK2qgSqGpqDhgg28RuUm8ddzSdpToIVPc,26813
|
26
|
+
dicube/dicom/dcb_streaming.py,sha256=Acsdusc6jIKuu1kd-VuDOoteZGdpt3UmwsxF-HQYZtM,9088
|
27
|
+
dicube/dicom/dicom_tags.py,sha256=sOjrK9SoAhGqynF0e3YH70j8wbtvwGRezV-tM0wp40Q,3945
|
28
|
+
dicube/dicom/space_from_meta.py,sha256=__B7UTmvgV1N-LMJg9O_ObHgNWa39mbRF4ZSkQXm3Vs,2420
|
29
|
+
dicube/dicom/dicom_status.py,sha256=NXi-sj3mhyaFGfpechewTjhI201vziVsyfLotsLr3Fs,10117
|
30
|
+
dicube/dicom/merge_utils.py,sha256=6flzoK_6gzpvv4WSTaWq4SjVdr1gh3gtUPMsRfKDSNM,9312
|
31
|
+
dicube-0.2.2.dist-info/METADATA,sha256=nBhXpfkqIUhGO2LUB-HmTwmDIolxcvd-cr8tW4CJNzM,10627
|
32
|
+
dicube-0.2.2.dist-info/RECORD,,
|
33
|
+
dicube-0.2.2.dist-info/WHEEL,sha256=Kwg1jTQSV5tLOpn4FT1S6-v_xgqCZdPA6R__HUoMkh0,158
|