unveil-python 0.6.0__tar.gz → 0.7.0__tar.gz
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.
- {unveil_python-0.6.0/src/unveil_python.egg-info → unveil_python-0.7.0}/PKG-INFO +2 -1
- {unveil_python-0.6.0 → unveil_python-0.7.0}/pyproject.toml +2 -1
- {unveil_python-0.6.0 → unveil_python-0.7.0}/src/unveil/__init__.py +1 -1
- {unveil_python-0.6.0 → unveil_python-0.7.0}/src/unveil/core.py +87 -49
- {unveil_python-0.6.0 → unveil_python-0.7.0/src/unveil_python.egg-info}/PKG-INFO +2 -1
- {unveil_python-0.6.0 → unveil_python-0.7.0}/src/unveil_python.egg-info/requires.txt +1 -0
- {unveil_python-0.6.0 → unveil_python-0.7.0}/LICENSE +0 -0
- {unveil_python-0.6.0 → unveil_python-0.7.0}/README.md +0 -0
- {unveil_python-0.6.0 → unveil_python-0.7.0}/setup.cfg +0 -0
- {unveil_python-0.6.0 → unveil_python-0.7.0}/src/unveil/__main__.py +0 -0
- {unveil_python-0.6.0 → unveil_python-0.7.0}/src/unveil_python.egg-info/SOURCES.txt +0 -0
- {unveil_python-0.6.0 → unveil_python-0.7.0}/src/unveil_python.egg-info/dependency_links.txt +0 -0
- {unveil_python-0.6.0 → unveil_python-0.7.0}/src/unveil_python.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: unveil-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Implementation of UNVEIL
|
|
5
5
|
Author-email: Nicolas Delinte <nicolas.delinte@uclouvain.be>
|
|
6
6
|
License-Expression: GPL-3.0-only
|
|
@@ -15,6 +15,7 @@ Requires-Dist: dipy
|
|
|
15
15
|
Requires-Dist: pyvista
|
|
16
16
|
Requires-Dist: pyvistaqt
|
|
17
17
|
Requires-Dist: PyQt6
|
|
18
|
+
Requires-Dist: binama
|
|
18
19
|
Dynamic: license-file
|
|
19
20
|
|
|
20
21
|
# UNVEIL
|
|
@@ -186,6 +186,24 @@ def plot_trk(trk_file, scalar=None, color_map='plasma', opacity: float = 1,
|
|
|
186
186
|
|
|
187
187
|
p.background_color = background
|
|
188
188
|
|
|
189
|
+
def load_gii_data(gii_path):
|
|
190
|
+
"""
|
|
191
|
+
Load all data contained in the GifTi file except vertex coordinates and triangles.
|
|
192
|
+
Returns : dictionnary {"Gii table name" : data}
|
|
193
|
+
"""
|
|
194
|
+
gii_img = nib.load(gii_path)
|
|
195
|
+
vertex_coords = gii_img.get_arrays_from_intent("NIFTI_INTENT_POINTSET")[0].data
|
|
196
|
+
gii_data = {}
|
|
197
|
+
|
|
198
|
+
# Iterate over all tables of the GIfTI
|
|
199
|
+
for darray in gii_img.darrays:
|
|
200
|
+
# Vertex coords and triangles are stored with None as 'Name'
|
|
201
|
+
if darray.meta.get("Name") is not None:
|
|
202
|
+
# Check that the table contains 1 value per vertex
|
|
203
|
+
if darray.data.shape == vertex_coords[:,0].shape:
|
|
204
|
+
gii_data[darray.meta.get("Name")] = darray.data
|
|
205
|
+
|
|
206
|
+
return gii_data
|
|
189
207
|
|
|
190
208
|
class TrkViewer(QWidget):
|
|
191
209
|
def __init__(self):
|
|
@@ -423,7 +441,7 @@ class TrkViewer(QWidget):
|
|
|
423
441
|
self.giiColorModeComboBox = QComboBox()
|
|
424
442
|
self.giiColorModeComboBox.addItems(['Solid', 'NIfTI values'])
|
|
425
443
|
self.giiColorModeComboBox.currentIndexChanged.connect(
|
|
426
|
-
self.update_gii_viewer)
|
|
444
|
+
lambda index: self.update_gii_viewer(update_color_range=True))
|
|
427
445
|
color_mode_gii_row.addWidget(self.giiColorModeComboBox)
|
|
428
446
|
gii_layout.addLayout(color_mode_gii_row)
|
|
429
447
|
|
|
@@ -500,38 +518,47 @@ class TrkViewer(QWidget):
|
|
|
500
518
|
options = QFileDialog.Options()
|
|
501
519
|
filePath, _ = QFileDialog.getOpenFileName(
|
|
502
520
|
self, "Open .nii.gz File", "", "Nifti Files (*.nii.gz)", options=options)
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
521
|
+
|
|
522
|
+
if not filePath:
|
|
523
|
+
return
|
|
524
|
+
|
|
525
|
+
print(f"Loaded NIfTI file: {filePath}")
|
|
526
|
+
img = nib.load(filePath)
|
|
527
|
+
self.nii_affine = img.affine
|
|
528
|
+
self.nii_data = img.get_fdata()
|
|
508
529
|
|
|
509
|
-
|
|
510
|
-
self.update_surface_color_range_from_nifti()
|
|
530
|
+
self.update_volume_color_range_from_nifti()
|
|
511
531
|
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
532
|
+
grid = pv.ImageData()
|
|
533
|
+
grid.dimensions = np.array(self.nii_data.shape) + 1
|
|
534
|
+
grid.cell_data['values'] = self.nii_data.flatten(order='F')
|
|
535
|
+
self.grid = grid
|
|
516
536
|
|
|
517
537
|
self.XSlider.setMaximum(self.nii_data.shape[0])
|
|
518
538
|
self.YSlider.setMaximum(self.nii_data.shape[1])
|
|
519
539
|
self.ZSlider.setMaximum(self.nii_data.shape[2])
|
|
520
540
|
|
|
521
541
|
self.update_nii_viewer(reset_camera=False)
|
|
542
|
+
|
|
543
|
+
# Dilation for surface
|
|
544
|
+
self.nii_data_dilated = dilate_atlas_labels(
|
|
545
|
+
self.nii_data, dilation_width=4)
|
|
546
|
+
self.nii_data_dilated = np.where(self.nii_data_dilated == 0, np.nan,
|
|
547
|
+
self.nii_data_dilated)
|
|
548
|
+
|
|
522
549
|
if hasattr(self, "gii_mesh"):
|
|
550
|
+
# Sample NIfTI values at each surface vertex
|
|
551
|
+
self.nii_surface_values = self.sample_nifti_on_surface(self.gii_mesh)
|
|
523
552
|
self.update_gii_viewer(reset_camera=False)
|
|
553
|
+
else:
|
|
554
|
+
self.nii_surface_values = None
|
|
524
555
|
self.window().refreshActorList()
|
|
525
556
|
|
|
526
557
|
# Update 2D view with current colormap
|
|
527
558
|
ortho_data = self.nii_data.copy()
|
|
528
559
|
ortho_data[ortho_data == 0] = None
|
|
529
560
|
|
|
530
|
-
|
|
531
|
-
self.nii_data_dilated = dilate_atlas_labels(
|
|
532
|
-
self.nii_data, dilation_width=4)
|
|
533
|
-
self.nii_data_dilated = np.where(self.nii_data_dilated == 0, np.nan,
|
|
534
|
-
self.nii_data_dilated)
|
|
561
|
+
|
|
535
562
|
|
|
536
563
|
self.window().ortho_viewer.set_volume(ortho_data, self.nii_affine)
|
|
537
564
|
self.window().ortho_viewer.set_colormap(self.niiColorMapComboBox.currentText())
|
|
@@ -577,14 +604,8 @@ class TrkViewer(QWidget):
|
|
|
577
604
|
|
|
578
605
|
def loadGiftiFile(self):
|
|
579
606
|
options = QFileDialog.Options()
|
|
580
|
-
|
|
581
607
|
filePath, _ = QFileDialog.getOpenFileName(
|
|
582
|
-
self,
|
|
583
|
-
"Open .gii File",
|
|
584
|
-
"",
|
|
585
|
-
"Gifti Files (*.gii)",
|
|
586
|
-
options=options
|
|
587
|
-
)
|
|
608
|
+
self, "Open .gii File", "", "Gifti Files (*.gii)", options=options)
|
|
588
609
|
|
|
589
610
|
if not filePath:
|
|
590
611
|
return
|
|
@@ -593,8 +614,24 @@ class TrkViewer(QWidget):
|
|
|
593
614
|
|
|
594
615
|
self.gii_mesh = gifti_to_pyvista(filePath)
|
|
595
616
|
|
|
617
|
+
self.gii_data = load_gii_data(filePath)
|
|
618
|
+
|
|
619
|
+
self.giiColorModeComboBox.setCurrentIndex(0)
|
|
620
|
+
|
|
621
|
+
for _ in range(self.giiColorModeComboBox.count()-2):
|
|
622
|
+
self.giiColorModeComboBox.removeItem(2)
|
|
623
|
+
|
|
624
|
+
self.giiColorModeComboBox.addItems(list(self.gii_data.keys()))
|
|
625
|
+
|
|
596
626
|
self.actor_types["gii_surface"] = "gii"
|
|
597
627
|
|
|
628
|
+
if hasattr(self, "nii_data"):
|
|
629
|
+
# Sample NIfTI values at each surface vertex
|
|
630
|
+
self.nii_surface_values = self.sample_nifti_on_surface(self.gii_mesh)
|
|
631
|
+
self.update_gii_viewer(reset_camera=False)
|
|
632
|
+
else:
|
|
633
|
+
self.nii_surface_values = None
|
|
634
|
+
|
|
598
635
|
self.update_gii_viewer(reset_camera=False)
|
|
599
636
|
self.window().refreshActorList()
|
|
600
637
|
|
|
@@ -740,7 +777,7 @@ class TrkViewer(QWidget):
|
|
|
740
777
|
reset_camera=reset_camera, clim=[vmin, vmax],
|
|
741
778
|
user_matrix=self.nii_affine)
|
|
742
779
|
|
|
743
|
-
def update_gii_viewer(self, reset_camera=False):
|
|
780
|
+
def update_gii_viewer(self, reset_camera=False, update_color_range = False):
|
|
744
781
|
"""Update the GIFTI surface rendering."""
|
|
745
782
|
|
|
746
783
|
if not hasattr(self, "gii_mesh"):
|
|
@@ -760,28 +797,29 @@ class TrkViewer(QWidget):
|
|
|
760
797
|
reset_camera=reset_camera,
|
|
761
798
|
point_size=0, render_lines_as_tubes=True)
|
|
762
799
|
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
opacity=opacity, name="gii_surface",
|
|
769
|
-
reset_camera=reset_camera,
|
|
770
|
-
point_size=0, render_lines_as_tubes=True)
|
|
771
|
-
return
|
|
772
|
-
|
|
773
|
-
# Sample NIfTI values at each surface vertex
|
|
774
|
-
scalars = self.sample_nifti_on_surface(self.gii_mesh)
|
|
800
|
+
else:
|
|
801
|
+
if color_mode == "NIfTI values":
|
|
802
|
+
scalars = self.nii_surface_values
|
|
803
|
+
else:
|
|
804
|
+
scalars = self.gii_data[color_mode]
|
|
775
805
|
|
|
776
806
|
if scalars is None:
|
|
807
|
+
self.plotter.add_mesh(self.gii_mesh, color="ghostwhite",
|
|
808
|
+
culling="back", smooth_shading=True,
|
|
809
|
+
opacity=opacity, name="gii_surface",
|
|
810
|
+
reset_camera=reset_camera,
|
|
811
|
+
point_size=0, render_lines_as_tubes=True)
|
|
777
812
|
return
|
|
778
813
|
|
|
779
814
|
# Copy the mesh so that the original GIFTI mesh is not modified
|
|
780
815
|
surface_mesh = self.gii_mesh.copy(deep=True)
|
|
781
|
-
surface_mesh.point_data[
|
|
816
|
+
surface_mesh.point_data[color_mode] = scalars
|
|
782
817
|
|
|
783
818
|
cmap_name = self.giiColorMapComboBox.currentText()
|
|
784
819
|
|
|
820
|
+
if update_color_range:
|
|
821
|
+
self.update_surface_color_range(scalars)
|
|
822
|
+
|
|
785
823
|
vmin = self.giiMinSpinBox.value()
|
|
786
824
|
vmax = self.giiMaxSpinBox.value()
|
|
787
825
|
|
|
@@ -789,13 +827,13 @@ class TrkViewer(QWidget):
|
|
|
789
827
|
if vmax <= vmin:
|
|
790
828
|
vmax = vmin + 1e-6
|
|
791
829
|
|
|
792
|
-
self.plotter.add_mesh(surface_mesh, scalars=
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
830
|
+
self.plotter.add_mesh(surface_mesh, scalars=color_mode,
|
|
831
|
+
cmap=cmap_name, clim=[vmin, vmax],
|
|
832
|
+
culling="back", smooth_shading=True,
|
|
833
|
+
opacity=opacity, name="gii_surface",
|
|
834
|
+
reset_camera=reset_camera, point_size=0,
|
|
835
|
+
render_lines_as_tubes=True,
|
|
836
|
+
show_scalar_bar=False)
|
|
799
837
|
|
|
800
838
|
self.plotter.render()
|
|
801
839
|
|
|
@@ -829,12 +867,12 @@ class TrkViewer(QWidget):
|
|
|
829
867
|
self.niiMinSpinBox.blockSignals(False)
|
|
830
868
|
self.niiMaxSpinBox.blockSignals(False)
|
|
831
869
|
|
|
832
|
-
def
|
|
870
|
+
def update_surface_color_range(self,data):
|
|
833
871
|
|
|
834
|
-
if
|
|
872
|
+
if data is None:
|
|
835
873
|
return
|
|
836
874
|
|
|
837
|
-
data = np.asarray(
|
|
875
|
+
data = np.asarray(data, dtype=float)
|
|
838
876
|
finite = np.isfinite(data)
|
|
839
877
|
|
|
840
878
|
if not np.any(finite):
|
|
@@ -997,7 +1035,7 @@ class TrkViewer(QWidget):
|
|
|
997
1035
|
"""Enable surface scalar controls only when using NIfTI values."""
|
|
998
1036
|
|
|
999
1037
|
use_nifti = (self.giiColorModeComboBox.currentText()
|
|
1000
|
-
|
|
1038
|
+
!= "Solid")
|
|
1001
1039
|
|
|
1002
1040
|
self.giiColorMapLabel.setEnabled(use_nifti)
|
|
1003
1041
|
self.giiColorMapComboBox.setEnabled(use_nifti)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: unveil-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Implementation of UNVEIL
|
|
5
5
|
Author-email: Nicolas Delinte <nicolas.delinte@uclouvain.be>
|
|
6
6
|
License-Expression: GPL-3.0-only
|
|
@@ -15,6 +15,7 @@ Requires-Dist: dipy
|
|
|
15
15
|
Requires-Dist: pyvista
|
|
16
16
|
Requires-Dist: pyvistaqt
|
|
17
17
|
Requires-Dist: PyQt6
|
|
18
|
+
Requires-Dist: binama
|
|
18
19
|
Dynamic: license-file
|
|
19
20
|
|
|
20
21
|
# UNVEIL
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|