Skip to content

Commit

Permalink
Rework threading mechanism of PCA and NNMA plugins.
Browse files Browse the repository at this point in the history
  • Loading branch information
vasole committed Feb 17, 2025
1 parent 320823d commit 0e54070
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 36 deletions.
85 changes: 57 additions & 28 deletions src/PyMca5/PyMcaPlugins/NNMAStackPlugin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#/*##########################################################################
# Copyright (C) 2004-2023 European Synchrotron Radiation Facility
# Copyright (C) 2004-2025 European Synchrotron Radiation Facility
#
# This file is part of the PyMca X-ray Fluorescence Toolkit developed at
# the ESRF.
Expand Down Expand Up @@ -178,23 +178,10 @@ def calculate(self):
if ret:
self._executeFunctionAndParameters()

def _executeFunctionAndParameters(self):
_logger.debug("NNMAStackPlugin _executeFunctionAndParameters")
self.widget = None
self.thread = CalculationThread.CalculationThread(\
calculation_method=self.actualCalculation)
self.configurationWidget.show()
message = "Please wait. NNMA Calculation going on."
_logger.debug("NNMAStackPlugin starting thread")
self.thread.start()
_logger.debug("NNMAStackPlugin waitingMessageDialog")
CalculationThread.waitingMessageDialog(self.thread,
message=message,
parent=self.configurationWidget)
_logger.debug("NNMAStackPlugin waitingMessageDialog passed")
self.threadFinished()

def actualCalculation(self):
def _getFunctionAndParameters(self):
"""
Get the function, vars and kw for the calculation thread
"""
_logger.debug("NNMAStackPlugin actualCalculation")
nnmaParameters = self.configurationWidget.getParameters()
self._status.setText("Calculation going on")
Expand All @@ -216,6 +203,16 @@ def actualCalculation(self):
spatial_mask = numpy.isfinite(self.getStackOriginalImage())
ddict['mask'] = spatial_mask
del nnmaParameters
return function, None, ddict

def _executeFunctionAndParameters(self):
_logger.debug("_executeFunctionAndParameters")
self.widget = None
self.configurationWidget.show()
function, dummy, ddict = self._getFunctionAndParameters()
_logger.info("NNMA function %s" % function.__name__)
_logger.info("NNMA parameters %s" % ddict)

stack = self.getStackDataObject()
if isinstance(stack, numpy.ndarray):
if stack.data.dtype not in [numpy.float64, numpy.float32]:
Expand All @@ -236,18 +233,48 @@ def actualCalculation(self):
tmpData.shape = -1
data[:, i] = tmpData
data.shape = oldShape[1:] + oldShape[0:1]
result = function(data, **ddict)
data = None
else:
result = function(stack, **ddict)
if stack.data.shape != oldShape:
stack.data.shape = oldShape
return result
data = stack
try:
if _logger.getEffectiveLevel() == logging.DEBUG:
result = function(inputStack, **ddict)
self.threadFinished(result)
else:
thread = CalculationThread.CalculationThread(\
calculation_method=function,
calculation_vars=data,
calculation_kw=ddict,
expand_vars=False,
expand_kw=True)
thread.start()
message = "Please wait. NNMA Calculation going on."
_logger.debug("NNMAStackPlugin waitingMessageDialog")
CalculationThread.waitingMessageDialog(thread,
message=message,
parent=self.configurationWidget,
modal=True,
update_callback=None,
frameless=False)
_logger.debug("NNMAStackPlugin waitingMessageDialog passed")
result = thread.getResult()
self.threadFinished(result)
except Exception:
msg = qt.QMessageBox(self)
msg.setIcon(qt.QMessageBox.Critical)
msg.setWindowTitle("Calculation error")
msg.setText("Error on NNMA calculation")
msg.setInformativeText(str(sys.exc_info()[1]))
msg.setDetailedText(traceback.format_exc())
msg.exec()
finally:
if mcaIndex == 0:
data = None
else:
if stack.data.shape != oldShape:
stack.data.shape = oldShape

def threadFinished(self):
_logger.debug("NNMAStackPlugin threadFinished")
result = self.thread.result
self.thread = None
def threadFinished(self, result):
_logger.info("threadFinished")
if type(result) == type((1,)):
#if we receive a tuple there was an error
if len(result):
Expand All @@ -258,6 +285,8 @@ def threadFinished(self):
return
self._status.setText("Ready")
curve = self.configurationWidget.getSpectrum(binned=True)


if curve not in [None, []]:
xValues = curve[0]
else:
Expand Down
24 changes: 16 additions & 8 deletions src/PyMca5/PyMcaPlugins/PCAStackPlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,10 @@ def calculate(self):
self._kMeansWidget = None
self._executeFunctionAndParameters()


def _executeFunctionAndParameters(self):
self.widget = None
self.configurationWidget.show()

def _getFunctionAndParameters(self):
"""
Get the function, vars and kw for the calculation thread
"""
#obtain the parameters for the calculation
pcaParameters = self.configurationWidget.getParameters()
self._status.setText("Calculation going on")
Expand Down Expand Up @@ -215,6 +214,13 @@ def _executeFunctionAndParameters(self):
spatial_mask = numpy.isfinite(self.getStackOriginalImage())
pcaParameters['mask'] = spatial_mask
pcaParameters["legacy"] = False
return function, None, pcaParameters

def _executeFunctionAndParameters(self):
_logger.debug("_executeFunctionAndParameters")
self.widget = None
self.configurationWidget.show()
function, dummy, pcaParameters = self._getFunctionAndParameters()
_logger.info("PCA function %s" % function.__name__)
_logger.info("PCA parameters %s" % pcaParameters)
if "Multiple" in self.__methodlabel:
Expand Down Expand Up @@ -252,14 +258,14 @@ def _executeFunctionAndParameters(self):
parent=self.configurationWidget,
modal=True,
update_callback=None,
frameless=True)
frameless=False)
result = thread.getResult()
self.threadFinished(result)
except Exception:
msg = qt.QMessageBox(self)
msg.setIcon(qt.QMessageBox.Critical)
msg.setWindowTitle("Configuration error")
msg.setText("Error configuring fit:")
msg.setWindowTitle("Calculation error")
msg.setText("Error on PCA calculation")
msg.setInformativeText(str(sys.exc_info()[1]))
msg.setDetailedText(traceback.format_exc())
msg.exec()
Expand All @@ -272,6 +278,7 @@ def _executeFunctionAndParameters(self):
stack.data.shape = oldShape

def threadFinished(self, result):
_logger.info("threadFinished")
if type(result) == type((1,)):
#if we receive a tuple there was an error
if len(result):
Expand All @@ -281,6 +288,7 @@ def threadFinished(self, result):
raise Exception(result[1], result[2])
return
self._status.setText("Ready")

curve = self.configurationWidget.getSpectrum(binned=True)
if curve not in [None, []]:
xValues = curve[0]
Expand Down

0 comments on commit 0e54070

Please sign in to comment.