diff --git a/src/mvesuvio/analysis_fitting.py b/src/mvesuvio/analysis_fitting.py index 5c91c13..ca2cf61 100644 --- a/src/mvesuvio/analysis_fitting.py +++ b/src/mvesuvio/analysis_fitting.py @@ -10,8 +10,10 @@ import time import re from mantid.kernel import logger +from mantid.simpleapi import AnalysisDataService from mvesuvio.util import handle_config +from mvesuvio.util.analysis_helpers import print_table_workspace, passDataIntoWS repoPath = Path(__file__).absolute().parent # Path to the repository @@ -40,7 +42,7 @@ def fitInYSpaceProcedure(yFitIC, IC, wsTOF): fitProfileMinuit(yFitIC, wsJoYAvg, wsResSum) fitProfileMantidFit(yFitIC, wsJoYAvg, wsResSum) - printYSpaceFitResults(wsJoYAvg.name()) + printYSpaceFitResults() yfitResults = ResultsYFitObject(IC, yFitIC, wsTOF.name(), wsJoYAvg.name()) yfitResults.save() @@ -105,7 +107,10 @@ def subtract_profiles_except_lightest(ic, ws): if len(ic.masses) == 1: return - ws_name_lightest_mass = ic.name + '_' + str(ic.number_of_iterations_for_corrections) + '_' + str(min(ic.masses)) + '_ncp' + # TODO: Make the fetching of these workspaces more robust, prone to error + profiles_table = mtd[ic.name + '_initial_parameters'] + lightest_mass_str = profiles_table.column('label')[np.argmin(profiles_table.column('mass'))] + ws_name_lightest_mass = ic.name + '_' + str(ic.number_of_iterations_for_corrections) + '_' + lightest_mass_str + '_ncp' ws_name_profiles = ic.name + '_' + str(ic.number_of_iterations_for_corrections) + '_total_ncp' wsNcpExceptFirst = Minus(mtd[ws_name_profiles], mtd[ws_name_lightest_mass], @@ -128,7 +133,9 @@ def switchFirstTwoAxis(A): def ySpaceReduction(wsTOF, mass0, yFitIC, ic): """Seperate procedures depending on masking specified.""" - ws_name_lightest_mass = ic.name + '_' + str(ic.number_of_iterations_for_corrections) + '_' + str(min(ic.masses)) + '_ncp' + profiles_table = mtd[ic.name + '_initial_parameters'] + lightest_mass_str = profiles_table.column('label')[np.argmin(profiles_table.column('mass'))] + ws_name_lightest_mass = ic.name + '_' + str(ic.number_of_iterations_for_corrections) + '_' + lightest_mass_str + '_ncp' ncp = mtd[ws_name_lightest_mass].extractY() rebinPars = yFitIC.range_for_rebinning_in_y_space @@ -415,15 +422,6 @@ def extractWS(ws): return ws.extractX(), ws.extractY(), ws.extractE() -def passDataIntoWS(dataX, dataY, dataE, ws): - "Modifies ws data to input data" - for i in range(ws.getNumberHistograms()): - ws.dataX(i)[:] = dataX[i, :] - ws.dataY(i)[:] = dataY[i, :] - ws.dataE(i)[:] = dataE[i, :] - return ws - - def symmetrizeWs(avgYSpace): """ Symmetrizes workspace after weighted average. @@ -904,6 +902,8 @@ def createCorrelationTableWorkspace(wsYSpaceSym, parameters, corrMatrix): tableWS.addColumn(type="float", name=p) for p, arr in zip(parameters, corrMatrix): tableWS.addRow([p] + list(arr)) + print_table_workspace(tableWS) + def runMinos(mObj, yFitIC, constrFunc, wsName): @@ -1283,39 +1283,10 @@ def fitProfileMantidFit(yFitIC, wsYSpaceSym, wsRes): return -def printYSpaceFitResults(wsJoYName): - logger.notice("\nFit in Y Space results:") - foundWS = [] - try: - wsFitLM = mtd[wsJoYName + "_lm_Parameters"] - foundWS.append(wsFitLM) - except KeyError: - pass - try: - wsFitSimplex = mtd[wsJoYName + "_simplex_Parameters"] - foundWS.append(wsFitSimplex) - except KeyError: - pass - try: - wsFitMinuit = mtd[wsJoYName + "_minuit_Parameters"] - foundWS.append(wsFitMinuit) - except KeyError: - pass - - for tableWS in foundWS: - logger.notice("\n" + " ".join(tableWS.getName().split("_")[-3:]) + ":") - for key in tableWS.keys(): - if key == "Name": - logger.notice( - f"{key:>20s}: " - + " ".join([f"{elem:7.8s}" for elem in tableWS.column(key)]) - ) - else: - logger.notice( - f"{key:>20s}: " - + " ".join([f"{elem:7.4f}" for elem in tableWS.column(key)]) - ) - logger.notice("\n") +def printYSpaceFitResults(): + for ws_name in mtd.getObjectNames(): + if ws_name.endswith('Parameters'): + print_table_workspace(mtd[ws_name]) class ResultsYFitObject: @@ -1858,12 +1829,11 @@ def create_table_for_global_fit_parameters(wsName, m, chi2): logger.notice(f"Value of Chi2/ndof: {chi2:.2f}") logger.notice(f"Migrad Minimum valid: {m.valid}") - logger.notice("\nResults of Global Fit:\n") for p, v, e in zip(m.parameters, m.values, m.errors): - logger.notice(f"{p:>7s} = {v:>8.4f} \u00B1 {e:<8.4f}") t.addRow([p, v, e]) t.addRow(["Cost function", chi2, 0]) + print_table_workspace(t) def plotGlobalFit(dataX, dataY, dataE, mObj, totCost, wsName, yFitIC): diff --git a/src/mvesuvio/analysis_reduction.py b/src/mvesuvio/analysis_reduction.py index b00c762..04c52b0 100644 --- a/src/mvesuvio/analysis_reduction.py +++ b/src/mvesuvio/analysis_reduction.py @@ -324,7 +324,6 @@ def _fit_neutron_compton_profiles(self): self._row_being_fit = 0 while self._row_being_fit != len(self._dataY): self._fit_neutron_compton_profiles_to_row() - self.log().notice('') self._row_being_fit += 1 assert np.any(self._fit_parameters), "Fitting parameters cannot be zero for all spectra!" @@ -466,7 +465,6 @@ def _create_means_table(self): table.addColumn(type="float", name="mean_intensity") table.addColumn(type="float", name="std_intensity") - self.log().notice("\nmass mean widths mean intensities\n") for label, mass, mean_width, std_width, mean_intensity, std_intensity in zip( self._profiles_table.column("label"), self._masses, @@ -477,10 +475,9 @@ def _create_means_table(self): ): # Explicit conversion to float required to match profiles table table.addRow([label, float(mass), float(mean_width), float(std_width), float(mean_intensity), float(std_intensity)]) - self.log().notice(f"{label:6s} {mean_width:10.5f} \u00B1 {std_width:7.5f}" + \ - f"{mean_intensity:10.5f} \u00B1 {std_intensity:7.5f}\n") self.setPropertyValue("OutputMeansTable", table.name()) + print_table_workspace(table, precision=5) return table diff --git a/src/mvesuvio/util/analysis_helpers.py b/src/mvesuvio/util/analysis_helpers.py index b73c6a1..fc0bfaa 100644 --- a/src/mvesuvio/util/analysis_helpers.py +++ b/src/mvesuvio/util/analysis_helpers.py @@ -6,18 +6,26 @@ import numpy as np import numbers -from mvesuvio.analysis_fitting import passDataIntoWS from mvesuvio.util import handle_config import ntpath -def print_table_workspace(table): +def passDataIntoWS(dataX, dataY, dataE, ws): + "Modifies ws data to input data" + for i in range(ws.getNumberHistograms()): + ws.dataX(i)[:] = dataX[i, :] + ws.dataY(i)[:] = dataY[i, :] + ws.dataE(i)[:] = dataE[i, :] + return ws + + +def print_table_workspace(table, precision=3): table_dict = table.toDict() # Convert floats into strings for key, values in table_dict.items(): new_column = [int(item) if (not isinstance(item, str) and item.is_integer()) else item for item in values] - table_dict[key] = [f"{item:.3f}" if isinstance(item, float) else str(item) for item in new_column] + table_dict[key] = [f"{item:.{precision}f}" if isinstance(item, float) else str(item) for item in new_column] max_spacing = [max([len(item) for item in values] + [len(key)]) for key, values in table_dict.items()] header = "|" + "|".join(f"{item}{' '*(spacing-len(item))}" for item, spacing in zip(table.keys(), max_spacing)) + "|"