Source code for populse_mia.user_interface.data_viewer.anatomist.mia_anatomist
"""
Mia data viewer implementation based on `Anatomist
<http://brainvisa.info/anatomist/user_doc/index.html>`_
Contains:
Class:
- MiaViewer
"""
#############################################################################
# Populse_mia - Copyright (C) IRMaGe/CEA, 2018
# Distributed under the terms of the CeCILL license, as published by
# the CEA-CNRS-INRIA. Refer to the LICENSE file or to
# http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.html
# for details.
#############################################################################
import logging
import os
from soma.qt_gui.qt_backend import Qt
from populse_mia.data_manager.project import COLLECTION_CURRENT, TAG_FILENAME
from populse_mia.user_interface.data_browser.data_browser import (
TableDataBrowser,
)
from ..data_viewer import DataViewer
logger = logging.getLogger(__name__)
try:
from anatomist.simpleviewer.anasimpleviewer import AnaSimpleViewer
except ImportError:
logger.warning(
"Anatomist seems not to be installed. The data_viewer anatomist "
"and anatomist_2 will not work..."
)
[docs]
class MiaViewer(DataViewer):
"""
A data viewer for Mia (Multiparametric Image Analysis) using PyAnatomist.
This class provides a specialized viewer for displaying and managing
medical imaging files with additional filtering and visualization
capabilities.
:class:`Mia data viewer <populse_mia.user_interface.data_viewer.data_viewer.DataViewer>` # noqa: E501
implementation based on `PyAnatomist <http://brainvisa.info/pyanatomist/sphinx/index.html>`_ # noqa: E501
.. Methods:
- _find_child: Find a child widget by name.
- _setup_ui: Set up the user interface components for the viewer.
- display_files: Display the given files in the Anatomist viewer.
- displayed_files: Get the list of currently displayed files.
- remove_files: Remove specified files from the viewer.
- set_documents: Set the current project and documents for the viewer.
- filter_documents: Open a dialog to filter and select documents for
visualization.
- close: Close the viewer and manage Anatomist viewer resources.
"""
[docs]
def __init__(self, init_global_handlers=None):
"""
Initialize the MiaViewer.
:param init_global_handlers: Initial global handlers for Anatomist
viewer.
"""
super().__init__()
# Initialize Anatomist viewer
self.anaviewer = AnaSimpleViewer(init_global_handlers)
# Count global number of viewers using anatomist, in order to close it
# nicely
if not hasattr(DataViewer, "mia_viewers"):
DataViewer.mia_viewers = 0
DataViewer.mia_viewers += 1
# Set up UI components
self._setup_ui()
# Initialize project-related attributes
self.project = None
self.displayed = []
self.documents = []
self.disp_find_childlayed = []
@staticmethod
def _find_child(parent, name):
"""
Find a child widget by name.
:param parent (Qt.QObject): Parent widget to search in.
:param name (str): Name of the child widget to find.
:return (Qt.QObject): The found child widget.
"""
return parent.findChild(Qt.QObject, name)
def _setup_ui(self):
"""
Set up the user interface components for the viewer.
"""
# Find and modify the toolbar
awidget = self.anaviewer.awidget
toolbar = self._find_child(awidget, "toolBar")
open_action = self._find_child(awidget, "fileOpenAction")
# Add custom filter action
db_action = Qt.QAction(open_action.icon(), "Filter", awidget)
toolbar.insertAction(open_action, db_action)
db_action.triggered.connect(self.filter_documents)
# Set up layout
layout = Qt.QVBoxLayout()
self.setLayout(layout)
# Configure Anatomist widget
self.anaviewer.awidget.setSizePolicy(
Qt.QSizePolicy.Expanding, Qt.QSizePolicy.Expanding
)
layout.addWidget(self.anaviewer.awidget)
[docs]
def display_files(self, files):
"""
Display the given files in the Anatomist viewer.
:param files (list): List of file paths to display.
"""
self.displayed.extend(files)
for filename in files:
self.anaviewer.loadObject(filename)
[docs]
def displayed_files(self):
"""
Get the list of currently displayed files.
:return (List): List of displayed file paths.
"""
return self.displayed
[docs]
def remove_files(self, files):
"""
Remove specified files from the viewer.
:param files (list): List of file paths to remove.
"""
self.anaviewer.deleteObjectsFromFiles(files)
self.files = [doc for doc in self.displayed if doc not in files]
[docs]
def set_documents(self, project, documents):
"""
Set the current project and documents for the viewer.
:param project: The project to set.
:param documents (List): List of documents in the project.
"""
if self.project is not project:
self.clear()
self.project = project
self.documents = documents
[docs]
def filter_documents(self):
"""Open a dialog to filter and select documents for visualization."""
# Create filter dialog
dialog = Qt.QDialog()
layout = Qt.QVBoxLayout()
dialog.setLayout(layout)
with self.project.database.data() as database_data:
# Create table data browser
table_data = TableDataBrowser(
self.project,
self,
database_data.get_shown_tags(),
False,
True,
link_viewer=False,
)
layout.addWidget(table_data)
# Add dialog buttons
hlay = Qt.QHBoxLayout()
layout.addLayout(hlay)
ok = Qt.QPushButton("Display")
hlay.addWidget(ok)
ok.clicked.connect(dialog.accept)
ok.setDefault(True)
cancel = Qt.QPushButton("Cancel")
hlay.addWidget(cancel)
cancel.clicked.connect(dialog.reject)
hlay.addStretch(1)
# Prepare table data
all_scans = table_data.scans_to_visualize
table_data.scans_to_visualize = self.documents
table_data.scans_to_search = self.documents
table_data.update_visualized_rows(all_scans)
# Execute dialog
if dialog.exec_() == Qt.QDialog.Accepted:
# Process selected files
result_names = []
with self.project.database.data() as database_data:
for point in table_data.selectedIndexes():
row = point.row()
# We get the FileName of the scan from the first row
scan_name = table_data.item(row, 0).text()
value = database_data.get_value(
COLLECTION_CURRENT, scan_name, TAG_FILENAME
)
full_path = os.path.abspath(
os.path.join(self.project.folder, value)
)
result_names.append(full_path)
self.display_files(result_names)
[docs]
def close(self):
"""Close the viewer and manage Anatomist viewer resources."""
super().close()
# Decrement viewer count
DataViewer.mia_viewers -= 1 # dec count
close_ana = DataViewer.mia_viewers == 0
self.anaviewer.closeAll(close_ana)