void ALCDataLoadingPresenter::load() { m_view->setWaitingCursor(); try { IAlgorithm_sptr alg = AlgorithmManager::Instance().create("PlotAsymmetryByLogValue"); alg->setChild(true); // Don't want workspaces in the ADS alg->setProperty("FirstRun", m_view->firstRun()); alg->setProperty("LastRun", m_view->lastRun()); alg->setProperty("LogValue", m_view->log()); alg->setProperty("Type", m_view->calculationType()); // If time limiting requested, set min/max times if (auto timeRange = m_view->timeRange()) { alg->setProperty("TimeMin", timeRange->first); alg->setProperty("TimeMax", timeRange->second); } alg->setPropertyValue("OutputWorkspace", "__NotUsed"); alg->execute(); m_loadedData = alg->getProperty("OutputWorkspace"); assert(m_loadedData); // If errors are properly caught, shouldn't happen assert(m_loadedData->getNumberHistograms() == 1); // PlotAsymmetryByLogValue guarantees that m_view->setDataCurve(*(ALCHelper::curveDataFromWs(m_loadedData, 0))); } catch(std::exception& e) { m_view->displayError(e.what()); } m_view->restoreCursor(); }
/** * Perform analysis on the given workspace using the parameters supplied * (using the MuonProcess algorithm) * @param inputWS :: [input] Workspace to analyse (previously grouped and * dead-time corrected) * @param options :: [input] Struct containing parameters for what sort of * analysis to do * @returns :: Workspace containing analysed data */ Workspace_sptr MuonAnalysisDataLoader::createAnalysisWorkspace( const Workspace_sptr inputWS, const AnalysisOptions &options) const { IAlgorithm_sptr alg = AlgorithmManager::Instance().createUnmanaged("MuonProcess"); alg->initialize(); // Set input workspace property auto inputGroup = boost::make_shared<WorkspaceGroup>(); // If is a group, will need to handle periods if (auto group = boost::dynamic_pointer_cast<WorkspaceGroup>(inputWS)) { for (int i = 0; i < group->getNumberOfEntries(); i++) { auto ws = boost::dynamic_pointer_cast<MatrixWorkspace>(group->getItem(i)); inputGroup->addWorkspace(ws); } alg->setProperty("SummedPeriodSet", options.summedPeriods); alg->setProperty("SubtractedPeriodSet", options.subtractedPeriods); } else if (auto ws = boost::dynamic_pointer_cast<MatrixWorkspace>(inputWS)) { // Put this single WS into a group and set it as the input property inputGroup->addWorkspace(ws); alg->setProperty("SummedPeriodSet", "1"); } else { throw std::runtime_error( "Cannot create analysis workspace: unsupported workspace type"); } alg->setProperty("InputWorkspace", inputGroup); // Set the rest of the algorithm properties setProcessAlgorithmProperties(alg, options); // We don't want workspace in the ADS so far alg->setChild(true); alg->setPropertyValue("OutputWorkspace", "__NotUsed"); alg->execute(); return alg->getProperty("OutputWorkspace"); }
/** * Mask edges of a RectangularDetector * @param ws :: Input workspace * @param left :: number of columns to mask left * @param right :: number of columns to mask right * @param high :: number of rows to mask top * @param low :: number of rows to mask Bottom * @param componentName :: Must be a RectangularDetector */ void CalculateEfficiency::maskEdges(MatrixWorkspace_sptr ws, int left, int right, int high, int low, const std::string &componentName) { auto instrument = ws->getInstrument(); boost::shared_ptr<Mantid::Geometry::RectangularDetector> component; try { component = boost::const_pointer_cast<Mantid::Geometry::RectangularDetector>( boost::dynamic_pointer_cast< const Mantid::Geometry::RectangularDetector>( instrument->getComponentByName(componentName))); } catch (std::exception &) { g_log.warning("Expecting the component " + componentName + " to be a RectangularDetector. maskEdges not executed."); return; } if (!component) { g_log.warning("Component " + componentName + " is not a RectangularDetector. MaskEdges not executed."); return; } std::vector<int> IDs; int i = 0; while (i < left * component->idstep()) { IDs.push_back(component->idstart() + i); i += 1; } // right i = component->maxDetectorID() - right * component->idstep(); while (i < component->maxDetectorID()) { IDs.push_back(i); i += 1; } // low: 0,256,512,768,..,1,257,513 for (int row = 0; row < low; row++) { i = row + component->idstart(); while (i < component->nelements() * component->idstep() - component->idstep() + low + component->idstart()) { IDs.push_back(i); i += component->idstep(); } } // high # 255, 511, 767.. for (int row = 0; row < high; row++) { i = component->idstep() + component->idstart() - row - 1; while (i < component->nelements() * component->idstep() + component->idstart()) { IDs.push_back(i); i += component->idstep(); } } g_log.debug() << "CalculateEfficiency::maskEdges Detector Ids to Mask:" << std::endl; for (auto id : IDs) { g_log.debug() << id << " "; } g_log.debug() << std::endl; IAlgorithm_sptr maskAlg = createChildAlgorithm("MaskDetectors"); maskAlg->setChild(true); maskAlg->setProperty("Workspace", ws); maskAlg->setProperty("DetectorList", IDs); maskAlg->execute(); }
/** Loads the instrument into a workspace. */ void VesuvioL1ThetaResolution::loadInstrument() { // Get the filename for the VESUVIO IDF MatrixWorkspace_sptr tempWS = WorkspaceFactory::Instance().create("Workspace2D", 1, 1, 1); const std::string vesuvioIPF = tempWS->getInstrumentFilename("VESUVIO"); // Load an empty VESUVIO instrument workspace IAlgorithm_sptr loadInst = AlgorithmManager::Instance().create("LoadEmptyInstrument"); loadInst->initialize(); loadInst->setChild(true); loadInst->setLogging(false); loadInst->setProperty("OutputWorkspace", "__evs"); loadInst->setProperty("Filename", vesuvioIPF); loadInst->execute(); m_instWorkspace = loadInst->getProperty("OutputWorkspace"); // Load the PAR file if provided const std::string parFilename = getPropertyValue("PARFile"); if (!parFilename.empty()) { g_log.information() << "Loading PAR file: " << parFilename << '\n'; // Get header format std::map<size_t, std::string> headerFormats; headerFormats[5] = "spectrum,theta,t0,-,R"; headerFormats[6] = "spectrum,-,theta,t0,-,R"; std::ifstream parFile(parFilename); if (!parFile) { throw std::runtime_error("Cannot open PAR file"); } std::string header; getline(parFile, header); g_log.debug() << "PAR file header: " << header << '\n'; boost::trim(header); std::vector<std::string> headers; boost::split(headers, header, boost::is_any_of("\t "), boost::token_compress_on); size_t numCols = headers.size(); g_log.debug() << "PAR file columns: " << numCols << '\n'; std::string headerFormat = headerFormats[numCols]; if (headerFormat.empty()) { std::stringstream error; error << "Unrecognised PAR file header. Number of colums: " << numCols << " (expected either 5 or 6."; throw std::runtime_error(error.str()); } g_log.debug() << "PAR file header format: " << headerFormat << '\n'; // Update instrument IAlgorithm_sptr updateInst = AlgorithmManager::Instance().create("UpdateInstrumentFromFile"); updateInst->initialize(); updateInst->setChild(true); updateInst->setLogging(false); updateInst->setProperty("Workspace", m_instWorkspace); updateInst->setProperty("Filename", parFilename); updateInst->setProperty("MoveMonitors", false); updateInst->setProperty("IgnorePhi", true); updateInst->setProperty("AsciiHeader", headerFormat); updateInst->execute(); m_instWorkspace = updateInst->getProperty("Workspace"); } const int specIdxMin = static_cast<int>( m_instWorkspace->getIndexFromSpectrumNumber(getProperty("SpectrumMin"))); const int specIdxMax = static_cast<int>( m_instWorkspace->getIndexFromSpectrumNumber(getProperty("SpectrumMax"))); // Crop the workspace to just the detectors we are interested in IAlgorithm_sptr crop = AlgorithmManager::Instance().create("CropWorkspace"); crop->initialize(); crop->setChild(true); crop->setLogging(false); crop->setProperty("InputWorkspace", m_instWorkspace); crop->setProperty("OutputWorkspace", "__evs"); crop->setProperty("StartWorkspaceIndex", specIdxMin); crop->setProperty("EndWorkspaceIndex", specIdxMax); crop->execute(); m_instWorkspace = crop->getProperty("OutputWorkspace"); m_sample = m_instWorkspace->getInstrument()->getSample(); }
/** * Load data from the given files into a struct * @param files :: [input] List of files to load * @returns :: struct with loaded data */ LoadResult MuonAnalysisDataLoader::loadFiles(const QStringList &files) const { if (files.empty()) throw std::invalid_argument("Supplied list of files is empty"); // Convert list of files into a mangled map key const auto toString = [](QStringList qsl) { std::ostringstream oss; qsl.sort(); for (const QString &qs : qsl) { oss << qs.toStdString() << ","; } return oss.str(); }; // Clean cache from stale files etc updateCache(); // Check cache to see if we've loaded this set of files before const std::string fileString = toString(files); if (m_loadedDataCache.find(fileString) != m_loadedDataCache.end()) { g_log.information("Using cached workspace for file(s): " + fileString); return m_loadedDataCache[fileString]; } LoadResult result; std::vector<Workspace_sptr> loadedWorkspaces; std::string instrName; // Instrument name all the run files should belong to // Go through all the files and try to load them for (const auto &fileName : files) { std::string file = fileName.toStdString(); // Set up load algorithm IAlgorithm_sptr load = AlgorithmManager::Instance().createUnmanaged("LoadMuonNexus"); load->initialize(); load->setChild(true); load->setPropertyValue("Filename", file); // Just to pass validation load->setPropertyValue("OutputWorkspace", "__NotUsed"); if (fileName == files.first()) { // These are only needed for the first file if (m_deadTimesType == DeadTimesType::FromFile) { load->setPropertyValue("DeadTimeTable", "__NotUsed"); } load->setPropertyValue("DetectorGroupingTable", "__NotUsed"); } load->execute(); Workspace_sptr loadedWorkspace = load->getProperty("OutputWorkspace"); if (fileName == files.first()) { instrName = getInstrumentName(loadedWorkspace); // Check that it is a valid Muon instrument if (!m_instruments.contains(QString::fromStdString(instrName), Qt::CaseInsensitive)) { if (0 != instrName.compare("DEVA")) { // special case - no IDF but let it load anyway throw std::runtime_error("Instrument is not recognized: " + instrName); } } if (m_deadTimesType == DeadTimesType::FromFile) { result.loadedDeadTimes = load->getProperty("DeadTimeTable"); } result.loadedGrouping = load->getProperty("DetectorGroupingTable"); result.mainFieldDirection = static_cast<std::string>(load->getProperty("MainFieldDirection")); result.timeZero = load->getProperty("TimeZero"); result.firstGoodData = load->getProperty("FirstGoodData"); } else { if (getInstrumentName(loadedWorkspace) != instrName) throw std::runtime_error( "All the files should be produced by the same instrument"); } loadedWorkspaces.push_back(loadedWorkspace); } // Some of the ARGUS data files contain wrong information about the // instrument main field direction. It is always longitudinal. if (instrName == "ARGUS") { result.mainFieldDirection = "longitudinal"; } if (loadedWorkspaces.size() == 1) { // If single workspace loaded - use it Workspace_sptr ws = loadedWorkspaces.front(); result.loadedWorkspace = ws; result.label = MuonAnalysisHelper::getRunLabel(ws); } else { // If multiple workspaces loaded - sum them to get the one to work with try { result.loadedWorkspace = MuonAnalysisHelper::sumWorkspaces(loadedWorkspaces); } catch (std::exception &e) { std::ostringstream error; error << "Unable to sum workspaces together: " << e.what() << "\n"; error << "Make sure they have equal dimensions and number of periods."; throw std::runtime_error(error.str()); } result.label = MuonAnalysisHelper::getRunLabel(loadedWorkspaces); } // Cache the result if we should so we don't have to load it next time if (shouldBeCached(files)) { g_log.information("Caching loaded workspace for file(s): " + fileString); m_loadedDataCache[fileString] = result; } return result; }
/** Stitches the workspaces created by the given rows together. @param rows : the list of rows */ void ReflMainViewPresenter::stitchRows(std::vector<size_t> rows) { //If we can get away with doing nothing, do. if(rows.size() < 2) return; //Ensure the rows are in order. std::sort(rows.begin(), rows.end()); //Properties for Stitch1DMany std::vector<std::string> wsNames; std::vector<std::string> runs; std::vector<double> params; std::vector<double> startOverlaps; std::vector<double> endOverlaps; //Go through each row and prepare the properties for(auto rowIt = rows.begin(); rowIt != rows.end(); ++rowIt) { const std::string runStr = m_model->String(*rowIt, COL_RUNS); const std::string qMinStr = m_model->String(*rowIt, COL_QMIN); const std::string qMaxStr = m_model->String(*rowIt, COL_QMAX); double qmin, qmax; Mantid::Kernel::Strings::convert<double>(qMinStr, qmin); Mantid::Kernel::Strings::convert<double>(qMaxStr, qmax); runs.push_back(runStr); wsNames.push_back(runStr + "_IvsQ"); startOverlaps.push_back(qmin); endOverlaps.push_back(qmax); } double dqq; std::string dqqStr = m_model->String(rows.front(), COL_DQQ); Mantid::Kernel::Strings::convert<double>(dqqStr, dqq); //params are qmin, -dqq, qmax for the final output params.push_back(*std::min_element(startOverlaps.begin(), startOverlaps.end())); params.push_back(-dqq); params.push_back(*std::max_element(endOverlaps.begin(), endOverlaps.end())); //startOverlaps and endOverlaps need to be slightly offset from each other //See usage examples of Stitch1DMany to see why we discard first qmin and last qmax startOverlaps.erase(startOverlaps.begin()); endOverlaps.pop_back(); std::string outputWSName = boost::algorithm::join(runs, "_") + "_IvsQ"; IAlgorithm_sptr algStitch = AlgorithmManager::Instance().create("Stitch1DMany"); algStitch->initialize(); algStitch->setChild(true); algStitch->setProperty("InputWorkspaces", boost::algorithm::join(wsNames, ",")); algStitch->setProperty("OutputWorkspace", outputWSName); algStitch->setProperty("Params", params); algStitch->setProperty("StartOverlaps", startOverlaps); algStitch->setProperty("EndOverlaps", endOverlaps); algStitch->execute(); if(!algStitch->isExecuted()) throw std::runtime_error("Failed to run Stitch1DMany on IvsQ workspaces."); Workspace_sptr stitchedWS = algStitch->getProperty("OutputWorkspace"); //Insert the final stitched row into the ADS AnalysisDataService::Instance().addOrReplace(outputWSName, stitchedWS); }
/** * Handles creating a diff of two workspaces and plotting it. */ void DataComparison::plotDiffWorkspace() { // Detach old curve if(m_diffCurve != NULL) m_diffCurve->attach(NULL); // Do nothing if there are not two workspaces if(m_diffWorkspaceNames.first.isEmpty() || m_diffWorkspaceNames.second.isEmpty()) return; // Get pointers to the workspaces to be diffed MatrixWorkspace_sptr ws1 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>( m_diffWorkspaceNames.first.toStdString()); MatrixWorkspace_sptr ws2 = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>( m_diffWorkspaceNames.second.toStdString()); int ws1Spec = 0; int ws2Spec = 0; // Get the current spectrum for each workspace int numRows = m_uiForm.twCurrentData->rowCount(); for(int row = 0; row < numRows; row++) { QString workspaceName = m_uiForm.twCurrentData->item(row, WORKSPACE_NAME)->text(); QString currentSpecName = m_uiForm.twCurrentData->item(row, CURRENT_SPEC)->text(); bool ok = false; bool found = false; if(workspaceName == m_diffWorkspaceNames.first) { ws1Spec = currentSpecName.toInt(&ok); found = true; } if(workspaceName == m_diffWorkspaceNames.second) { ws2Spec = currentSpecName.toInt(&ok); found = true; } // Check that the spectra are not out of range if(!ok && found) { // Set info message QString infoMessage = workspaceName + ": Index out of range."; m_uiForm.lbDiffInfo->setText(infoMessage); return; } } // Extract the current spectrum for both workspaces IAlgorithm_sptr extractWs1Alg = AlgorithmManager::Instance().create("ExtractSingleSpectrum"); extractWs1Alg->setChild(true); extractWs1Alg->initialize(); extractWs1Alg->setProperty("InputWorkspace", ws1); extractWs1Alg->setProperty("OutputWorkspace", "__ws1_spec"); extractWs1Alg->setProperty("WorkspaceIndex", ws1Spec); extractWs1Alg->execute(); MatrixWorkspace_sptr ws1SpecWs = extractWs1Alg->getProperty("OutputWorkspace"); IAlgorithm_sptr extractWs2Alg = AlgorithmManager::Instance().create("ExtractSingleSpectrum"); extractWs2Alg->setChild(true); extractWs2Alg->initialize(); extractWs2Alg->setProperty("InputWorkspace", ws2); extractWs2Alg->setProperty("OutputWorkspace", "__ws2_spec"); extractWs2Alg->setProperty("WorkspaceIndex", ws2Spec); extractWs2Alg->execute(); MatrixWorkspace_sptr ws2SpecWs = extractWs2Alg->getProperty("OutputWorkspace"); // Rebin the second workspace to the first // (needed for identical binning for Minus algorithm) IAlgorithm_sptr rebinAlg = AlgorithmManager::Instance().create("RebinToWorkspace"); rebinAlg->setChild(true); rebinAlg->initialize(); rebinAlg->setProperty("WorkspaceToRebin", ws2SpecWs); rebinAlg->setProperty("WorkspaceToMatch", ws1SpecWs); rebinAlg->setProperty("OutputWorkspace", "__ws2_spec_rebin"); rebinAlg->execute(); MatrixWorkspace_sptr rebinnedWs2SpecWs = rebinAlg->getProperty("OutputWorkspace"); // Subtract the two extracted spectra IAlgorithm_sptr minusAlg = AlgorithmManager::Instance().create("Minus"); minusAlg->setChild(true); minusAlg->initialize(); minusAlg->setProperty("LHSWorkspace", ws1SpecWs); minusAlg->setProperty("RHSWorkspace", rebinnedWs2SpecWs); minusAlg->setProperty("OutputWorkspace", "__diff"); minusAlg->execute(); MatrixWorkspace_sptr diffWorkspace = minusAlg->getProperty("OutputWorkspace"); // Create curve and add to plot QwtWorkspaceSpectrumData wsData(*diffWorkspace, 0, false, false); boost::shared_ptr<QwtPlotCurve> curve(new QwtPlotCurve); curve->setData(wsData); curve->setPen(QColor(Qt::green)); curve->attach(m_plot); m_diffCurve = curve; // Set info message QString infoMessage = m_diffWorkspaceNames.first + "(" + QString::number(ws1Spec) + ") - " + m_diffWorkspaceNames.second + "(" + QString::number(ws2Spec) + ")"; m_uiForm.lbDiffInfo->setText(infoMessage); }
/** * Load new data and update the view accordingly * @param lastFile :: [input] Last file in range (user-specified or auto) */ void ALCDataLoadingPresenter::load(const std::string &lastFile) { m_view->disableAll(); // Use Path.toString() to ensure both are in same (native) format Poco::Path firstRun(m_view->firstRun()); Poco::Path lastRun(lastFile); // Before loading, check custom grouping (if used) is sensible const bool groupingOK = checkCustomGrouping(); if (!groupingOK) { m_view->displayError( "Custom grouping not valid (bad format or detector numbers)"); m_view->enableAll(); return; } try { IAlgorithm_sptr alg = AlgorithmManager::Instance().create("PlotAsymmetryByLogValue"); alg->setChild(true); // Don't want workspaces in the ADS alg->setProperty("FirstRun", firstRun.toString()); alg->setProperty("LastRun", lastRun.toString()); alg->setProperty("LogValue", m_view->log()); alg->setProperty("Function", m_view->function()); alg->setProperty("Type", m_view->calculationType()); alg->setProperty("DeadTimeCorrType", m_view->deadTimeType()); alg->setProperty("Red", m_view->redPeriod()); // If time limiting requested, set min/max times if (auto timeRange = m_view->timeRange()) { double timeMin = (*timeRange).first; double timeMax = (*timeRange).second; if (timeMin >= timeMax) { throw std::invalid_argument("Invalid time limits"); } alg->setProperty("TimeMin", timeMin); alg->setProperty("TimeMax", timeMax); } // If corrections from custom file requested, set file property if (m_view->deadTimeType() == "FromSpecifiedFile") { alg->setProperty("DeadTimeCorrFile", m_view->deadTimeFile()); } // If custom grouping requested, set forward/backward groupings if (m_view->detectorGroupingType() == "Custom") { alg->setProperty("ForwardSpectra", m_view->getForwardGrouping()); alg->setProperty("BackwardSpectra", m_view->getBackwardGrouping()); } // If Subtract checkbox is selected, set green period if (m_view->subtractIsChecked()) { alg->setProperty("Green", m_view->greenPeriod()); } alg->setPropertyValue("OutputWorkspace", "__NotUsed"); // Execute async so we can show progress bar Poco::ActiveResult<bool> result(alg->executeAsync()); while (!result.available()) { QCoreApplication::processEvents(); } if (!result.error().empty()) { throw std::runtime_error(result.error()); } m_loadedData = alg->getProperty("OutputWorkspace"); // If errors are properly caught, shouldn't happen assert(m_loadedData); // If subtract is not checked, only one spectrum, // else four spectra if (!m_view->subtractIsChecked()) { assert(m_loadedData->getNumberHistograms() == 1); } else { assert(m_loadedData->getNumberHistograms() == 4); } // Plot spectrum 0. It is either red period (if subtract is unchecked) or // red - green (if subtract is checked) m_view->setDataCurve(*(ALCHelper::curveDataFromWs(m_loadedData, 0)), ALCHelper::curveErrorsFromWs(m_loadedData, 0)); emit dataChanged(); } catch (std::exception &e) { m_view->displayError(e.what()); } m_view->enableAll(); }
void HFIRDarkCurrentSubtraction::exec() { std::string output_message = ""; // Reduction property manager const std::string reductionManagerName = getProperty("ReductionProperties"); boost::shared_ptr<PropertyManager> reductionManager; if (PropertyManagerDataService::Instance().doesExist(reductionManagerName)) { reductionManager = PropertyManagerDataService::Instance().retrieve(reductionManagerName); } else { reductionManager = boost::make_shared<PropertyManager>(); PropertyManagerDataService::Instance().addOrReplace(reductionManagerName, reductionManager); } // If the load algorithm isn't in the reduction properties, add it const bool persistent = getProperty("PersistentCorrection"); if (!reductionManager->existsProperty("DarkCurrentAlgorithm") && persistent) { AlgorithmProperty *algProp = new AlgorithmProperty("DarkCurrentAlgorithm"); algProp->setValue(toString()); reductionManager->declareProperty(algProp); } Progress progress(this,0.0,1.0,10); MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); const std::string fileName = getPropertyValue("Filename"); MatrixWorkspace_sptr darkWS; std::string darkWSName = getPropertyValue("OutputDarkCurrentWorkspace"); progress.report("Subtracting dark current"); // Look for an entry for the dark current in the reduction table Poco::Path path(fileName); const std::string entryName = "DarkCurrent"+path.getBaseName(); if (reductionManager->existsProperty(entryName)) { darkWS = reductionManager->getProperty(entryName); darkWSName = reductionManager->getPropertyValue(entryName); output_message += darkWSName + '\n'; } else { // Load the dark current if we don't have it already if (darkWSName.size()==0) { darkWSName = "__dark_current_"+path.getBaseName(); setPropertyValue("OutputDarkCurrentWorkspace", darkWSName); } IAlgorithm_sptr loadAlg; if (!reductionManager->existsProperty("LoadAlgorithm")) { loadAlg = createChildAlgorithm("HFIRLoad", 0.1, 0.3); loadAlg->setProperty("Filename", fileName); loadAlg->setProperty("ReductionProperties", reductionManagerName); loadAlg->executeAsChildAlg(); } else { IAlgorithm_sptr loadAlg0 = reductionManager->getProperty("LoadAlgorithm"); const std::string loadString = loadAlg0->toString(); loadAlg = Algorithm::fromString(loadString); loadAlg->setChild(true); loadAlg->setProperty("Filename", fileName); loadAlg->setProperty("ReductionProperties", reductionManagerName); loadAlg->setPropertyValue("OutputWorkspace", darkWSName); loadAlg->execute(); } darkWS = loadAlg->getProperty("OutputWorkspace"); output_message += "\n Loaded " + fileName + "\n"; if (loadAlg->existsProperty("OutputMessage")) { std::string msg = loadAlg->getPropertyValue("OutputMessage"); output_message += " |" + Poco::replace(msg, "\n", "\n |") + "\n"; } setProperty("OutputDarkCurrentWorkspace", darkWS); reductionManager->declareProperty(new WorkspaceProperty<>(entryName,"",Direction::Output)); reductionManager->setPropertyValue(entryName, darkWSName); reductionManager->setProperty(entryName, darkWS); } progress.report(3, "Loaded dark current"); // Perform subtraction double darkTimer = getCountingTime(darkWS); double dataTimer = getCountingTime(inputWS); IAlgorithm_sptr scaleAlg = createChildAlgorithm("Scale", 0.3, 0.5); scaleAlg->setProperty("InputWorkspace", darkWS); scaleAlg->setProperty("Factor", dataTimer/darkTimer); scaleAlg->setProperty("Operation", "Multiply"); scaleAlg->executeAsChildAlg(); MatrixWorkspace_sptr scaledDarkWS = scaleAlg->getProperty("OutputWorkspace"); // Zero out timer and monitor so that we don't subtract them out for(size_t i=0; i<scaledDarkWS->dataY(0).size(); i++) { scaledDarkWS->dataY(DEFAULT_TIMER_ID)[i]=0.0; scaledDarkWS->dataE(DEFAULT_TIMER_ID)[i]=0.0; scaledDarkWS->dataY(DEFAULT_MONITOR_ID)[i]=0.0; scaledDarkWS->dataE(DEFAULT_MONITOR_ID)[i]=0.0; } IAlgorithm_sptr minusAlg = createChildAlgorithm("Minus", 0.5, 0.7); minusAlg->setProperty("LHSWorkspace", inputWS); minusAlg->setProperty("RHSWorkspace", scaledDarkWS); MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); minusAlg->setProperty("OutputWorkspace", outputWS); minusAlg->executeAsChildAlg(); MatrixWorkspace_sptr correctedWS = minusAlg->getProperty("OutputWorkspace"); setProperty("OutputWorkspace", correctedWS); setProperty("OutputMessage", "Dark current subtracted: "+output_message); progress.report("Subtracted dark current"); }
void SANSSensitivityCorrection::exec() { // Output log m_output_message = ""; Progress progress(this, 0.0, 1.0, 10); // Reduction property manager const std::string reductionManagerName = getProperty("ReductionProperties"); boost::shared_ptr<PropertyManager> reductionManager; if (PropertyManagerDataService::Instance().doesExist(reductionManagerName)) { reductionManager = PropertyManagerDataService::Instance().retrieve(reductionManagerName); } else { reductionManager = boost::make_shared<PropertyManager>(); PropertyManagerDataService::Instance().addOrReplace(reductionManagerName, reductionManager); } if (!reductionManager->existsProperty("SensitivityAlgorithm")) { auto algProp = make_unique<AlgorithmProperty>("SensitivityAlgorithm"); algProp->setValue(toString()); reductionManager->declareProperty(std::move(algProp)); } progress.report("Loading sensitivity file"); const std::string fileName = getPropertyValue("Filename"); // Look for an entry for the dark current in the reduction table Poco::Path path(fileName); const std::string entryName = "Sensitivity" + path.getBaseName(); MatrixWorkspace_sptr floodWS; std::string floodWSName = "__sensitivity_" + path.getBaseName(); if (reductionManager->existsProperty(entryName)) { std::string wsName = reductionManager->getPropertyValue(entryName); floodWS = boost::dynamic_pointer_cast<MatrixWorkspace>( AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(wsName)); m_output_message += " |Using " + wsName + "\n"; g_log.debug() << "SANSSensitivityCorrection :: Using sensitivity workspace: " << wsName << "\n"; } else { // Load the flood field if we don't have it already // First, try to determine whether we need to load data or a sensitivity // workspace... if (!floodWS && fileCheck(fileName)) { g_log.debug() << "SANSSensitivityCorrection :: Loading sensitivity file: " << fileName << "\n"; IAlgorithm_sptr loadAlg = createChildAlgorithm("Load", 0.1, 0.3); loadAlg->setProperty("Filename", fileName); loadAlg->executeAsChildAlg(); Workspace_sptr floodWS_ws = loadAlg->getProperty("OutputWorkspace"); floodWS = boost::dynamic_pointer_cast<MatrixWorkspace>(floodWS_ws); // Check that it's really a sensitivity file if (!floodWS->run().hasProperty("is_sensitivity")) { // Reset pointer floodWS.reset(); g_log.error() << "A processed Mantid workspace was loaded but it " "wasn't a sensitivity file!\n"; } } // ... if we don't, just load the data and process it if (!floodWS) { // Read in default beam center double center_x = getProperty("BeamCenterX"); double center_y = getProperty("BeamCenterY"); if (isEmpty(center_x) || isEmpty(center_y)) { if (reductionManager->existsProperty("LatestBeamCenterX") && reductionManager->existsProperty("LatestBeamCenterY")) { center_x = reductionManager->getProperty("LatestBeamCenterX"); center_y = reductionManager->getProperty("LatestBeamCenterY"); m_output_message += " |Setting beam center to [" + Poco::NumberFormatter::format(center_x, 1) + ", " + Poco::NumberFormatter::format(center_y, 1) + "]\n"; } else m_output_message += " |No beam center provided: skipping!\n"; } const std::string rawFloodWSName = "__flood_data_" + path.getBaseName(); MatrixWorkspace_sptr rawFloodWS; if (!reductionManager->existsProperty("LoadAlgorithm")) { IAlgorithm_sptr loadAlg = createChildAlgorithm("Load", 0.1, 0.3); loadAlg->setProperty("Filename", fileName); if (!isEmpty(center_x) && loadAlg->existsProperty("BeamCenterX")) loadAlg->setProperty("BeamCenterX", center_x); if (!isEmpty(center_y) && loadAlg->existsProperty("BeamCenterY")) loadAlg->setProperty("BeamCenterY", center_y); loadAlg->setPropertyValue("OutputWorkspace", rawFloodWSName); loadAlg->executeAsChildAlg(); Workspace_sptr tmpWS = loadAlg->getProperty("OutputWorkspace"); rawFloodWS = boost::dynamic_pointer_cast<MatrixWorkspace>(tmpWS); m_output_message += " | Loaded " + fileName + " (Load algorithm)\n"; } else { // Get load algorithm as a string so that we can create a completely // new proxy and ensure that we don't overwrite existing properties IAlgorithm_sptr loadAlg0 = reductionManager->getProperty("LoadAlgorithm"); const std::string loadString = loadAlg0->toString(); IAlgorithm_sptr loadAlg = Algorithm::fromString(loadString); loadAlg->setChild(true); loadAlg->setProperty("Filename", fileName); loadAlg->setPropertyValue("OutputWorkspace", rawFloodWSName); if (!isEmpty(center_x) && loadAlg->existsProperty("BeamCenterX")) loadAlg->setProperty("BeamCenterX", center_x); if (!isEmpty(center_y) && loadAlg->existsProperty("BeamCenterY")) loadAlg->setProperty("BeamCenterY", center_y); loadAlg->execute(); rawFloodWS = loadAlg->getProperty("OutputWorkspace"); m_output_message += " |Loaded " + fileName + "\n"; if (loadAlg->existsProperty("OutputMessage")) { std::string msg = loadAlg->getPropertyValue("OutputMessage"); m_output_message += " |" + Poco::replace(msg, "\n", "\n |") + "\n"; } } // Check whether we just loaded a flood field data set, or the actual // sensitivity if (!rawFloodWS->run().hasProperty("is_sensitivity")) { const std::string darkCurrentFile = getPropertyValue("DarkCurrentFile"); // Look for a dark current subtraction algorithm std::string dark_result; if (reductionManager->existsProperty("DarkCurrentAlgorithm")) { IAlgorithm_sptr darkAlg = reductionManager->getProperty("DarkCurrentAlgorithm"); darkAlg->setChild(true); darkAlg->setProperty("InputWorkspace", rawFloodWS); darkAlg->setProperty("OutputWorkspace", rawFloodWS); // Execute as-is if we use the sample dark current, otherwise check // whether a dark current file was provided. // Otherwise do nothing if (getProperty("UseSampleDC")) { darkAlg->execute(); if (darkAlg->existsProperty("OutputMessage")) dark_result = darkAlg->getPropertyValue("OutputMessage"); } else if (!darkCurrentFile.empty()) { darkAlg->setProperty("Filename", darkCurrentFile); darkAlg->setProperty("PersistentCorrection", false); darkAlg->execute(); if (darkAlg->existsProperty("OutputMessage")) dark_result = darkAlg->getPropertyValue("OutputMessage"); else dark_result = " Dark current subtracted\n"; } } else if (!darkCurrentFile.empty()) { // We need to subtract the dark current for the flood field but no // dark // current subtraction was set for the sample! Use the default dark // current algorithm if we can find it. if (reductionManager->existsProperty("DefaultDarkCurrentAlgorithm")) { IAlgorithm_sptr darkAlg = reductionManager->getProperty("DefaultDarkCurrentAlgorithm"); darkAlg->setChild(true); darkAlg->setProperty("InputWorkspace", rawFloodWS); darkAlg->setProperty("OutputWorkspace", rawFloodWS); darkAlg->setProperty("Filename", darkCurrentFile); darkAlg->setProperty("PersistentCorrection", false); darkAlg->execute(); if (darkAlg->existsProperty("OutputMessage")) dark_result = darkAlg->getPropertyValue("OutputMessage"); } else { // We are running out of options g_log.error() << "No dark current algorithm provided to load [" << getPropertyValue("DarkCurrentFile") << "]: skipped!\n"; dark_result = " No dark current algorithm provided: skipped\n"; } } m_output_message += " |" + Poco::replace(dark_result, "\n", "\n |") + "\n"; // Look for solid angle correction algorithm if (reductionManager->existsProperty("SANSSolidAngleCorrection")) { IAlgorithm_sptr solidAlg = reductionManager->getProperty("SANSSolidAngleCorrection"); solidAlg->setChild(true); solidAlg->setProperty("InputWorkspace", rawFloodWS); solidAlg->setProperty("OutputWorkspace", rawFloodWS); solidAlg->execute(); std::string msg = "Solid angle correction applied\n"; if (solidAlg->existsProperty("OutputMessage")) msg = solidAlg->getPropertyValue("OutputMessage"); m_output_message += " |" + Poco::replace(msg, "\n", "\n |") + "\n"; } // Apply transmission correction as needed double floodTransmissionValue = getProperty("FloodTransmissionValue"); double floodTransmissionError = getProperty("FloodTransmissionError"); if (!isEmpty(floodTransmissionValue)) { g_log.debug() << "SANSSensitivityCorrection :: Applying transmission " "to flood field\n"; IAlgorithm_sptr transAlg = createChildAlgorithm("ApplyTransmissionCorrection"); transAlg->setProperty("InputWorkspace", rawFloodWS); transAlg->setProperty("OutputWorkspace", rawFloodWS); transAlg->setProperty("TransmissionValue", floodTransmissionValue); transAlg->setProperty("TransmissionError", floodTransmissionError); transAlg->setProperty("ThetaDependent", true); transAlg->execute(); rawFloodWS = transAlg->getProperty("OutputWorkspace"); m_output_message += " |Applied transmission to flood field\n"; } // Calculate detector sensitivity IAlgorithm_sptr effAlg = createChildAlgorithm("CalculateEfficiency"); effAlg->setProperty("InputWorkspace", rawFloodWS); const double minEff = getProperty("MinEfficiency"); const double maxEff = getProperty("MaxEfficiency"); const std::string maskFullComponent = getPropertyValue("MaskedFullComponent"); const std::string maskEdges = getPropertyValue("MaskedEdges"); const std::string maskComponent = getPropertyValue("MaskedComponent"); effAlg->setProperty("MinEfficiency", minEff); effAlg->setProperty("MaxEfficiency", maxEff); effAlg->setProperty("MaskedFullComponent", maskFullComponent); effAlg->setProperty("MaskedEdges", maskEdges); effAlg->setProperty("MaskedComponent", maskComponent); effAlg->execute(); floodWS = effAlg->getProperty("OutputWorkspace"); } else { floodWS = rawFloodWS; } // Patch as needed if (reductionManager->existsProperty("SensitivityPatchAlgorithm")) { IAlgorithm_sptr patchAlg = reductionManager->getProperty("SensitivityPatchAlgorithm"); patchAlg->setChild(true); patchAlg->setProperty("Workspace", floodWS); patchAlg->execute(); m_output_message += " |Sensitivity patch applied\n"; } floodWS->mutableRun().addProperty("is_sensitivity", 1, "", true); } std::string floodWSOutputName = getPropertyValue("OutputSensitivityWorkspace"); if (floodWSOutputName.empty()) { setPropertyValue("OutputSensitivityWorkspace", floodWSName); AnalysisDataService::Instance().addOrReplace(floodWSName, floodWS); reductionManager->declareProperty( Kernel::make_unique<WorkspaceProperty<>>(entryName, floodWSName, Direction::InOut)); reductionManager->setPropertyValue(entryName, floodWSName); reductionManager->setProperty(entryName, floodWS); } setProperty("OutputSensitivityWorkspace", floodWS); } progress.report(3, "Loaded flood field"); // Check whether we need to apply the correction to a workspace MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); if (inputWS) { // Divide sample data by detector efficiency IAlgorithm_sptr divideAlg = createChildAlgorithm("Divide", 0.6, 0.7); divideAlg->setProperty("LHSWorkspace", inputWS); divideAlg->setProperty("RHSWorkspace", floodWS); divideAlg->executeAsChildAlg(); MatrixWorkspace_sptr outputWS = divideAlg->getProperty("OutputWorkspace"); // Copy over the efficiency's masked pixels to the reduced workspace IAlgorithm_sptr maskAlg = createChildAlgorithm("MaskDetectors", 0.75, 0.85); maskAlg->setProperty("Workspace", outputWS); maskAlg->setProperty("MaskedWorkspace", floodWS); maskAlg->executeAsChildAlg(); setProperty("OutputWorkspace", outputWS); } setProperty("OutputMessage", "Sensitivity correction computed\n" + m_output_message); progress.report("Performed sensitivity correction"); }