Skip to content

Commit

Permalink
ptycho+xrf GUI complete
Browse files Browse the repository at this point in the history
  • Loading branch information
stevehenke committed Oct 23, 2024
1 parent 3c522b2 commit 1b0f30d
Show file tree
Hide file tree
Showing 14 changed files with 718 additions and 457 deletions.
6 changes: 6 additions & 0 deletions ptychodus/api/fluorescence.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ class FluorescenceDataset:
# scan_indexes: IntegerArray


class FluorescenceEnhancingAlgorithm(ABC):
@abstractmethod
def enhance(self, dataset: FluorescenceDataset, product: Product) -> FluorescenceDataset:
pass


class FluorescenceFileReader(ABC):
@abstractmethod
def read(self, filePath: Path) -> FluorescenceDataset:
Expand Down
2 changes: 1 addition & 1 deletion ptychodus/controller/probe/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@

from ...model.analysis import (
ExposureAnalyzer,
FluorescenceEnhancer,
ProbePropagator,
STXMSimulator,
)
from ...model.fluorescence import FluorescenceEnhancer
from ...model.product import ProbeAPI, ProbeRepository
from ...model.product.probe import ProbeRepositoryItem
from ...model.visualization import VisualizationEngine
Expand Down
142 changes: 107 additions & 35 deletions ptychodus/controller/probe/fluorescence.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
from typing import Any
from decimal import Decimal
from typing import Any, Final
import logging

from PyQt5.QtCore import Qt, QAbstractListModel, QModelIndex, QObject, QStringListModel
from PyQt5.QtWidgets import QWidget

from ptychodus.api.observer import Observable, Observer

from ...model.analysis import FluorescenceEnhancer
from ...model.fluorescence import (
FluorescenceEnhancer,
TwoStepFluorescenceEnhancingAlgorithm,
VSPIFluorescenceEnhancingAlgorithm,
)
from ...model.visualization import VisualizationEngine
from ...view.probe import FluorescenceDialog
from ...view.probe import (
FluorescenceDialog,
FluorescenceTwoStepParametersView,
FluorescenceVSPIParametersView,
)
from ...view.widgets import ExceptionDialog
from ..data import FileDialogFactory
from ..visualization import (
Expand All @@ -33,6 +43,71 @@ def rowCount(self, parent: QModelIndex = QModelIndex()) -> int:
return self._enhancer.getNumberOfChannels()


class FluorescenceTwoStepViewController(Observer):
def __init__(self, algorithm: TwoStepFluorescenceEnhancingAlgorithm) -> None:
super().__init__()
self._algorithm = algorithm
self._view = FluorescenceTwoStepParametersView()

self._upscalingModel = QStringListModel()
self._upscalingModel.setStringList(self._algorithm.getUpscalingStrategyList())
self._view.upscalingStrategyComboBox.setModel(self._upscalingModel)
self._view.upscalingStrategyComboBox.textActivated.connect(algorithm.setUpscalingStrategy)

self._deconvolutionModel = QStringListModel()
self._deconvolutionModel.setStringList(self._algorithm.getDeconvolutionStrategyList())
self._view.deconvolutionStrategyComboBox.setModel(self._deconvolutionModel)
self._view.deconvolutionStrategyComboBox.textActivated.connect(
algorithm.setDeconvolutionStrategy
)

self._syncModelToView()
algorithm.addObserver(self)

def getWidget(self) -> QWidget:
return self._view

def _syncModelToView(self) -> None:
self._view.upscalingStrategyComboBox.setCurrentText(self._algorithm.getUpscalingStrategy())
self._view.deconvolutionStrategyComboBox.setCurrentText(
self._algorithm.getDeconvolutionStrategy()
)

def update(self, observable: Observable) -> None:
if observable is self._algorithm:
self._syncModelToView()


class FluorescenceVSPIViewController(Observer):
MAX_INT: Final[int] = 0x7FFFFFFF

def __init__(self, algorithm: VSPIFluorescenceEnhancingAlgorithm) -> None:
super().__init__()
self._algorithm = algorithm
self._view = FluorescenceVSPIParametersView()

self._view.dampingFactorLineEdit.valueChanged.connect(self._syncDampingFactorToModel)
self._view.maxIterationsSpinBox.setRange(1, self.MAX_INT)
self._view.maxIterationsSpinBox.valueChanged.connect(algorithm.setMaxIterations)

algorithm.addObserver(self)
self._syncModelToView()

def getWidget(self) -> QWidget:
return self._view

def _syncDampingFactorToModel(self, value: Decimal) -> None:
self._algorithm.setDampingFactor(float(value))

def _syncModelToView(self) -> None:
self._view.dampingFactorLineEdit.setValue(Decimal(repr(self._algorithm.getDampingFactor())))
self._view.maxIterationsSpinBox.setValue(self._algorithm.getMaxIterations())

def update(self, observable: Observable) -> None:
if observable is self._algorithm:
self._syncModelToView()


class FluorescenceViewController(Observer):
def __init__(
self,
Expand All @@ -46,43 +121,42 @@ def __init__(
self._fileDialogFactory = fileDialogFactory
self._dialog = FluorescenceDialog()
self._enhancementModel = QStringListModel()
self._enhancementModel.setStringList(self._enhancer.getEnhancementStrategyList())
# FIXME add vspiDampingFactor
# FIXME add vspiMaxIterations
self._upscalingModel = QStringListModel()
self._upscalingModel.setStringList(self._enhancer.getUpscalingStrategyList())
self._deconvolutionModel = QStringListModel()
self._deconvolutionModel.setStringList(self._enhancer.getDeconvolutionStrategyList())
self._enhancementModel.setStringList(self._enhancer.getAlgorithmList())
self._channelListModel = FluorescenceChannelListModel(enhancer)

self._dialog.fluorescenceParametersView.openButton.clicked.connect(
self._openMeasuredDataset
)

self._dialog.fluorescenceParametersView.enhancementStrategyComboBox.setModel(
self._enhancementModel
twoStepViewController = FluorescenceTwoStepViewController(
enhancer.twoStepEnhancingAlgorithm
)
self._dialog.fluorescenceParametersView.algorithmComboBox.addItem(
TwoStepFluorescenceEnhancingAlgorithm.DISPLAY_NAME,
self._dialog.fluorescenceParametersView.algorithmComboBox.count(),
)
self._dialog.fluorescenceParametersView.enhancementStrategyComboBox.textActivated.connect(
enhancer.setEnhancementStrategy
self._dialog.fluorescenceParametersView.stackedWidget.addWidget(
twoStepViewController.getWidget()
)

self._dialog.fluorescenceParametersView.upscalingStrategyComboBox.setModel(
self._upscalingModel
vspiViewController = FluorescenceVSPIViewController(enhancer.vspiEnhancingAlgorithm)
self._dialog.fluorescenceParametersView.algorithmComboBox.addItem(
VSPIFluorescenceEnhancingAlgorithm.DISPLAY_NAME,
self._dialog.fluorescenceParametersView.algorithmComboBox.count(),
)
self._dialog.fluorescenceParametersView.upscalingStrategyComboBox.textActivated.connect(
enhancer.setUpscalingStrategy
self._dialog.fluorescenceParametersView.stackedWidget.addWidget(
vspiViewController.getWidget()
)

self._dialog.fluorescenceParametersView.deconvolutionStrategyComboBox.setModel(
self._deconvolutionModel
self._dialog.fluorescenceParametersView.algorithmComboBox.textActivated.connect(
enhancer.setAlgorithm
)
self._dialog.fluorescenceParametersView.deconvolutionStrategyComboBox.textActivated.connect(
enhancer.setDeconvolutionStrategy
self._dialog.fluorescenceParametersView.algorithmComboBox.currentIndexChanged.connect(
self._dialog.fluorescenceParametersView.stackedWidget.setCurrentIndex
)

self._dialog.fluorescenceChannelListView.setModel(self._channelListModel)
self._dialog.fluorescenceChannelListView.selectionModel().currentChanged.connect(
self._updateView
self._dialog.fluorescenceParametersView.algorithmComboBox.setModel(self._enhancementModel)
self._dialog.fluorescenceParametersView.algorithmComboBox.textActivated.connect(
enhancer.setAlgorithm
)

self._dialog.fluorescenceParametersView.enhanceButton.clicked.connect(
Expand All @@ -92,6 +166,11 @@ def __init__(
self._saveEnhancedDataset
)

self._dialog.fluorescenceChannelListView.setModel(self._channelListModel)
self._dialog.fluorescenceChannelListView.selectionModel().currentChanged.connect(
self._updateView
)

self._measuredWidgetController = VisualizationWidgetController(
engine,
self._dialog.measuredWidget,
Expand Down Expand Up @@ -162,16 +241,9 @@ def _saveEnhancedDataset(self) -> None:
ExceptionDialog.showException(title, err)

def _syncModelToView(self) -> None:
self._dialog.fluorescenceParametersView.enhancementStrategyComboBox.setCurrentText(
self._enhancer.getEnhancementStrategy()
)
self._dialog.fluorescenceParametersView.upscalingStrategyComboBox.setCurrentText(
self._enhancer.getUpscalingStrategy()
self._dialog.fluorescenceParametersView.algorithmComboBox.setCurrentText(
self._enhancer.getAlgorithm()
)
self._dialog.fluorescenceParametersView.deconvolutionStrategyComboBox.setCurrentText(
self._enhancer.getDeconvolutionStrategy()
)

self._channelListModel.beginResetModel()
self._channelListModel.endResetModel()

Expand Down
2 changes: 0 additions & 2 deletions ptychodus/model/analysis/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from .core import AnalysisCore
from .exposure import ExposureAnalyzer, ExposureMap
from .fluorescence import FluorescenceEnhancer
from .frc import FourierRingCorrelator
from .objectInterpolator import ObjectLinearInterpolator
from .objectStitcher import ObjectStitcher
Expand All @@ -12,7 +11,6 @@
'AnalysisCore',
'ExposureAnalyzer',
'ExposureMap',
'FluorescenceEnhancer',
'FourierRingCorrelator',
'ObjectLinearInterpolator',
'ObjectStitcher',
Expand Down
42 changes: 1 addition & 41 deletions ptychodus/model/analysis/core.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,14 @@
from pathlib import Path
import logging

from ptychodus.api.fluorescence import (
DeconvolutionStrategy,
FluorescenceFileReader,
FluorescenceFileWriter,
UpscalingStrategy,
)
from ptychodus.api.plugins import PluginChooser
from ptychodus.api.settings import SettingsRegistry

from ..product import ObjectRepository, ProductRepository
from ..reconstructor import DiffractionPatternPositionMatcher
from ..visualization import VisualizationEngine
from .exposure import ExposureAnalyzer
from .fluorescence import FluorescenceEnhancer
from .frc import FourierRingCorrelator
from .propagator import ProbePropagator
from .settings import FluorescenceSettings, ProbePropagationSettings
from .settings import ProbePropagationSettings
from .stxm import STXMSimulator
from .xmcd import XMCDAnalyzer

Expand All @@ -31,10 +22,6 @@ def __init__(
dataMatcher: DiffractionPatternPositionMatcher,
productRepository: ProductRepository,
objectRepository: ObjectRepository,
upscalingStrategyChooser: PluginChooser[UpscalingStrategy],
deconvolutionStrategyChooser: PluginChooser[DeconvolutionStrategy],
fluorescenceFileReaderChooser: PluginChooser[FluorescenceFileReader],
fluorescenceFileWriterChooser: PluginChooser[FluorescenceFileWriter],
) -> None:
self.stxmSimulator = STXMSimulator(dataMatcher)
self.stxmVisualizationEngine = VisualizationEngine(isComplex=False)
Expand All @@ -46,32 +33,5 @@ def __init__(
self.exposureVisualizationEngine = VisualizationEngine(isComplex=False)
self.fourierRingCorrelator = FourierRingCorrelator(objectRepository)

self._fluorescenceSettings = FluorescenceSettings(settingsRegistry)
self.fluorescenceEnhancer = FluorescenceEnhancer(
self._fluorescenceSettings,
productRepository,
upscalingStrategyChooser,
deconvolutionStrategyChooser,
fluorescenceFileReaderChooser,
fluorescenceFileWriterChooser,
settingsRegistry,
)
self.fluorescenceVisualizationEngine = VisualizationEngine(isComplex=False)
self.xmcdAnalyzer = XMCDAnalyzer(objectRepository)
self.xmcdVisualizationEngine = VisualizationEngine(isComplex=False)

def enhanceFluorescence(
self, productIndex: int, inputFilePath: Path, outputFilePath: Path
) -> int:
fileType = 'XRF-Maps'

try:
self.fluorescenceEnhancer.setProduct(productIndex)
self.fluorescenceEnhancer.openMeasuredDataset(inputFilePath, fileType)
self.fluorescenceEnhancer.enhanceFluorescence()
self.fluorescenceEnhancer.saveEnhancedDataset(outputFilePath, fileType)
except Exception as exc:
logger.exception(exc)
return -1

return 0
Loading

0 comments on commit 1b0f30d

Please sign in to comment.