diff --git a/Framework/Algorithms/src/CalculateMuonAsymmetry.cpp b/Framework/Algorithms/src/CalculateMuonAsymmetry.cpp index 53970a0952929cb38845d1d6aac2204967cd2059..c8fa246f4af650d67f145309db28cd0f540a81fe 100644 --- a/Framework/Algorithms/src/CalculateMuonAsymmetry.cpp +++ b/Framework/Algorithms/src/CalculateMuonAsymmetry.cpp @@ -80,6 +80,9 @@ void CalculateMuonAsymmetry::init() { declareProperty( "MaxIterations", 500, mustBePositive->clone(), "Stop after this number of iterations if a good fit is not found"); + declareProperty("OutputStatus", "", Kernel::Direction::Output); + declareProperty(make_unique<API::FunctionProperty>("OutputFunction", Kernel::Direction::Output), + "The fitting function after fit."); } /* * Validate the input parameters @@ -238,8 +241,11 @@ std::vector<double> CalculateMuonAsymmetry::getNormConstants( } fit->execute(); + auto status = fit->getPropertyValue("OutputStatus"); + setProperty("OutputStatus", status); API::IFunction_sptr tmp = fit->getProperty("Function"); + setProperty("OutputFunction", tmp); try { if (wsNames.size() == 1) { // N(1+g) + exp @@ -269,15 +275,16 @@ std::vector<double> CalculateMuonAsymmetry::getNormConstants( * @return normalization constant */ double CalculateMuonAsymmetry::getNormValue(API::CompositeFunction_sptr &func) { - + // getFunction(0) -> N(1+g) auto TFFunc = boost::dynamic_pointer_cast<API::CompositeFunction>(func->getFunction(0)); + auto fdas = TFFunc->asString(); // getFunction(0) -> N - TFFunc = boost::dynamic_pointer_cast<API::CompositeFunction>( - TFFunc->getFunction(0)); - return TFFunc->getParameter("f0.A0"); + auto flat = TFFunc->getFunction(0); + + return flat->getParameter("A0"); } } // namespace Algorithm } // namespace Mantid diff --git a/qt/widgets/common/inc/MantidQtWidgets/Common/MuonFitPropertyBrowser.h b/qt/widgets/common/inc/MantidQtWidgets/Common/MuonFitPropertyBrowser.h index 3aaf66efbcb8b7e0b07980d4c261a32540c2d2f0..7ca8a75d3960b0b51bfcfd3d248dc03ea857b95a 100644 --- a/qt/widgets/common/inc/MantidQtWidgets/Common/MuonFitPropertyBrowser.h +++ b/qt/widgets/common/inc/MantidQtWidgets/Common/MuonFitPropertyBrowser.h @@ -55,6 +55,8 @@ public: void setWorkspaceName(const QString &wsName) override; /// Called when the fit is finished void finishHandle(const Mantid::API::IAlgorithm *alg) override; + void finishHandleTF(const Mantid::API::IAlgorithm *alg); + void finishHandleNormal(const Mantid::API::IAlgorithm *alg); /// Add an extra widget into the browser void addExtraWidget(QWidget *widget); void addFitBrowserWidget(QWidget *widget, MantidQt::MantidWidgets::FunctionBrowser *functionBrowser); diff --git a/qt/widgets/common/src/MuonFitPropertyBrowser.cpp b/qt/widgets/common/src/MuonFitPropertyBrowser.cpp index f4bbf0fc10f5836594ca2dbc91a5bf1909fe0967..a129050336e3a227fa6effc165b87bd10d34f374 100644 --- a/qt/widgets/common/src/MuonFitPropertyBrowser.cpp +++ b/qt/widgets/common/src/MuonFitPropertyBrowser.cpp @@ -65,6 +65,7 @@ const QString CUSTOM_LABEL{"Custom"}; const QString ALL_GROUPS_LABEL{"All Groups"}; const QString ALL_PAIRS_LABEL{"All Pairs"}; const QString ALL_PERIODS_LABEL{"All Periods"}; +const std::string UNNORM = "_unNorm"; } namespace MantidQt { @@ -666,117 +667,79 @@ void MuonFitPropertyBrowser::populateFunctionNames() { * Creates an instance of Fit algorithm, sets its properties and launches it. */ void MuonFitPropertyBrowser::doTFAsymmFit() { - std::string wsName = workspaceName(); - if (wsName.empty()) { - QMessageBox::critical(this, "Mantid - Error", "Workspace name is not set"); - return; - } - std::vector<double> normVec; - auto norms = readMultipleNormalization(); - - // TFAsymm calculation -> there is already some estimated data - // rescale WS to normalized counts: - const int nWorkspaces = static_cast<int>(m_workspacesToFit.size()); - if (nWorkspaces > 1) { - emit functionUpdateRequested(); - } - for (int i = 0; i < nWorkspaces; i++) { - rescaleWS(norms, m_workspacesToFit[i], 1.0); - std::string tmp = m_workspacesToFit[i]; - std::replace(tmp.begin(), tmp.end(), ' ', ';'); - // The order of the input is the same - // as the order of the workspace list - // create a vec of norms in the same order - auto it = norms.find(tmp); - if (it != norms.end()) { - normVec.push_back(it->second); - } else { // if raw data cannot be found - // use the binned data as initial norm - tmp = tmp.substr(0, tmp.size() - 4); - it = norms.find(tmp); - normVec.push_back(it->second); - } - } - try { - m_initialParameters.resize(compositeFunction()->nParams()); - for (size_t i = 0; i < compositeFunction()->nParams(); i++) { - m_initialParameters[i] = compositeFunction()->getParameter(i); - } - m_fitActionUndoFit->setEnabled(true); - - IAlgorithm_sptr alg = AlgorithmManager::Instance().create("Fit"); - alg->initialize(); - if (m_compositeFunction->name() == "MultiBG") { - alg->setPropertyValue("Function", ""); - } else if (m_compositeFunction->nFunctions() > 1) { - IFunction_sptr userFunc = getFittingFunction(); - auto TFAsymmFunc = getTFAsymmFitFunction(userFunc, normVec); - alg->setProperty("Function", TFAsymmFunc); - } else { - IFunction_sptr userFunc = m_compositeFunction->getFunction(0); - auto TFAsymmFunc = getTFAsymmFitFunction(userFunc, normVec); - alg->setProperty("Function", TFAsymmFunc); - } - if (rawData()) { - alg->setPropertyValue("InputWorkspace", wsName + "_Raw"); - } else { - alg->setPropertyValue("InputWorkspace", wsName); - } - alg->setProperty("WorkspaceIndex", workspaceIndex()); - alg->setProperty("StartX", startX()); - alg->setProperty("EndX", endX()); - alg->setPropertyValue("Minimizer", minimizer()); - alg->setPropertyValue("CostFunction", costFunction()); + std::string wsName = workspaceName(); - // If we are doing a simultaneous fit, set this up here - const int nWorkspaces = static_cast<int>(m_workspacesToFit.size()); - if (nWorkspaces > 1) { - alg->setPropertyValue("InputWorkspace", m_workspacesToFit[0]); - // Remove existing results with the same name - if (AnalysisDataService::Instance().doesExist(outputName())) { - AnalysisDataService::Instance().deepRemoveGroup(outputName()); - } - for (int i = 1; i < nWorkspaces; i++) { - std::string suffix = boost::lexical_cast<std::string>(i); + if (wsName.empty()) { + QMessageBox::critical(this, "Mantid - Error", "Workspace name is not set"); + return; + } + try { + auto fa = m_compositeFunction->asString(); + m_initialParameters.resize(compositeFunction()->nParams()); + for (size_t i = 0; i < compositeFunction()->nParams(); i++) { + m_initialParameters[i] = compositeFunction()->getParameter(i); + } + m_fitActionUndoFit->setEnabled(true); + + // Delete any existing results for this workspace, UNLESS we are doing a + // simultaneous fit + if (m_workspacesToFit.size() < 2) { + if (AnalysisDataService::Instance().doesExist( + wsName + "_NormalisedCovarianceMatrix")) { + FrameworkManager::Instance().deleteWorkspace( + wsName + "_NormalisedCovarianceMatrix"); + } + if (AnalysisDataService::Instance().doesExist(wsName + "_Parameters")) { + FrameworkManager::Instance().deleteWorkspace(wsName + "_Parameters"); + } + if (AnalysisDataService::Instance().doesExist(wsName + "_Workspace")) { + FrameworkManager::Instance().deleteWorkspace(wsName + "_Workspace"); + } + } + + IAlgorithm_sptr alg = AlgorithmManager::Instance().create("CalculateMuonAsymmetry"); + alg->initialize(); + + alg->setProperty("InputFunction", boost::dynamic_pointer_cast<IFunction>( + m_compositeFunction->getFunction(0))); - alg->setPropertyValue("InputWorkspace_" + suffix, m_workspacesToFit[i]); - alg->setProperty("WorkspaceIndex_" + suffix, workspaceIndex()); - alg->setProperty("StartX_" + suffix, startX()); - alg->setProperty("EndX_" + suffix, endX()); - } - } else { - setSingleFitLabel(wsName); - } - alg->setPropertyValue("Output", outputName()); + std::string tmpWSName = wsName; + if (rawData()) { + tmpWSName += "_Raw"; + } + if (m_boolManager->value(m_TFAsymmMode) && tmpWSName.find(UNNORM)) { + tmpWSName += TFExtension(); + } + + + auto unnorm = m_workspacesToFit; + std::string tmp = UNNORM; + std::for_each(unnorm.begin(), unnorm.end(),[tmp](std::string& str) {str += UNNORM; }); + + alg->setProperty("UnNormalizedWorkspaceList", unnorm); + alg->setProperty("ReNormalizedWorkspaceList", m_workspacesToFit); + alg->setProperty("NormalizationTable", "MuonAnalysisTFNormalizations"); + + alg->setProperty("StartX", startX()); + alg->setProperty("EndX", endX()); + alg->setPropertyValue("Minimizer", minimizer()); + //alg->setPropertyValue("CostFunction", costFunction()); + + // If we are doing a simultaneous fit, set this up here + const int nWorkspaces = static_cast<int>(m_workspacesToFit.size()); + if (nWorkspaces == 1) { + setSingleFitLabel(wsName); + } + alg->setPropertyValue("OutputFitWorkspace", outputName()); + + observeFinish(alg); + alg->execute(); - observeFinish(alg); - alg->execute(); - // get norms - std::vector<double> newNorms; - IFunction_sptr outputFunction = alg->getProperty("Function"); - for (int j = 0; j < nWorkspaces; j++) { - std::string paramName = "f" + std::to_string(j); - paramName += ".f0.f0.A0"; - newNorms.push_back(outputFunction->getParameter(paramName)); - std::string tmpWSName = m_workspacesToFit[j]; - if (rawData()) { // store norms without the raw - tmpWSName = tmpWSName.substr(0, tmpWSName.size() - 4); - } - auto tmpWSNameNoRaw = tmpWSName; - std::replace(tmpWSName.begin(), tmpWSName.end(), ' ', ';'); - auto it = norms.find(tmpWSName); - it->second = newNorms[newNorms.size() - 1]; - // transform data back to Asymm - // rescale WS: - rescaleWS(norms, tmpWSNameNoRaw, -1.0); - } - - updateMultipleNormalization(norms); - } catch (const std::exception &e) { - QString msg = "TF Asymmetry Fit failed.\n\n" + QString(e.what()) + "\n"; - QMessageBox::critical(this, "Mantid - Error", msg); - } - runFit(); + } + catch (const std::exception &e) { + QString msg = "CalculateMuonAsymmetry algorithm failed.\n\n" + QString(e.what()) + "\n"; + QMessageBox::critical(this, "Mantid - Error", msg); + } } /** * Updates the normalization in the table WS @@ -995,7 +958,7 @@ void MuonFitPropertyBrowser::runFit() { if (rawData()) { tmpWSName += "_Raw"; } - if (m_boolManager->value(m_TFAsymmMode) && tmpWSName.find("_unNorm")) { + if (m_boolManager->value(m_TFAsymmMode) && tmpWSName.find(UNNORM)) { tmpWSName += TFExtension(); } @@ -1033,9 +996,9 @@ void MuonFitPropertyBrowser::runFit() { } std::string MuonFitPropertyBrowser :: TFExtension() const{ - const std::string UNNORM = "_unNorm"; - return (m_boolManager->value(m_TFAsymmMode)) ? UNNORM : ""; + + return (m_boolManager->value(m_TFAsymmMode)) ? UNNORM : ""; } /** @@ -1080,6 +1043,69 @@ bool MuonFitPropertyBrowser::isWorkspaceValid(Workspace_sptr ws) const { } void MuonFitPropertyBrowser::finishHandle(const IAlgorithm *alg) { + if (alg->name()=="CalculateMuonAsymmetry") { + finishHandleTF(alg); + } + else { + finishHandleNormal(alg); + + } +} +void MuonFitPropertyBrowser::finishHandleTF(const IAlgorithm *alg) { + auto tfsdaf = alg->getPropertyValue("OutputStatus"); + auto status = QString::fromStdString(alg->getPropertyValue("OutputStatus")); + emit fitResultsChanged(status); + //need to add errors and values to browser + //m_functionBrowser->setParamError() + // need to work out magic grouping + auto &ads = AnalysisDataService::Instance(); + const QString wsName = QString::fromStdString(workspaceName()); + std::string groupName; + const int index = wsName.indexOf(';'); + if (index != -1) { + groupName = wsName.left(index).toStdString(); + } + else { + groupName= wsName.toStdString(); + } + WorkspaceGroup_sptr group; + if (ads.doesExist(groupName)) { + group = ads.retrieveWS<WorkspaceGroup>(groupName); + } + std::string wsNormalised = + wsName.toStdString() + "_NormalisedCovarianceMatrix"; + std::string wsParameters = wsName.toStdString() + "_Parameters"; + std::string wsWorkspace = wsName.toStdString() + "_Workspace"; + std::vector<std::string> inputWorkspaces; + + if (Mantid::API::AnalysisDataService::Instance().doesExist(wsNormalised)) { + inputWorkspaces.push_back(wsNormalised); + } + if (Mantid::API::AnalysisDataService::Instance().doesExist(wsParameters)) { + inputWorkspaces.push_back(wsParameters); + } + if (Mantid::API::AnalysisDataService::Instance().doesExist(wsWorkspace)) { + inputWorkspaces.push_back(wsWorkspace); + } + if (group) { + + // Exists and is a group -> add missing workspaces to it + for (auto it = inputWorkspaces.begin(); it != inputWorkspaces.end(); ++it) { + if (!group->contains(*it)) { + group->add(*it); + } + } + } + else { + // Doesn't exist or isn't a group -> create/overwrite + IAlgorithm_sptr groupingAlg = + AlgorithmManager::Instance().create("GroupWorkspaces"); + groupingAlg->setProperty("InputWorkspaces", inputWorkspaces); + groupingAlg->setPropertyValue("OutputWorkspace", groupName); + groupingAlg->execute(); + } +} +void MuonFitPropertyBrowser::finishHandleNormal(const IAlgorithm *alg) { // Copy experiment info to output workspace if (AnalysisDataService::Instance().doesExist(outputName() + "_Workspace")) { // Input workspace should be a MatrixWorkspace according to isWorkspaceValid @@ -1378,7 +1404,7 @@ void MuonFitPropertyBrowser::updateTFPlot(){ //update plot int j = m_enumManager->value(m_workspace); std::string option = m_workspaceNames[j].toStdString(); - if (m_boolManager->value(m_TFAsymmMode) && option.find("unNorm")==std::string::npos) { + if (m_boolManager->value(m_TFAsymmMode) && option.find(UNNORM)==std::string::npos) { option += TFExtension(); } // update plot