From 483962941d093d77c808bae17c64435dab051958 Mon Sep 17 00:00:00 2001 From: Noella Spitz Date: Fri, 28 Jun 2024 15:56:35 +0100 Subject: [PATCH] Finalise optimisation --- gudpy/core/data_files.py | 12 --- gudpy/core/gudpy.py | 4 +- gudpy/core/gudrun_file.py | 3 + gudpy/core/iterators.py | 1 - gudpy/core/optimise.py | 31 ++++-- gudpy/core/output_file_handler.py | 11 +- gudpy/core/sample.py | 17 ++- gudpy/gui/widgets/core/control.py | 28 ++--- gudpy/gui/widgets/core/main_window.py | 18 ++++ gudpy/gui/widgets/core/optimise_tab.py | 142 +++++++++++++++---------- gudpy/gui/widgets/core/worker.py | 77 ++++++++++---- 11 files changed, 214 insertions(+), 130 deletions(-) diff --git a/gudpy/core/data_files.py b/gudpy/core/data_files.py index ed69ebe5..8062b843 100644 --- a/gudpy/core/data_files.py +++ b/gudpy/core/data_files.py @@ -42,14 +42,10 @@ def gudFile(self): @property def mintFile(self): - if not self.isSampleDataFile: - return None return self._outputs.get(".mint01", None) @property def mdcsFile(self): - if not self.isSampleDataFile: - return None mdcsFile = self._outputs.get(".mdcs01", None) if mdcsFile: return mdcsFile @@ -72,26 +68,18 @@ def mdcsFile(self): @property def msubwFile(self): - if not self.isSampleDataFile: - return None return self._outputs.get(".msubw01", None) @property def mcdsFile(self): - if not self.isSampleDataFile: - return None return self._outputs.get(".mcds01", None) @property def mdorFile(self): - if not self.isSampleDataFile: - return None return self._outputs.get(".mdor01", None) @property def mgorFile(self): - if not self.isSampleDataFile: - return None return self._outputs.get(".mgor01", None) diff --git a/gudpy/core/gudpy.py b/gudpy/core/gudpy.py index d969b366..9b42936b 100644 --- a/gudpy/core/gudpy.py +++ b/gudpy/core/gudpy.py @@ -32,7 +32,7 @@ def __init__( self.purge: Purge = None self.gudrun: Gudrun = None - self.runModes: RunModes = None + self.runModes: RunModes = RunModes() self.gudrunIterator: GudrunIterator = None self.batchProcessor: BatchProcessing = None self.optimiser = None @@ -713,7 +713,7 @@ def convertContainersToSample(self, gudrunFile: GudrunFile): containersAsSamples.append( container.convertToSample() ) - newGudrunFile.sampleBackground.samples = containersAsSamples + sampleBackground.samples = containersAsSamples return newGudrunFile def partition(self, gudrunFile): diff --git a/gudpy/core/gudrun_file.py b/gudpy/core/gudrun_file.py index 8079903a..75ff635c 100644 --- a/gudpy/core/gudrun_file.py +++ b/gudpy/core/gudrun_file.py @@ -173,6 +173,9 @@ def samples(self): s for sb in self.sampleBackgrounds for s in sb.samples] + def containers(self): + return [c for s in self.samples() for c in s.containers] + def checkNormDataFiles(self): return (len(self.normalisation.dataFiles) and len(self.normalisation.dataFilesBg)) diff --git a/gudpy/core/iterators.py b/gudpy/core/iterators.py index 64406731..4187acea 100644 --- a/gudpy/core/iterators.py +++ b/gudpy/core/iterators.py @@ -489,7 +489,6 @@ def setSelfScatteringFiles(self, scale, gudrunFile): if self.iterationCount == 0: return for sample in gudrunFile.runSamples(): - print(sample.name) if len(sample.dataFiles): if scale == Scales.Q: targetFile = sample.dataFiles[0].msubwFile diff --git a/gudpy/core/optimise.py b/gudpy/core/optimise.py index 511bba59..9423035a 100644 --- a/gudpy/core/optimise.py +++ b/gudpy/core/optimise.py @@ -32,7 +32,7 @@ def __init__( self.mseRec = {} - for sample in self.gudrunIterator.gudrunFile.samples(): + for sample in self.gudrunFile.samples(): sample.runThisSample = False if sample.name in [s.name for s in samples]: sample.runThisSample = True @@ -42,13 +42,17 @@ def __init__( self.mse[sample.name]["initial"] = copy.deepcopy(sample) self.results[sample.name] = {} + @property + def gudrunFile(self): + return self.gudrunIterator.gudrunFile + def optimise(self): projectDir = gudpy_io.GudPyIO.projectDir gudpy_io.GudPyIO.projectDir = os.path.join(projectDir, "Optimise") for gudrun in self.gudrunIterator.gudrunObjects: exitcode, error = self.gudrunIterator.singleIteration( - self.gudrunIterator.gudrunFile, gudrun, self.purge) + self.gudrunFile, gudrun, self.purge) self.exitcode = exitcode if exitcode: # An exit code != 0 indicates failure self.error = error @@ -62,7 +66,7 @@ def optimise(self): self.results[sample.name]["bestSample"] = ( self.mse[sample.name]["initial"] ) - self.results[sample.name]["bestIt"] = "initial" + self.results[sample.name]["bestIt"] = "None" for iteration, sample in self.mse[sample.name].items(): if (sample.mse() < self.results[sample.name]["bestSample"].mse()): @@ -98,10 +102,10 @@ def __init__( self.nCalls = nIters self.nIters = nIters * len(samples) self.purge = purge - self.gudrunFile = gudrunFile + self.gudrunFile = copy.deepcopy(gudrunFile) self.samples = [] self.sample = None - self.nCurrent = 0 + self.nCurrent = 1 self.mse = None self.result = None @@ -117,7 +121,7 @@ def __init__( self.gudrun = gudpy.Gudrun() self.gudrunObjects = [] self.gudrunQueue = [] - for _ in range(nIters + len(self.samples)): + for _ in range(nIters * len(self.samples)): self.gudrunQueue.append(gudpy.Gudrun()) self.simulation = data.NpDataSet( @@ -166,6 +170,7 @@ def tweakExponent(self, exponents): return error def optimiseSample(self): + self.mse = None for sample in self.gudrunFile.runSamples(): if sample.name != self.sample.name: sample.runThisSample = False @@ -190,6 +195,7 @@ def optimiseSample(self): ) self.result = result mse = round(result.fun, 5) + self.mse = mse optExponents = [result.x[0:2] + [0.0], result.x[2:] + [0.0]] @@ -197,10 +203,12 @@ def optimiseSample(self): if initError < mse: optExponents = initExp + self.mse = initError return optExponents def optimise(self): + projectFolder = gudpy_io.GudPyIO.projectDir try: for sample in self.samples: self.sample = sample @@ -210,9 +218,16 @@ def optimise(self): sample.dataFiles[0].mintFile, self.limit) optExponents = self.optimiseSample() self.sample.exponentialValues = optExponents - self.nCurrent = 0 - self.nCurrent = 0 + self.nCurrent = 1 + self.nCurrent = "Final Run" + for sample in self.gudrunFile.samples(): + sample.runThisSample = True + outputPath = os.path.join(projectFolder, "Optimise", "Exponents") + gudpy_io.GudPyIO.projectDir = outputPath + self.gudrun.gudrun(gudrunFile=self.gudrunFile, purge=self.purge) + gudpy_io.GudPyIO.projectDir = projectFolder except exc.GudrunException as e: + gudpy_io.GudPyIO.projectDir = projectFolder self.error = e.args return (1, e) return (0, "") diff --git a/gudpy/core/output_file_handler.py b/gudpy/core/output_file_handler.py index a448c079..6f6f3d4a 100644 --- a/gudpy/core/output_file_handler.py +++ b/gudpy/core/output_file_handler.py @@ -272,13 +272,14 @@ def _createSampleDir(self, dest: str): # Create container folders within sample folder for container in sample.containers: + name = (utils.replace_unwanted_chars(container.name) + if container.name != "CONTAINER" + else "Container") for dataFile in container.dataFiles: - self._copyOutputs( + self._copyOutputsByExt( dataFile, - samplePath, - (utils.replace_unwanted_chars(container.name) - if container.name != "CONTAINER" - else "Container") + os.path.join(samplePath, name), + name ) def _createAddOutDir(self, dest: str, exclude: list[str] = []): diff --git a/gudpy/core/sample.py b/gudpy/core/sample.py index 4dabefb3..f7ac82e5 100644 --- a/gudpy/core/sample.py +++ b/gudpy/core/sample.py @@ -1,3 +1,5 @@ +import os + from core.utils import bjoin, numifyBool from core.data_files import DataFiles from core.composition import Composition @@ -174,11 +176,18 @@ def referenceData(self): return data.NpDataSet(self._referenceDataFile) def mse(self, limit=None): - if (not self.dataFiles or not self.dataFiles[0].mintFile - or not self.referenceDataFile): + if not self.dataFiles or not self.dataFiles[0].mintFile: + return None + if not os.path.exists(self.dataFiles[0].mintFile): + return None + if (not self.referenceDataFile + or not os.path.exists(self.referenceDataFile)): + return None + try: + refData = data.NpDataSet(self.referenceDataFile, lim=limit) + expData = data.NpDataSet(self.dataFiles[0].mintFile, lim=limit) + except TypeError: return None - refData = data.NpDataSet(self.referenceDataFile, lim=limit) - expData = data.NpDataSet(self.dataFiles[0].mintFile, lim=limit) return data.meanSquaredError(refData, expData) def pathName(self): diff --git a/gudpy/gui/widgets/core/control.py b/gudpy/gui/widgets/core/control.py index 10b440c7..87957a41 100644 --- a/gudpy/gui/widgets/core/control.py +++ b/gudpy/gui/widgets/core/control.py @@ -2,7 +2,6 @@ import sys import traceback import typing as typ -import copy from PySide6 import QtCore, QtWidgets @@ -561,8 +560,6 @@ def gudrunFinished(self, exitcode): return if exitcode != 0: - print(self.workerThread.gudrunIterator.gudrunFile.runSamples( - )[0].dataFiles[0]._outputs) self.mainWidget.sendError( f"Process failed with the following output: " f"\n{self.workerThread.error}" @@ -585,20 +582,17 @@ def gudrunFinished(self, exitcode): if self.workerThread == self.gudpy.optimiser: self.mainWidget.optimiseTab.setResults( - self.gudpy.optimiser.gudrunIterator.gudrunFile.samples(), + self.gudpy.optimiser.gudrunFile.samples(), self.gudpy.optimiser ) - (self.mainWidget.optimiseTab.exponentialGroupBox - .exportDataButton.setEnabled(True)) - (self.mainWidget.optimiseTab.exponentialGroupBox - .setParamsButton.setEnabled(True)) self.mainWidget.outputSlots.setOutput( self.workerThread.output, "Gudrun", self.gudrunFile) - self.mainWidget.updateWidgets( - gudrunFile=self.gudrunFile, - ) - self.gudpy.io.save(self.gudrunFile) + if not self.workerThread == self.gudpy.optimiser: + self.mainWidget.updateWidgets( + gudrunFile=self.gudrunFile, + ) + self.gudpy.io.save(self.gudrunFile) self.workerThread = None def compositionIterationFinished(self, exitcode): @@ -654,18 +648,16 @@ def runBatchProcessing(self): self.startProcess() def runOptimiseExponents(self): - gudrunFileCopy = copy.deepcopy(self.gudrunFile) - if not self.prepareRun(): return samples = [] - for sw in self.mainWidget.optimiseTab.sampleWidgets: + for sw in self.mainWidget.optimiseTab.sampleWidgets.values(): if sw.runSample: samples.append(sw.sample) self.gudpy.optimiser = worker.OptimiseExponentsWorker( - gudrunFile=gudrunFileCopy, + gudrunFile=self.gudrunFile, samples=samples, purge=self.gudpy.purge, limit=(self.mainWidget.optimiseTab @@ -675,7 +667,7 @@ def runOptimiseExponents(self): ) self.mainWidget.optimiseTab.setSamples( - self.gudpy.optimiser.gudrunFile.runSamples() + self.gudpy.gudrunFile.runSamples() ) self.connectProcessSignals( @@ -698,7 +690,7 @@ def runOptimiseInelasticity(self): return samples = [] - for sw in self.mainWidget.optimiseTab.sampleWidgets: + for sw in self.mainWidget.optimiseTab.sampleWidgets.values(): if sw.runSample: samples.append(sw.sample) diff --git a/gudpy/gui/widgets/core/main_window.py b/gudpy/gui/widgets/core/main_window.py index ce93f068..a4a0a5d4 100644 --- a/gudpy/gui/widgets/core/main_window.py +++ b/gudpy/gui/widgets/core/main_window.py @@ -371,6 +371,21 @@ def updateWidgets(self, gudrunFile): self.normalisationSlots.setNormalisation(self.gudrunFile.normalisation) self.optimiseTab.setSamples(self.gudrunFile.runSamples()) + if not self.allPlots: + allTopChart = GudPyChart() + samples = [*gudrunFile.samples(), *gudrunFile.containers()] + allTopChart.addSamples(samples) + allTopChart.plot( + self.ui.allPlotComboBox.itemData( + self.ui.allPlotComboBox.currentIndex() + ) + ) + allBottomChart = GudPyChart() + allBottomChart.addSamples(samples) + self.allPlots = [allTopChart, allBottomChart] + self.ui.allSampleTopPlot.setChart(allTopChart) + self.ui.allSampleBottomPlot.setChart(allBottomChart) + if len(self.gudrunFile.sampleBackgrounds): self.sampleBackgroundSlots.setSampleBackground( self.gudrunFile.sampleBackgrounds[0] @@ -577,6 +592,8 @@ def updateSamples(self): *self.ui.objectTree.getContainers(), ] for sample in samples: + if sample in self.results.keys(): + continue topChart = GudPyChart() topChart.addSample(sample) bottomChart = GudPyChart() @@ -600,6 +617,7 @@ def updateSamples(self): topChart, bottomChart, gf if gf else None] def updateAllSamples(self): + return samples = [ *self.ui.objectTree.getSamples(), *self.ui.objectTree.getContainers(), diff --git a/gudpy/gui/widgets/core/optimise_tab.py b/gudpy/gui/widgets/core/optimise_tab.py index d299b079..90232519 100644 --- a/gudpy/gui/widgets/core/optimise_tab.py +++ b/gudpy/gui/widgets/core/optimise_tab.py @@ -1,6 +1,5 @@ from PySide6 import QtWidgets, QtCore import os -import copy import shutil from core import utils @@ -55,7 +54,11 @@ def browseFiles(self): def checkFile(self): if not os.path.exists(self.lineEdit.text()): - self.lineEdit.setStyleSheet("color: red;") + if self.runSample: + self.sampleNameLabel.setStyleSheet("color: darkRed;") + else: + self.sampleNameLabel.setStyleSheet("") + self.sample.referenceDataFile = "" else: self.lineEdit.setStyleSheet("") self.sample.referenceDataFile = self.lineEdit.text() @@ -72,7 +75,7 @@ def __init__(self, headings): def rowCount( self, parent: QtCore.QModelIndex) -> int: - return len(self.samples) + return len(self.initSamples) def columnCount(self, parent: QtCore.QModelIndex) -> int: return len(self.headings) @@ -85,19 +88,28 @@ def headerData(self, section: int, orientation: QtCore.Qt.Orientation, else: return "" - def setSamples(self, samples): - self.samples = samples - if not self.initSamples: - self.initSamples = [] - for s in samples: - self.initSamples.append(copy.deepcopy(s)) + def setSamples(self, initSamples): + self.initSamples = initSamples bottomRight = self.createIndex(len(self.samples), len(self.headings)) self.dataChanged.emit(self.createIndex(0, 0), bottomRight) + def setResults(self, resultSamples): + self.samples = [] + for s in self.initSamples: + for rs in resultSamples: + if rs.name == s.name: + self.samples.append(rs) + def refresh(self): bottomRight = self.createIndex(len(self.samples), len(self.headings)) self.dataChanged.emit(self.createIndex(0, 0), bottomRight) + def round(self, val, precision): + try: + return round(val, precision) + except TypeError: + return "-" + class OptimiseExponents(QtWidgets.QGroupBox): class OptimiseExponentsResultsModel(OptimiseResultsModel): @@ -109,23 +121,27 @@ def __init__(self, limitSpinBox): def data(self, index: QtCore.QModelIndex, role: int): if role == QtCore.Qt.DisplayRole: if index.column() == 0: - return self.samples[index.row()].name + return self.initSamples[index.row()].name if index.column() == 1: if not self.initSamples[index.row()].mse( self.limitSpinBox.value()): return "-" - return str(round(self.initSamples[index.row()].mse( + return str(self.round(self.initSamples[index.row()].mse( self.limitSpinBox.value()), 5)) if index.column() == 2: + if not self.samples: + return "-" if not self.samples[index.row()].mse( self.limitSpinBox.value()): return "-" - return str(round(self.samples[index.row()].mse( + return str(self.round(self.samples[index.row()].mse( self.limitSpinBox.value()), 5)) if index.column() == 3: rounded = "" - for set in self.samples[index.row()].exponentialValues: - roundedSet = [round(v, 3) for v in set] + samples = (self.samples if self.samples + else self.initSamples) + for set in samples[index.row()].exponentialValues: + roundedSet = [self.round(v, 3) for v in set] if rounded: rounded += ", " rounded += str(roundedSet) @@ -203,15 +219,24 @@ def __init__(self, parent=None): def setSamples(self, samples): self.resultsModel.setSamples(samples) + self.resultsModel.refresh() + + def setResults(self, resultSamples): + self.resultsModel.setResults(resultSamples) + self.resultsModel.refresh() + self.setParamsButton.setEnabled(True) + self.exportDataButton.setEnabled(True) def setParameters(self, gudrunFile): for optSample in self.resultsModel.samples: - for sample in gudrunFile.samples: + for sample in gudrunFile.samples(): if optSample.name == sample.name: sample.exponentialValues = optSample.exponentialValues - message = QtWidgets.QMessageBox( - title="GudPy Info", - text="New parameters applied to the samples.") + message = QtWidgets.QMessageBox() + message.setWindowTitle("GudPy Info") + message.setText( + "New parameters applied to the samples. " + + "Run Gudrun to apply the changes.") message.exec() def exportData(self): @@ -236,18 +261,20 @@ def __init__(self): def data(self, index: QtCore.QModelIndex, role: int): if role == QtCore.Qt.DisplayRole: - sample = self.samples[index.row()] + sample = self.initSamples[index.row()] if index.column() == 0: return sample.name if index.column() == 1: - if not self.initSamples[index.row()].mse(): + if not sample.mse(): return "-" - return str(round(self.initSamples[index.row()].mse(), 5)) + return str(self.round(sample.mse(), 5)) if index.column() == 2: if not self.results.get(sample.name, None): - return "-" + if not sample.mse(): + return "-" + return str(self.round(sample.mse(), 5)) bestSamp = self.results[sample.name]["bestSample"] - return str(round(bestSamp.mse(), 5)) + return str(self.round(bestSamp.mse(), 5)) if index.column() == 3: if not self.results.get(sample.name, None): return "-" @@ -265,6 +292,7 @@ def __init__(self, parent=None): self.resultsLayout = QtWidgets.QHBoxLayout() self.resultsTable = QtWidgets.QTableView() + self.resultsModel = self.OptimiseInelasticityResultsModel() self.resultsTable.setModel(self.resultsModel) self.resultsModel.dataChanged.connect(self.resultsTable.update) @@ -272,10 +300,12 @@ def __init__(self, parent=None): QtWidgets.QHeaderView.ResizeMode.ResizeToContents ) self.resultsTable.verticalHeader().hide() + self.resultsTable.horizontalHeader().setSectionResizeMode( + QtWidgets.QHeaderView.ResizeMode.Stretch + ) self.resultsTable.setSizePolicy( QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) self.resultsLayout.addWidget(self.resultsTable) - self.inelasticityLayout.addItem(self.resultsLayout) self.buttonLayout = QtWidgets.QHBoxLayout() @@ -294,8 +324,10 @@ def __init__(self, parent=None): def setSamples(self, samples): self.resultsModel.setSamples(samples) + self.resultsModel.refresh() - def setResults(self, results: dict): + def setResults(self, resultSamples, results: dict): + self.resultsModel.setResults(resultSamples) self.resultsModel.results = results self.resultsModel.refresh() self.exportDataButton.setEnabled(True) @@ -319,17 +351,6 @@ def exportData(self): dirname, os.path.basename(mintFile))) -class SampleReferenceTable(QtWidgets.QTableWidget): - def __init__(self, parent=None): - super().__init__(parent) - self._parent = parent - self.samples = [] - - def setSamples(self, samples): - self.setRowCount(len(samples)) - self.setColumnCount(4) - - class OptimiseTab(QtWidgets.QWidget): runOptimiseExponents = QtCore.Signal(int) runOptimiseInelasticity = QtCore.Signal(int) @@ -338,7 +359,7 @@ def __init__(self, parent=None): super().__init__(parent) self._parent = parent self.samples = [] - self.sampleWidgets = [] + self.sampleWidgets = {} self.mainLayout = QtWidgets.QVBoxLayout() self.sampleGroupBox = QtWidgets.QGroupBox( @@ -382,7 +403,7 @@ def setSamples(self, samples): if samples == self.samples: return - runSamples = [sw.sample for sw in self.sampleWidgets if sw.runSample] + self.samples = samples while self.sampleLayout.count(): item = self.sampleLayout.takeAt(0) @@ -390,40 +411,42 @@ def setSamples(self, samples): if widget is not None: widget.deleteLater() - self.sampleWidgets = [] - for sample in samples: - sampleWidget = SampleWidget(self._parent, sample) - if sample not in runSamples: - sampleWidget.checkBox.setChecked(False) - else: - sampleWidget.checkBox.setChecked(True) - sampleWidget.refDataSet.connect( - lambda: ( - self.exponentialGroupBox.resultsModel.setSamples( - self.samples))) - sampleWidget.refDataSet.connect( - lambda: ( - self.inelasticityGroupBox.resultsModel.setSamples( - self.samples))) - self.sampleWidgets.append(sampleWidget) + sampleWidget = self.sampleWidgets.get(sample.name) + if not sampleWidget: + sampleWidget = SampleWidget(self._parent, sample) + sampleWidget.refDataSet.connect( + lambda: ( + self.exponentialGroupBox.resultsModel.setSamples( + self.samples))) + sampleWidget.refDataSet.connect( + lambda: ( + self.inelasticityGroupBox.resultsModel.setSamples( + self.samples))) + self.sampleWidgets[sample.name] = sampleWidget self.sampleLayout.addWidget(sampleWidget) + for sname in self.sampleWidgets.keys(): + if sname not in [s.name for s in samples]: + self.sampleWidgets.pop(sname, None) + if not self._parent.widgetsRefreshing: self._parent.setModified() def setResults(self, samples, optimiser): - self.exponentialGroupBox.setSamples(samples) + self.exponentialGroupBox.setResults(samples) if isinstance(optimiser, opt.InelasticityOptimisation): - self.inelasticityGroupBox.setResults(optimiser.results) + self.inelasticityGroupBox.setResults(samples, optimiser.results) if not self._parent.widgetsRefreshing: self._parent.setModified() def validateRun(self): - for sw in self.sampleWidgets: + sampleSelected = False + for sw in self.sampleWidgets.values(): if sw.runSample: + sampleSelected = True if not sw.sample.referenceDataFile: self._parent.sendError( f"Reference data not provided for {sw.sample.name}" @@ -435,6 +458,11 @@ def validateRun(self): "Please run Gudrun before optimising." ) return False + if not sampleSelected: + self._parent.sendError( + "No samples selected" + ) + return False return True def handleOptimiseExponentsButton(self): diff --git a/gudpy/gui/widgets/core/worker.py b/gudpy/gui/widgets/core/worker.py index b0de448c..e8bc8afc 100644 --- a/gudpy/gui/widgets/core/worker.py +++ b/gudpy/gui/widgets/core/worker.py @@ -95,23 +95,26 @@ def __init__( self.progress = 0 # Number of GudPy objects - self.markers = ( - config.NUM_GUDPY_CORE_OBJECTS - 1 - + len(self.gudrunFile.sampleBackgrounds) + sum([sum([ - len([ - sample - for sample in sampleBackground.samples - if sample.runThisSample - ]), - *[ - len(sample.containers) - for sample in sampleBackground.samples - if sample.runThisSample - ]]) - for sampleBackground in self.gudrunFile.sampleBackgrounds - ])) + self.markers = None def _progressChanged(self): + if not self.markers: + self.markers = ( + config.NUM_GUDPY_CORE_OBJECTS - 1 + + len(self.gudrunFile.sampleBackgrounds) + sum([sum([ + len([ + sample + for sample in sampleBackground.samples + if sample.runThisSample + ]), + *[ + len(sample.containers) + for sample in sampleBackground.samples + if sample.runThisSample + ]]) + for sampleBackground in self.gudrunFile.sampleBackgrounds + ])) + stepSize = math.ceil(100 / self.markers) self.progress = stepSize * sum([ self.output.count("Got to: INSTRUMENT"), @@ -278,14 +281,15 @@ def __init__( self.gudrunObjects = [] self.gudrunQueue = [] - for _ in range(nIters): - gudrunWorker = GudrunWorker(gudrunFile=gudrunFile, purge=purge) + for _ in range(nIters * len(samples)): + gudrunWorker = GudrunWorker( + gudrunFile=self.gudrunFile, purge=purge) self.gudrunObjects.append(gudrunWorker) self.gudrunQueue.append(gudrunWorker) gudrunWorker.outputChanged.connect(self._outputChanged) gudrunWorker.progressChanged.connect(self._progressChanged) - self.gudrun = GudrunWorker(gudrunFile=gudrunFile, purge=purge) + self.gudrun = GudrunWorker(gudrunFile=self.gudrunFile, purge=purge) self.gudrun.outputChanged.connect(self._outputChanged) self.gudrun.progressChanged.connect(self._progressChanged) @@ -305,11 +309,38 @@ def _progressChanged(self, progress): rounded += ", " rounded += str(roundedSet) - text = (f"Optimise {self.sample.name} " + - (f"- {rounded}" + - f" MSE: {self.mse} " if self.mse else "") + - f"- {self.nCurrent + 1}/{int(self.nIters/len(self.samples))}" - ) + if self.nCurrent == "Final Run": + text = ( + "Final Run with params " + + f"- {rounded}" + ) + else: + text = ( + f"Optimise {self.sample.name} " + + f"- {rounded}" + + (f" MSE: {self.mse} " if self.mse else "") + + f"- {self.nCurrent}/{int(self.nIters/len(self.samples))}" + ) + + self.progressChanged.emit( + progress, + text + ) + + def _progressChangedFinalRun(self, progress): + rounded = "" + + for set in self.sample.exponentialValues: + roundedSet = [round(v, 3) for v in set] + if rounded: + rounded += ", " + rounded += str(roundedSet) + + text = ( + "Final run with params " + + f"- {rounded}" + + f" MSE: {self.mse}" + ) self.progressChanged.emit( progress,