unveil-python 0.1.0__tar.gz → 0.2.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.1.0/src/unveil_python.egg-info → unveil_python-0.2.0}/PKG-INFO +1 -1
- {unveil_python-0.1.0 → unveil_python-0.2.0}/src/unveil/__init__.py +1 -1
- {unveil_python-0.1.0 → unveil_python-0.2.0}/src/unveil/core.py +52 -12
- {unveil_python-0.1.0 → unveil_python-0.2.0/src/unveil_python.egg-info}/PKG-INFO +1 -1
- {unveil_python-0.1.0 → unveil_python-0.2.0}/LICENSE +0 -0
- {unveil_python-0.1.0 → unveil_python-0.2.0}/README.md +0 -0
- {unveil_python-0.1.0 → unveil_python-0.2.0}/pyproject.toml +0 -0
- {unveil_python-0.1.0 → unveil_python-0.2.0}/setup.cfg +0 -0
- {unveil_python-0.1.0 → unveil_python-0.2.0}/src/unveil/__main__.py +0 -0
- {unveil_python-0.1.0 → unveil_python-0.2.0}/src/unveil_python.egg-info/SOURCES.txt +0 -0
- {unveil_python-0.1.0 → unveil_python-0.2.0}/src/unveil_python.egg-info/dependency_links.txt +0 -0
- {unveil_python-0.1.0 → unveil_python-0.2.0}/src/unveil_python.egg-info/requires.txt +0 -0
- {unveil_python-0.1.0 → unveil_python-0.2.0}/src/unveil_python.egg-info/top_level.txt +0 -0
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"""
|
|
3
3
|
Created on Tue Mar 4 13:03:28 2025
|
|
4
4
|
|
|
5
|
-
@author:
|
|
5
|
+
@author: DELINTE Nicolas
|
|
6
6
|
"""
|
|
7
7
|
import sys
|
|
8
8
|
import numpy as np
|
|
9
9
|
import nibabel as nib
|
|
10
10
|
import pyvista as pv
|
|
11
|
-
from pyvistaqt import QtInteractor
|
|
11
|
+
from pyvistaqt import QtInteractor
|
|
12
12
|
from PyQt6.QtCore import Qt
|
|
13
13
|
from PyQt6.QtGui import QAction
|
|
14
14
|
from PyQt6.QtWidgets import (QApplication, QWidget, QHBoxLayout, QVBoxLayout,
|
|
@@ -214,6 +214,10 @@ class TrkViewer(QWidget):
|
|
|
214
214
|
btn_screenshot = QPushButton("Screenshot")
|
|
215
215
|
btn_screenshot.clicked.connect(self.take_screenshot)
|
|
216
216
|
cam_layout.addWidget(btn_screenshot)
|
|
217
|
+
btn_gif = QPushButton("Create GIF")
|
|
218
|
+
btn_gif.setToolTip("This takes ~2min to save after animation end.")
|
|
219
|
+
btn_gif.clicked.connect(self.create_gif)
|
|
220
|
+
cam_layout.addWidget(btn_gif)
|
|
217
221
|
|
|
218
222
|
global_layout.addLayout(cam_layout)
|
|
219
223
|
|
|
@@ -396,16 +400,52 @@ class TrkViewer(QWidget):
|
|
|
396
400
|
def take_screenshot(self):
|
|
397
401
|
"""Take a screenshot of the current 3D view."""
|
|
398
402
|
options = QFileDialog.Options()
|
|
399
|
-
file_path, _ = QFileDialog.getSaveFileName(
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
"",
|
|
403
|
-
"PNG Image (*.png);;JPEG Image (*.jpg);;TIFF Image (*.tif)",
|
|
404
|
-
options=options
|
|
405
|
-
)
|
|
403
|
+
file_path, _ = QFileDialog.getSaveFileName(self, "Save Screenshot", "",
|
|
404
|
+
"PNG Image (*.png);;JPEG Image (*.jpg);;TIFF Image (*.tif)",
|
|
405
|
+
options=options)
|
|
406
406
|
if file_path:
|
|
407
407
|
self.plotter.screenshot(file_path, transparent_background=True)
|
|
408
408
|
|
|
409
|
+
def create_gif(self):
|
|
410
|
+
"""Create a 360° rotation GIF of the current 3D view."""
|
|
411
|
+
options = QFileDialog.Options()
|
|
412
|
+
file_path, _ = QFileDialog.getSaveFileName(self, "Save GIF", "",
|
|
413
|
+
"GIF Files (*.gif)",
|
|
414
|
+
options=options)
|
|
415
|
+
|
|
416
|
+
if not file_path:
|
|
417
|
+
return
|
|
418
|
+
|
|
419
|
+
# Ensure the file has a .gif extension
|
|
420
|
+
if not file_path.lower().endswith(".gif"):
|
|
421
|
+
file_path += ".gif"
|
|
422
|
+
|
|
423
|
+
# Use an offscreen plotter so the main one remains visible
|
|
424
|
+
offscreen = pv.Plotter(
|
|
425
|
+
off_screen=True, window_size=self.plotter.window_size)
|
|
426
|
+
|
|
427
|
+
# Copy all meshes and volumes from the main plotter to the offscreen one
|
|
428
|
+
for actor_name, actor in self.plotter.actors.items():
|
|
429
|
+
offscreen.add_actor(actor.copy())
|
|
430
|
+
|
|
431
|
+
# Match background color and camera
|
|
432
|
+
offscreen.background_color = self.plotter.background_color
|
|
433
|
+
offscreen.camera_position = self.plotter.camera_position
|
|
434
|
+
offscreen.camera.SetPosition(self.plotter.camera.GetPosition())
|
|
435
|
+
offscreen.camera.SetFocalPoint(self.plotter.camera.GetFocalPoint())
|
|
436
|
+
offscreen.camera.SetViewUp(self.plotter.camera.GetViewUp())
|
|
437
|
+
|
|
438
|
+
# Create the 360° rotation GIF
|
|
439
|
+
offscreen.open_gif(file_path, fps=20)
|
|
440
|
+
n_frames = 360
|
|
441
|
+
for i in range(n_frames):
|
|
442
|
+
offscreen.camera.Azimuth(360 / n_frames)
|
|
443
|
+
offscreen.render()
|
|
444
|
+
offscreen.write_frame()
|
|
445
|
+
self.plotter.camera.azimuth += 360 / n_frames
|
|
446
|
+
self.plotter.render()
|
|
447
|
+
offscreen.close()
|
|
448
|
+
|
|
409
449
|
def update_trk_viewer(self, reset_camera=False):
|
|
410
450
|
|
|
411
451
|
opacity = self.opacitySlider.value() / 100.0
|
|
@@ -508,8 +548,8 @@ class TrkViewer(QWidget):
|
|
|
508
548
|
opacity=opacity, name='gii_surface',
|
|
509
549
|
reset_camera=reset_camera)
|
|
510
550
|
else:
|
|
511
|
-
|
|
512
|
-
self.plotter.actors['gii_surface'].visibility = False
|
|
551
|
+
self.plotter.remove_actor('gii_surface', reset_camera=reset_camera)
|
|
552
|
+
# self.plotter.actors['gii_surface'].visibility = False
|
|
513
553
|
|
|
514
554
|
|
|
515
555
|
class MainWindow(QMainWindow):
|
|
@@ -518,7 +558,7 @@ class MainWindow(QMainWindow):
|
|
|
518
558
|
self.viewer = TrkViewer()
|
|
519
559
|
self.setCentralWidget(self.viewer)
|
|
520
560
|
self.initMenuBar()
|
|
521
|
-
self.setWindowTitle("Tractography Viewer
|
|
561
|
+
self.setWindowTitle("UNVEIL - Tractography Viewer")
|
|
522
562
|
|
|
523
563
|
def initMenuBar(self):
|
|
524
564
|
menubar = self.menuBar()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|