cardio 2025.10.0__py3-none-any.whl → 2025.12.0__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.
- cardio/__init__.py +1 -1
- cardio/app.py +0 -2
- cardio/blend_transfer_functions.py +0 -3
- cardio/color_transfer_function.py +0 -2
- cardio/logic.py +131 -83
- cardio/mesh.py +1 -4
- cardio/object.py +0 -3
- cardio/orientation.py +1 -3
- cardio/piecewise_function.py +0 -2
- cardio/property_config.py +0 -3
- cardio/scene.py +18 -15
- cardio/segmentation.py +2 -5
- cardio/transfer_function_pair.py +0 -2
- cardio/types.py +0 -2
- cardio/ui.py +236 -90
- cardio/volume.py +162 -45
- cardio/volume_property.py +0 -2
- cardio/volume_property_presets.py +0 -3
- cardio/window_level.py +0 -2
- {cardio-2025.10.0.dist-info → cardio-2025.12.0.dist-info}/METADATA +7 -8
- cardio-2025.12.0.dist-info/RECORD +29 -0
- cardio-2025.10.0.dist-info/RECORD +0 -29
- {cardio-2025.10.0.dist-info → cardio-2025.12.0.dist-info}/WHEEL +0 -0
- {cardio-2025.10.0.dist-info → cardio-2025.12.0.dist-info}/entry_points.txt +0 -0
cardio/volume.py
CHANGED
|
@@ -20,7 +20,7 @@ class Volume(Object):
|
|
|
20
20
|
"""Volume object with transfer functions and clipping support."""
|
|
21
21
|
|
|
22
22
|
pattern: str = pc.Field(
|
|
23
|
-
default="
|
|
23
|
+
default="{frame}.nii.gz",
|
|
24
24
|
description="Filename pattern with $frame placeholder",
|
|
25
25
|
)
|
|
26
26
|
transfer_function_preset: str = pc.Field(
|
|
@@ -30,6 +30,9 @@ class Volume(Object):
|
|
|
30
30
|
_mpr_actors: dict[str, list[vtk.vtkImageActor]] = pc.PrivateAttr(
|
|
31
31
|
default_factory=dict
|
|
32
32
|
)
|
|
33
|
+
_crosshair_actors: dict[str, dict[str, vtk.vtkActor]] = pc.PrivateAttr(
|
|
34
|
+
default_factory=dict
|
|
35
|
+
)
|
|
33
36
|
|
|
34
37
|
@pc.model_validator(mode="after")
|
|
35
38
|
def initialize_volume(self):
|
|
@@ -134,6 +137,104 @@ class Volume(Object):
|
|
|
134
137
|
return self.create_mpr_actors(frame)
|
|
135
138
|
return self._mpr_actors[frame]
|
|
136
139
|
|
|
140
|
+
def create_crosshair_actors(self, colors: dict, line_width: float = 1.5) -> dict:
|
|
141
|
+
"""Create 2D crosshair overlay actors for each MPR view.
|
|
142
|
+
|
|
143
|
+
Uses screen-space 2D actors that always appear centered in the view.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
colors: Dict mapping view names to RGB tuples
|
|
147
|
+
line_width: Width of the crosshair lines
|
|
148
|
+
|
|
149
|
+
Returns:
|
|
150
|
+
Dict mapping view names to dicts with line actors
|
|
151
|
+
"""
|
|
152
|
+
crosshairs = {}
|
|
153
|
+
|
|
154
|
+
for view_name in ["axial", "sagittal", "coronal"]:
|
|
155
|
+
view_crosshairs = {}
|
|
156
|
+
|
|
157
|
+
for line_name in ["line1", "line2"]:
|
|
158
|
+
# Create 2D line using normalized viewport coordinates
|
|
159
|
+
points = vtk.vtkPoints()
|
|
160
|
+
lines = vtk.vtkCellArray()
|
|
161
|
+
|
|
162
|
+
# Placeholder points - will set based on line orientation
|
|
163
|
+
if line_name == "line1":
|
|
164
|
+
# Vertical line (one of the other planes)
|
|
165
|
+
points.InsertNextPoint(0.5, 0.0, 0.0)
|
|
166
|
+
points.InsertNextPoint(0.5, 1.0, 0.0)
|
|
167
|
+
else:
|
|
168
|
+
# Horizontal line (other plane)
|
|
169
|
+
points.InsertNextPoint(0.0, 0.5, 0.0)
|
|
170
|
+
points.InsertNextPoint(1.0, 0.5, 0.0)
|
|
171
|
+
|
|
172
|
+
line = vtk.vtkLine()
|
|
173
|
+
line.GetPointIds().SetId(0, 0)
|
|
174
|
+
line.GetPointIds().SetId(1, 1)
|
|
175
|
+
lines.InsertNextCell(line)
|
|
176
|
+
|
|
177
|
+
polydata = vtk.vtkPolyData()
|
|
178
|
+
polydata.SetPoints(points)
|
|
179
|
+
polydata.SetLines(lines)
|
|
180
|
+
|
|
181
|
+
# Use coordinate transform to map normalized coords to viewport
|
|
182
|
+
coord = vtk.vtkCoordinate()
|
|
183
|
+
coord.SetCoordinateSystemToNormalizedViewport()
|
|
184
|
+
|
|
185
|
+
mapper = vtk.vtkPolyDataMapper2D()
|
|
186
|
+
mapper.SetInputData(polydata)
|
|
187
|
+
mapper.SetTransformCoordinate(coord)
|
|
188
|
+
|
|
189
|
+
actor = vtk.vtkActor2D()
|
|
190
|
+
actor.SetMapper(mapper)
|
|
191
|
+
actor.GetProperty().SetLineWidth(line_width)
|
|
192
|
+
actor.SetVisibility(False)
|
|
193
|
+
|
|
194
|
+
view_crosshairs[line_name] = {
|
|
195
|
+
"polydata": polydata,
|
|
196
|
+
"actor": actor,
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
# Set colors based on which planes the lines represent
|
|
200
|
+
if view_name == "axial":
|
|
201
|
+
view_crosshairs["line1"]["actor"].GetProperty().SetColor(
|
|
202
|
+
*colors.get("sagittal", (1, 0, 0))
|
|
203
|
+
)
|
|
204
|
+
view_crosshairs["line2"]["actor"].GetProperty().SetColor(
|
|
205
|
+
*colors.get("coronal", (0, 1, 0))
|
|
206
|
+
)
|
|
207
|
+
elif view_name == "sagittal":
|
|
208
|
+
view_crosshairs["line1"]["actor"].GetProperty().SetColor(
|
|
209
|
+
*colors.get("axial", (0, 0, 1))
|
|
210
|
+
)
|
|
211
|
+
view_crosshairs["line2"]["actor"].GetProperty().SetColor(
|
|
212
|
+
*colors.get("coronal", (0, 1, 0))
|
|
213
|
+
)
|
|
214
|
+
else: # coronal
|
|
215
|
+
view_crosshairs["line1"]["actor"].GetProperty().SetColor(
|
|
216
|
+
*colors.get("axial", (0, 0, 1))
|
|
217
|
+
)
|
|
218
|
+
view_crosshairs["line2"]["actor"].GetProperty().SetColor(
|
|
219
|
+
*colors.get("sagittal", (1, 0, 0))
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
crosshairs[view_name] = view_crosshairs
|
|
223
|
+
|
|
224
|
+
self._crosshair_actors = crosshairs
|
|
225
|
+
return crosshairs
|
|
226
|
+
|
|
227
|
+
@property
|
|
228
|
+
def crosshair_actors(self) -> dict:
|
|
229
|
+
"""Get crosshair actors."""
|
|
230
|
+
return self._crosshair_actors
|
|
231
|
+
|
|
232
|
+
def set_crosshairs_visible(self, visible: bool):
|
|
233
|
+
"""Set visibility of all crosshair actors."""
|
|
234
|
+
for view_crosshairs in self._crosshair_actors.values():
|
|
235
|
+
for line_data in view_crosshairs.values():
|
|
236
|
+
line_data["actor"].SetVisibility(visible)
|
|
237
|
+
|
|
137
238
|
def _get_mpr_coordinate_systems(self):
|
|
138
239
|
"""Get coordinate system transformation matrices for MPR views."""
|
|
139
240
|
view_axcodes = {
|
|
@@ -197,12 +298,54 @@ class Volume(Object):
|
|
|
197
298
|
|
|
198
299
|
return bounds
|
|
199
300
|
|
|
301
|
+
def _build_cumulative_rotation(
|
|
302
|
+
self, rotation_sequence: list, rotation_angles: dict
|
|
303
|
+
) -> np.ndarray:
|
|
304
|
+
"""Build cumulative rotation matrix from sequence of rotations."""
|
|
305
|
+
cumulative_rotation = np.eye(3)
|
|
306
|
+
if rotation_sequence and rotation_angles:
|
|
307
|
+
for i, rotation in enumerate(rotation_sequence):
|
|
308
|
+
angle = rotation_angles.get(i, 0)
|
|
309
|
+
rotation_matrix = euler_angle_to_rotation_matrix(
|
|
310
|
+
EulerAxis(rotation["axis"]), angle
|
|
311
|
+
)
|
|
312
|
+
cumulative_rotation = cumulative_rotation @ rotation_matrix
|
|
313
|
+
return cumulative_rotation
|
|
314
|
+
|
|
315
|
+
def get_scroll_vector(
|
|
316
|
+
self,
|
|
317
|
+
view_name: str,
|
|
318
|
+
rotation_sequence: list = None,
|
|
319
|
+
rotation_angles: dict = None,
|
|
320
|
+
) -> np.ndarray:
|
|
321
|
+
"""Get the current normal vector for a view after rotation.
|
|
322
|
+
|
|
323
|
+
Args:
|
|
324
|
+
view_name: One of "axial", "sagittal", "coronal"
|
|
325
|
+
rotation_sequence: List of rotation definitions
|
|
326
|
+
rotation_angles: Dict mapping rotation index to angle
|
|
327
|
+
|
|
328
|
+
Returns:
|
|
329
|
+
3D unit vector representing the scroll direction for this view
|
|
330
|
+
"""
|
|
331
|
+
base_normals = {
|
|
332
|
+
"axial": np.array([0.0, 0.0, 1.0]),
|
|
333
|
+
"sagittal": np.array([1.0, 0.0, 0.0]),
|
|
334
|
+
"coronal": np.array([0.0, 1.0, 0.0]),
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
if view_name not in base_normals:
|
|
338
|
+
return np.array([0.0, 0.0, 1.0])
|
|
339
|
+
|
|
340
|
+
cumulative_rotation = self._build_cumulative_rotation(
|
|
341
|
+
rotation_sequence, rotation_angles
|
|
342
|
+
)
|
|
343
|
+
return cumulative_rotation @ base_normals[view_name]
|
|
344
|
+
|
|
200
345
|
def update_slice_positions(
|
|
201
346
|
self,
|
|
202
347
|
frame: int,
|
|
203
|
-
|
|
204
|
-
sagittal_pos: float,
|
|
205
|
-
coronal_pos: float,
|
|
348
|
+
origin: list,
|
|
206
349
|
rotation_sequence: list = None,
|
|
207
350
|
rotation_angles: dict = None,
|
|
208
351
|
):
|
|
@@ -210,62 +353,36 @@ class Volume(Object):
|
|
|
210
353
|
|
|
211
354
|
Args:
|
|
212
355
|
frame: Frame index
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
356
|
+
origin: [x, y, z] position in LPS coordinates (shared by all views)
|
|
357
|
+
rotation_sequence: List of rotation definitions
|
|
358
|
+
rotation_angles: Dict mapping rotation index to angle
|
|
216
359
|
"""
|
|
217
360
|
if frame not in self._mpr_actors:
|
|
218
361
|
return
|
|
219
362
|
|
|
220
|
-
volume_actor = self._actors[frame]
|
|
221
|
-
image_data = volume_actor.GetMapper().GetInput()
|
|
222
|
-
bounds = image_data.GetBounds()
|
|
223
|
-
|
|
224
363
|
actors = self._mpr_actors[frame]
|
|
225
364
|
|
|
226
|
-
# Clamp positions to volume bounds
|
|
227
|
-
axial_pos = max(bounds[4], min(bounds[5], axial_pos)) # Z bounds
|
|
228
|
-
sagittal_pos = max(bounds[0], min(bounds[1], sagittal_pos)) # X bounds
|
|
229
|
-
coronal_pos = max(bounds[2], min(bounds[3], coronal_pos)) # Y bounds
|
|
230
|
-
|
|
231
365
|
# Get coordinate system transformations for each MPR view
|
|
232
366
|
transforms = self._get_mpr_coordinate_systems()
|
|
233
367
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
sagittal_origin = [sagittal_pos, center[1], center[2]]
|
|
239
|
-
coronal_origin = [center[0], coronal_pos, center[2]]
|
|
368
|
+
# Build cumulative rotation matrix
|
|
369
|
+
cumulative_rotation = self._build_cumulative_rotation(
|
|
370
|
+
rotation_sequence, rotation_angles
|
|
371
|
+
)
|
|
240
372
|
|
|
241
|
-
#
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
angle = rotation_angles.get(i, 0)
|
|
246
|
-
rotation_matrix = euler_angle_to_rotation_matrix(
|
|
247
|
-
EulerAxis(rotation["axis"]), angle
|
|
248
|
-
)
|
|
249
|
-
cumulative_rotation = cumulative_rotation @ rotation_matrix
|
|
373
|
+
# Apply rotation to base transforms
|
|
374
|
+
axial_transform = cumulative_rotation @ transforms["axial"]
|
|
375
|
+
sagittal_transform = cumulative_rotation @ transforms["sagittal"]
|
|
376
|
+
coronal_transform = cumulative_rotation @ transforms["coronal"]
|
|
250
377
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
sagittal_transform = cumulative_rotation @ transforms["sagittal"]
|
|
254
|
-
coronal_transform = cumulative_rotation @ transforms["coronal"]
|
|
255
|
-
else:
|
|
256
|
-
# Use base transforms without rotation
|
|
257
|
-
axial_transform = transforms["axial"]
|
|
258
|
-
sagittal_transform = transforms["sagittal"]
|
|
259
|
-
coronal_transform = transforms["coronal"]
|
|
260
|
-
|
|
261
|
-
# Update slices with translated origins and rotated transforms
|
|
262
|
-
axial_matrix = create_vtk_reslice_matrix(axial_transform, axial_origin)
|
|
378
|
+
# All views share the same origin
|
|
379
|
+
axial_matrix = create_vtk_reslice_matrix(axial_transform, origin)
|
|
263
380
|
actors["axial"]["reslice"].SetResliceAxes(axial_matrix)
|
|
264
381
|
|
|
265
|
-
sagittal_matrix = create_vtk_reslice_matrix(sagittal_transform,
|
|
382
|
+
sagittal_matrix = create_vtk_reslice_matrix(sagittal_transform, origin)
|
|
266
383
|
actors["sagittal"]["reslice"].SetResliceAxes(sagittal_matrix)
|
|
267
384
|
|
|
268
|
-
coronal_matrix = create_vtk_reslice_matrix(coronal_transform,
|
|
385
|
+
coronal_matrix = create_vtk_reslice_matrix(coronal_transform, origin)
|
|
269
386
|
actors["coronal"]["reslice"].SetResliceAxes(coronal_matrix)
|
|
270
387
|
|
|
271
388
|
def update_mpr_window_level(self, frame: int, window: float, level: float):
|
cardio/volume_property.py
CHANGED
cardio/window_level.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: cardio
|
|
3
|
-
Version: 2025.
|
|
3
|
+
Version: 2025.12.0
|
|
4
4
|
Summary: A simple web-based viewer for 3D and 4D ('cine') medical imaging data.
|
|
5
5
|
Keywords: Medical,Imaging,3D,4D,Visualization
|
|
6
6
|
Author: Davis Marc Vigneault
|
|
@@ -59,12 +59,11 @@ Description-Content-Type: text/markdown
|
|
|
59
59
|
`cardio` is a simple web-based viewer for 3D and 4D ('cine') medical imaging data,
|
|
60
60
|
built primarily on [trame](https://github.com/kitware/trame),
|
|
61
61
|
[vtk](https://github.com/kitware/vtk), and
|
|
62
|
-
[itk](https://github.com/insightsoftwareconsortium/itk). `cardio`
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
commandline
|
|
67
|
-
TOML configuration file, or a combination of the two.
|
|
62
|
+
[itk](https://github.com/insightsoftwareconsortium/itk). `cardio` can render sequences
|
|
63
|
+
of mesh files (e.g., `\*.obj` files), segmentation files (e.g., `\*nii.gz` files with
|
|
64
|
+
discrete labels) and volume renderings of grayscale images (e.g., `\*.nii.gz` files with
|
|
65
|
+
continuous values). `cardio` is launched from the commandline and may be configured via
|
|
66
|
+
commandline arguments, a static TOML configuration file, or a combination of the two.
|
|
68
67
|
|
|
69
68
|
## Quickstart
|
|
70
69
|
|
|
@@ -76,7 +75,7 @@ $ uv init
|
|
|
76
75
|
$ uv add cardio
|
|
77
76
|
$ . ./.venv/bin/activate
|
|
78
77
|
(project) cardio --version
|
|
79
|
-
cardio 2025.
|
|
78
|
+
cardio 2025.12.0
|
|
80
79
|
```
|
|
81
80
|
|
|
82
81
|
### Developing
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
cardio/__init__.py,sha256=laKThzytBHNMY_Z5Qy9-jF25NpfSyfDM9VGrG4bhJ14,602
|
|
2
|
+
cardio/app.py,sha256=h-Xh57Txw3Hom-fDv08YxjXzovuIxY8_5qPy6MJThZs,1354
|
|
3
|
+
cardio/assets/bone.toml,sha256=vv8uVYSHIoKuHkNCoBOkGe2_qoEbXMvQO6ypm3mMOtA,675
|
|
4
|
+
cardio/assets/vascular_closed.toml,sha256=XtaZS_Zd6NSAtY3ZlUfiog3T86u9Ii0oSutU2wBQy78,1267
|
|
5
|
+
cardio/assets/vascular_open.toml,sha256=1M3sV1IGt3zh_3vviysKEk9quKfjF9xUBcIq3kxVHFM,879
|
|
6
|
+
cardio/assets/xray.toml,sha256=siPem0OZ2OkWH0e5pizftpItJKGJgxKJ_S2K0316ubQ,693
|
|
7
|
+
cardio/blend_transfer_functions.py,sha256=fkLDYGMj_QXYs0vmXYT_B1tgTfl3YICLYimtWlxrmbQ,2958
|
|
8
|
+
cardio/color_transfer_function.py,sha256=uTyPdwxi0HjR4wm418cQN9-q9SspkkeqvLNqXaF3zzg,792
|
|
9
|
+
cardio/logic.py,sha256=e7OaroXgpq6oE3Zfa2afusVsEzopkpL4YdEGPuFINzc,39885
|
|
10
|
+
cardio/mesh.py,sha256=wYdU0BU84eXrrHp0U0VLwYW7ZpRJ6GbT5Kl_-K6CBzY,9356
|
|
11
|
+
cardio/object.py,sha256=98A32VpFR4UtVqW8dZsRJR13VVyUoJJ20uoOZBgN4js,6168
|
|
12
|
+
cardio/orientation.py,sha256=GRm6Ix3hzMXybgKgpJip0Mlodqn_LCV9VaGFjTAmS-A,6122
|
|
13
|
+
cardio/piecewise_function.py,sha256=X-_C-BVStufmFjfF8IbkqKk9Xw_jh00JUmjC22ZqeqQ,764
|
|
14
|
+
cardio/property_config.py,sha256=YrWIyCoSAfJPigkhriIQybQpJantGnXjT4nJfrtIJco,1689
|
|
15
|
+
cardio/scene.py,sha256=H_GxJ6Dq2QVx7RJYwwvleLL5M_egTzFd0bJ95TqtrhI,14530
|
|
16
|
+
cardio/screenshot.py,sha256=l8bLgxnU5O0FlnmsyVAzKwM9Y0401IzcdnDP0WqFSTY,640
|
|
17
|
+
cardio/segmentation.py,sha256=KT1ClgultXyGpZDdpYxor38GflY7uCgRzfA8JEGQVaU,6642
|
|
18
|
+
cardio/transfer_function_pair.py,sha256=_J0qXA0InUPpvfWPcW492KGSYAqeb12htCzKBSpWHwo,780
|
|
19
|
+
cardio/types.py,sha256=jxSZjvxEJ03OThfupT2CG9UHsFklwbWeFrUozNXro2I,333
|
|
20
|
+
cardio/ui.py,sha256=KwRGb_vDZ6pi8TQ82Ios7zcG9xmvd2hzCv45h0voNMM,50109
|
|
21
|
+
cardio/utils.py,sha256=tFUQ4FxfidTH6GjEIKQwguqhO9T_wJ2Vk0IhbEfxRGA,1616
|
|
22
|
+
cardio/volume.py,sha256=wKvEhjCGhnn8Se-VVNyurspfH9IgAvqp7Br_j0wUdDM,14536
|
|
23
|
+
cardio/volume_property.py,sha256=-EUMV9sWCaetgGjnqIWxPp39qrxEZKTNDJ5GHUgLMlk,1619
|
|
24
|
+
cardio/volume_property_presets.py,sha256=4-hjo-dukm5sMMmWidbWnVXq0IN4sWpBnDITY9MqUFg,1625
|
|
25
|
+
cardio/window_level.py,sha256=XMkwLAHcmsEYcI0SoHySQZvptq4VwX2gj--ps3hV8AQ,784
|
|
26
|
+
cardio-2025.12.0.dist-info/WHEEL,sha256=4n27za1eEkOnA7dNjN6C5-O2rUiw6iapszm14Uj-Qmk,79
|
|
27
|
+
cardio-2025.12.0.dist-info/entry_points.txt,sha256=xRd1otqKtW9xmidJ4CFRX1V9KWmsBbtxrgMtDColq3w,40
|
|
28
|
+
cardio-2025.12.0.dist-info/METADATA,sha256=y1706xsek2kYRBsXskEqYxAHdBl5ovdWOIkXULc572o,3522
|
|
29
|
+
cardio-2025.12.0.dist-info/RECORD,,
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
cardio/__init__.py,sha256=5lINeD9qQQm_u9eJfPIzdEMfYW62UZ2asOmQIS4PcFk,602
|
|
2
|
-
cardio/app.py,sha256=TEzgA03EAgI7HSCHhYwYb8tsnAptsrpcysV5CytfAq4,1379
|
|
3
|
-
cardio/assets/bone.toml,sha256=vv8uVYSHIoKuHkNCoBOkGe2_qoEbXMvQO6ypm3mMOtA,675
|
|
4
|
-
cardio/assets/vascular_closed.toml,sha256=XtaZS_Zd6NSAtY3ZlUfiog3T86u9Ii0oSutU2wBQy78,1267
|
|
5
|
-
cardio/assets/vascular_open.toml,sha256=1M3sV1IGt3zh_3vviysKEk9quKfjF9xUBcIq3kxVHFM,879
|
|
6
|
-
cardio/assets/xray.toml,sha256=siPem0OZ2OkWH0e5pizftpItJKGJgxKJ_S2K0316ubQ,693
|
|
7
|
-
cardio/blend_transfer_functions.py,sha256=s5U4hO810oE434wIkPmAP2mrAfqFb4xxxi3hHf_k8og,2982
|
|
8
|
-
cardio/color_transfer_function.py,sha256=KV4j11AXYeaYGeJWBc9I-WZf7Shrm5xjQVq-0bq9Qc8,817
|
|
9
|
-
cardio/logic.py,sha256=a73JJ2b8t-TYggYMGI1IGpn0Q6AFD8I1JNz9fn6QeDk,37557
|
|
10
|
-
cardio/mesh.py,sha256=xL4hadrVF3GVtMFxpq79DKApbmstZEI_HEwTAqc4ZMI,9391
|
|
11
|
-
cardio/object.py,sha256=fvLSZtWf1zDbYMh-AMpgVLwD-9S1LCzuRt7HmkXxb3A,6215
|
|
12
|
-
cardio/orientation.py,sha256=J3bqZbv8vfl4loGl7ksmuyqWb3zFAz-TVSIahKcg0pc,6145
|
|
13
|
-
cardio/piecewise_function.py,sha256=bwtwgrAMGkgu1krnvsOF9gRMaZb6smsS9jLrgBecSbo,789
|
|
14
|
-
cardio/property_config.py,sha256=XJYcKeRcq8s9W9jqxzVer75r5jBLuvebv780FYdPV8U,1723
|
|
15
|
-
cardio/scene.py,sha256=9jskdEARyJjk7QBIcMt5X2HsnikTAJdoRoLSI0LxcJE,14301
|
|
16
|
-
cardio/screenshot.py,sha256=l8bLgxnU5O0FlnmsyVAzKwM9Y0401IzcdnDP0WqFSTY,640
|
|
17
|
-
cardio/segmentation.py,sha256=QqeG2C3BVbO9fUJDSWf0mZXzgfrTx4LHWwaz4vtv8ZM,6677
|
|
18
|
-
cardio/transfer_function_pair.py,sha256=90PQXByCL6mMaODo7Yfd-lmdFtCKhcBZbNaiH-PTds0,805
|
|
19
|
-
cardio/types.py,sha256=DYDgA5QmYdU3QQrEgZMouEbMEIf40DJCeXo4V7cDXtg,356
|
|
20
|
-
cardio/ui.py,sha256=wsRujwiNtMeq65R4bx-myxSPDhJT0RskwvBWlGenmHk,42901
|
|
21
|
-
cardio/utils.py,sha256=tFUQ4FxfidTH6GjEIKQwguqhO9T_wJ2Vk0IhbEfxRGA,1616
|
|
22
|
-
cardio/volume.py,sha256=TxUfOvEoQw-kbEAQLSTfVOU3DhJjnjB8iy4qygCmVXA,10378
|
|
23
|
-
cardio/volume_property.py,sha256=6T2r67SSIDl8F6ZlQvgMCZESLxuXVVAUjOC50lgQEmk,1644
|
|
24
|
-
cardio/volume_property_presets.py,sha256=U2a2MnyCjryzOLEADs3OLSMMmAUnXq82mYK7OVXbQV0,1659
|
|
25
|
-
cardio/window_level.py,sha256=gjk39Iv6jMJ52y6jydOjxBZBsI1nZQMs2CdWWTshQoE,807
|
|
26
|
-
cardio-2025.10.0.dist-info/WHEEL,sha256=4n27za1eEkOnA7dNjN6C5-O2rUiw6iapszm14Uj-Qmk,79
|
|
27
|
-
cardio-2025.10.0.dist-info/entry_points.txt,sha256=xRd1otqKtW9xmidJ4CFRX1V9KWmsBbtxrgMtDColq3w,40
|
|
28
|
-
cardio-2025.10.0.dist-info/METADATA,sha256=VIqGgz8ueoxxEahbi1hshAnK90zWx_IUlyihRJHdwH8,3540
|
|
29
|
-
cardio-2025.10.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|