/** * Adds a spline interpolation as a step in the calculation for using legacy *correction factor * workspaces. * * @param toInterpolate Pointer to the workspace to interpolate * @param toMatch Name of the workspace to match */ void ApplyPaalmanPings::addInterpolationStep(MatrixWorkspace_sptr toInterpolate, std::string toMatch) { API::BatchAlgorithmRunner::AlgorithmRuntimeProps interpolationProps; interpolationProps["WorkspaceToMatch"] = toMatch; IAlgorithm_sptr interpolationAlg = AlgorithmManager::Instance().create("SplineInterpolation"); interpolationAlg->initialize(); interpolationAlg->setProperty("WorkspaceToInterpolate", toInterpolate->name()); interpolationAlg->setProperty("OutputWorkspace", toInterpolate->name()); m_batchAlgoRunner->addAlgorithm(interpolationAlg, interpolationProps); }
bool ApplyPaalmanPings::validate() { UserInputValidator uiv; uiv.checkDataSelectorIsValid("Sample", m_uiForm.dsSample); MatrixWorkspace_sptr sampleWs; bool useCan = m_uiForm.ckUseCan->isChecked(); bool useCorrections = m_uiForm.ckUseCorrections->isChecked(); if (!(useCan || useCorrections)) uiv.addErrorMessage("Must use either container subtraction or corrections"); if (useCan) { uiv.checkDataSelectorIsValid("Container", m_uiForm.dsContainer); // Check can and sample workspaces are the same "type" (reduced or S(Q, w)) QString sample = m_uiForm.dsSample->getCurrentDataName(); QString sampleType = sample.right(sample.length() - sample.lastIndexOf("_")); QString container = m_uiForm.dsContainer->getCurrentDataName(); QString containerType = container.right(container.length() - container.lastIndexOf("_")); g_log.debug() << "Sample type is: " << sampleType.toStdString() << '\n'; g_log.debug() << "Can type is: " << containerType.toStdString() << '\n'; if (containerType != sampleType) uiv.addErrorMessage( "Sample and can workspaces must contain the same type of data."); } if (useCorrections) { if (m_uiForm.dsCorrections->getCurrentDataName().compare("") == 0) { uiv.addErrorMessage( "Use Correction must contain a corrections file or workspace."); } else { QString correctionsWsName = m_uiForm.dsCorrections->getCurrentDataName(); WorkspaceGroup_sptr corrections = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>( correctionsWsName.toStdString()); for (size_t i = 0; i < corrections->size(); i++) { // Check it is a MatrixWorkspace MatrixWorkspace_sptr factorWs = boost::dynamic_pointer_cast<MatrixWorkspace>( corrections->getItem(i)); if (!factorWs) { QString msg = "Correction factor workspace " + QString::number(i) + " is not a MatrixWorkspace"; uiv.addErrorMessage(msg); continue; } // Check X unit is wavelength Mantid::Kernel::Unit_sptr xUnit = factorWs->getAxis(0)->unit(); if (xUnit->caption() != "Wavelength") { QString msg = "Correction factor workspace " + QString::fromStdString(factorWs->name()) + " is not in wavelength"; uiv.addErrorMessage(msg); } } } } // Show errors if there are any if (!uiv.isAllInputValid()) emit showMessageBox(uiv.generateErrorMessage()); return uiv.isAllInputValid(); }
void ApplyPaalmanPings::run() { // Create / Initialize algorithm API::BatchAlgorithmRunner::AlgorithmRuntimeProps absCorProps; IAlgorithm_sptr applyCorrAlg = AlgorithmManager::Instance().create("ApplyPaalmanPingsCorrection"); applyCorrAlg->initialize(); // get Sample Workspace MatrixWorkspace_sptr sampleWs = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>( m_sampleWorkspaceName); m_originalSampleUnits = sampleWs->getAxis(0)->unit()->unitID(); // If not in wavelength then do conversion if (m_originalSampleUnits != "Wavelength") { g_log.information( "Sample workspace not in wavelength, need to convert to continue."); absCorProps["SampleWorkspace"] = addConvertUnitsStep(sampleWs, "Wavelength"); } else { absCorProps["SampleWorkspace"] = m_sampleWorkspaceName; } const bool useCan = m_uiForm.ckUseCan->isChecked(); const bool useCorrections = m_uiForm.ckUseCorrections->isChecked(); // Get Can and Clone MatrixWorkspace_sptr canClone; if (useCan) { const auto canName = m_uiForm.dsContainer->getCurrentDataName().toStdString(); const auto cloneName = "__algorithm_can"; IAlgorithm_sptr clone = AlgorithmManager::Instance().create("CloneWorkspace"); clone->initialize(); clone->setProperty("InputWorkspace", canName); clone->setProperty("Outputworkspace", cloneName); clone->execute(); const bool useShift = m_uiForm.ckShiftCan->isChecked(); if (useShift) { IAlgorithm_sptr scaleX = AlgorithmManager::Instance().create("ScaleX"); scaleX->initialize(); scaleX->setLogging(false); scaleX->setProperty("InputWorkspace", cloneName); scaleX->setProperty("OutputWorkspace", cloneName); scaleX->setProperty("Factor", m_uiForm.spCanShift->value()); scaleX->setProperty("Operation", "Add"); scaleX->execute(); IAlgorithm_sptr rebin = AlgorithmManager::Instance().create("RebinToWorkspace"); rebin->initialize(); rebin->setLogging(false); rebin->setProperty("WorkspaceToRebin", cloneName); rebin->setProperty("WorkspaceToMatch", m_sampleWorkspaceName); rebin->setProperty("OutputWorkspace", cloneName); rebin->execute(); } canClone = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(cloneName); // Check for same binning across sample and container if (!checkWorkspaceBinningMatches(sampleWs, canClone)) { const char *text = "Binning on sample and container does not match." "Would you like to rebin the container to match the sample?"; int result = QMessageBox::question(NULL, tr("Rebin sample?"), tr(text), QMessageBox::Yes, QMessageBox::No, QMessageBox::NoButton); if (result == QMessageBox::Yes) { addRebinStep(QString::fromStdString(canName), QString::fromStdString(m_sampleWorkspaceName)); } else { m_batchAlgoRunner->clearQueue(); g_log.error("Cannot apply absorption corrections " "using a sample and " "container with different binning."); return; } } // If not in wavelength then do conversion std::string originalCanUnits = canClone->getAxis(0)->unit()->unitID(); if (originalCanUnits != "Wavelength") { g_log.information("Container workspace not in wavelength, need to " "convert to continue."); absCorProps["CanWorkspace"] = addConvertUnitsStep(canClone, "Wavelength"); } else { absCorProps["CanWorkspace"] = cloneName; } const bool useCanScale = m_uiForm.ckScaleCan->isChecked(); if (useCanScale) { const double canScaleFactor = m_uiForm.spCanScale->value(); applyCorrAlg->setProperty("CanScaleFactor", canScaleFactor); } } if (useCorrections) { QString correctionsWsName = m_uiForm.dsCorrections->getCurrentDataName(); WorkspaceGroup_sptr corrections = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>( correctionsWsName.toStdString()); bool interpolateAll = false; for (size_t i = 0; i < corrections->size(); i++) { MatrixWorkspace_sptr factorWs = boost::dynamic_pointer_cast<MatrixWorkspace>(corrections->getItem(i)); // Check for matching binning if (sampleWs && (sampleWs->blocksize() != factorWs->blocksize())) { int result; if (interpolateAll) { result = QMessageBox::Yes; } else { std::string text = "Number of bins on sample and " + factorWs->name() + " workspace does not match.\n" + "Would you like to interpolate this workspace to " "match the sample?"; result = QMessageBox::question( NULL, tr("Interpolate corrections?"), tr(text.c_str()), QMessageBox::YesToAll, QMessageBox::Yes, QMessageBox::No); } switch (result) { case QMessageBox::YesToAll: interpolateAll = true; // fall through case QMessageBox::Yes: addInterpolationStep(factorWs, absCorProps["SampleWorkspace"]); break; default: m_batchAlgoRunner->clearQueue(); g_log.error("ApplyPaalmanPings cannot run with corrections that do " "not match sample binning."); return; } } } applyCorrAlg->setProperty("CorrectionsWorkspace", correctionsWsName.toStdString()); } // Generate output workspace name auto QStrSampleWsName = QString::fromStdString(m_sampleWorkspaceName); int nameCutIndex = QStrSampleWsName.lastIndexOf("_"); if (nameCutIndex == -1) nameCutIndex = QStrSampleWsName.length(); QString correctionType; switch (m_uiForm.cbGeometry->currentIndex()) { case 0: correctionType = "flt"; break; case 1: correctionType = "cyl"; break; case 2: correctionType = "anl"; break; } QString outputWsName = QStrSampleWsName.left(nameCutIndex); // Using corrections if (m_uiForm.ckUseCorrections->isChecked()) { outputWsName += "_" + correctionType + "_Corrected"; } else { outputWsName += "_Subtracted"; } // Using container if (m_uiForm.ckUseCan->isChecked()) { const auto canName = m_uiForm.dsContainer->getCurrentDataName().toStdString(); MatrixWorkspace_sptr containerWs = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(canName); auto run = containerWs->run(); if (run.hasProperty("run_number")) { outputWsName += "_" + QString::fromStdString(run.getProperty("run_number")->value()); } else { auto canCutIndex = QString::fromStdString(canName).indexOf("_"); outputWsName += "_" + QString::fromStdString(canName).left(canCutIndex); } } outputWsName += "_red"; applyCorrAlg->setProperty("OutputWorkspace", outputWsName.toStdString()); // Add corrections algorithm to queue m_batchAlgoRunner->addAlgorithm(applyCorrAlg, absCorProps); // Run algorithm queue connect(m_batchAlgoRunner, SIGNAL(batchComplete(bool)), this, SLOT(absCorComplete(bool))); m_batchAlgoRunner->executeBatchAsync(); // Set the result workspace for Python script export m_pythonExportWsName = outputWsName.toStdString(); // m_containerWorkspaceName = m_uiForm.dsContainer->getCurrentDataName(); // updateContainer(); }