Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MacOS] [ROI Imaging] Rework threading mechanism #1102

Merged
merged 2 commits into from
Feb 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
86 changes: 55 additions & 31 deletions src/PyMca5/PyMcaPlugins/PCAStackPlugin.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 @@ -181,25 +181,11 @@ def calculate(self):
self._kMeansWidget = None
self._executeFunctionAndParameters()

def _executeFunctionAndParameters(self):
self.widget = None
self.configurationWidget.show()
if _logger.getEffectiveLevel() == logging.DEBUG:
self.thread = CalculationThread.CalculationThread(\
calculation_method=self.actualCalculation)
self.thread.result = self.actualCalculation()
self.threadFinished()
else:
self.thread = CalculationThread.CalculationThread(\
calculation_method=self.actualCalculation)
self.thread.start()
message = "Please wait. PCA Calculation going on."
CalculationThread.waitingMessageDialog(self.thread,
message=message,
parent=self.configurationWidget)
self.threadFinished()

def actualCalculation(self):
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")
self.configurationWidget.setEnabled(False)
Expand Down Expand Up @@ -228,17 +214,21 @@ def actualCalculation(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:
stackList = self.getStackDataObjectList()
oldShapes = []
for stack in stackList:
oldShapes.append(stack.data.shape)
result = function(stackList, **pcaParameters)
for i in range(len(stackList)):
stackList[i].data.shape = oldShapes[i]
return result
inputStack = stackList
else:
stack = self.getStackDataObject()
if isinstance(stack, numpy.ndarray):
Expand All @@ -248,14 +238,47 @@ def actualCalculation(self):
text += " WARNING: Non floating point data."
self._status.setText(text)
oldShape = stack.data.shape
result = function(stack, **pcaParameters)
if stack.data.shape != oldShape:
stack.data.shape = oldShape
return result
inputStack = stack

def threadFinished(self):
result = self.thread.getResult()
self.thread = None
try:
if _logger.getEffectiveLevel() == logging.DEBUG:
result = function(inputStack, **pcaParameters)
self.threadFinished(result)
else:
thread = CalculationThread.CalculationThread(\
calculation_method=function,
calculation_vars=inputStack,
calculation_kw=pcaParameters,
expand_vars=False,
expand_kw=True)
thread.start()
message = "Please wait. PCA Calculation going on."
CalculationThread.waitingMessageDialog(thread,
message=message,
parent=self.configurationWidget,
modal=True,
update_callback=None,
frameless=False)
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 PCA calculation")
msg.setInformativeText(str(sys.exc_info()[1]))
msg.setDetailedText(traceback.format_exc())
msg.exec()
finally:
if "Multiple" in self.__methodlabel:
for i in range(len(stackList)):
stackList[i].data.shape = oldShapes[i]
else:
if stack.data.shape != oldShape:
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 @@ -265,6 +288,7 @@ def threadFinished(self):
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