Source code for napari_locan.widgets.widget_smlm_data
"""
The data model for localization-based SMLM data.
QWidget plugin to access SMLM datasets from which images are rendered
and localization-based analysis procedures are computed.
Each dataset is kept as locdata, i.e. a locan.LocData object with metadata,
aggregated properties, and localization properties for all localizations.
"""
import logging
from pathlib import Path
import locan as lc
from napari.viewer import Viewer
from qtpy.QtWidgets import (
QComboBox,
QFileDialog,
QHBoxLayout,
QMessageBox,
QPushButton,
QVBoxLayout,
QWidget,
)
from napari_locan import smlm_data
from napari_locan.data_model.smlm_data import SmlmData
logger = logging.getLogger(__name__)
[docs]
class SmlmDataQWidget(QWidget): # type: ignore
def __init__(self, napari_viewer: Viewer, smlm_data: SmlmData = smlm_data):
super().__init__()
self.viewer = napari_viewer
self.smlm_data = smlm_data
self._add_locdatas_combobox()
self._add_buttons()
self._set_layout()
def _add_locdatas_combobox(self) -> None:
self._locdatas_combobox = QComboBox()
self._connect_locdatas_combobox_and_smlm_data()
self._locdatas_layout = QHBoxLayout()
self._locdatas_layout.addWidget(self._locdatas_combobox)
def _connect_locdatas_combobox_and_smlm_data(self) -> None:
self.smlm_data.locdata_names_changed_signal.connect(
self._synchronize_smlm_data_to_combobox
)
self.smlm_data.locdata_names_changed_signal.emit(self.smlm_data.locdata_names)
self.smlm_data.index_changed_signal.connect(
self._locdatas_combobox.setCurrentIndex
)
self.smlm_data.index_changed_signal.emit(self.smlm_data.index)
self._locdatas_combobox.currentIndexChanged.connect(
self.smlm_data.set_index_slot
)
def _synchronize_smlm_data_to_combobox(self, locdata_names: list[str]) -> None:
current_index = self.smlm_data.index
self._locdatas_combobox.clear()
self._locdatas_combobox.addItems(locdata_names)
self._locdatas_combobox.setCurrentIndex(current_index)
def _add_buttons(self) -> None:
self._save_button = QPushButton("Save")
self._save_button.setToolTip("Save SMLM dataset as ASDF file.")
self._save_button.clicked.connect(self._save_button_on_click)
self._delete_all_button = QPushButton("Delete all")
self._delete_all_button.setToolTip("Delete all SMLM data.")
self._delete_all_button.clicked.connect(self._delete_all_button_on_click)
self._delete_button = QPushButton("Delete")
self._delete_button.setToolTip("Delete SMLM dataset.")
self._delete_button.clicked.connect(self._delete_button_on_click)
self._buttons_layout = QHBoxLayout()
self._buttons_layout.addWidget(self._delete_all_button)
self._buttons_layout.addWidget(self._delete_button)
self._buttons_layout.addWidget(self._save_button)
def _set_layout(self) -> None:
layout = QVBoxLayout()
layout.addLayout(self._buttons_layout)
layout.addLayout(self._locdatas_layout)
self.setLayout(layout)
def _delete_button_on_click(self) -> None:
self.smlm_data.delete_item()
def _delete_all_button_on_click(self) -> None:
msgBox = QMessageBox()
msgBox.setText("Do you really want to delete ALL datasets?")
msgBox.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) # type: ignore[attr-defined]
msgBox.setDefaultButton(QMessageBox.Cancel) # type: ignore[attr-defined]
return_value = msgBox.exec()
if return_value == QMessageBox.Ok: # type: ignore[attr-defined]
self.smlm_data.delete_all()
else:
return
def _save_button_on_click(self) -> None:
current_index = self._locdatas_combobox.currentIndex()
if current_index == -1:
raise KeyError("No item available to be saved.")
else:
file_dialog = QFileDialog()
file_dialog.setFileMode(QFileDialog.AnyFile) # type: ignore[attr-defined]
file_path_return = file_dialog.getSaveFileName(
caption="Provide file name and path to save data",
filter="ASDF file (*.asdf)",
)
file_path = Path(file_path_return[0])
print("Save SmlmDdata at:", file_path)
if file_path:
lc.save_asdf(locdata=self.smlm_data.locdata, path=file_path) # type: ignore[arg-type]