Workspace_sptr GenericDataProcessorAlgorithm<Base>::load(const std::string &inputData, const bool loadQuiet) { Workspace_sptr inputWS; // First, check whether we have the name of an existing workspace if (AnalysisDataService::Instance().doesExist(inputData)) { inputWS = AnalysisDataService::Instance().retrieve(inputData); } else { std::string foundFile = FileFinder::Instance().getFullPath(inputData); if (foundFile.empty()) { // Get facility extensions FacilityInfo facilityInfo = ConfigService::Instance().getFacility(); const std::vector<std::string> facilityExts = facilityInfo.extensions(); foundFile = FileFinder::Instance().findRun(inputData, facilityExts); } if (!foundFile.empty()) { Poco::Path p(foundFile); const std::string outputWSName = p.getBaseName(); IAlgorithm_sptr loadAlg = createChildAlgorithm(m_loadAlg); loadAlg->setProperty(m_loadAlgFileProp, foundFile); if (!loadQuiet) { loadAlg->setAlwaysStoreInADS(true); } // Set up MPI if available #ifdef MPI_BUILD // First, check whether the loader allows use to chunk the data if (loadAlg->existsProperty("ChunkNumber") && loadAlg->existsProperty("TotalChunks")) { m_useMPI = true; // The communicator containing all processes boost::mpi::communicator world; g_log.notice() << "Chunk/Total: " << world.rank() + 1 << "/" << world.size() << '\n'; loadAlg->setPropertyValue("OutputWorkspace", outputWSName); loadAlg->setProperty("ChunkNumber", world.rank() + 1); loadAlg->setProperty("TotalChunks", world.size()); } #endif loadAlg->execute(); if (loadQuiet) { inputWS = loadAlg->getProperty("OutputWorkspace"); } else { inputWS = AnalysisDataService::Instance().retrieve(outputWSName); } } else throw std::runtime_error( "DataProcessorAlgorithm::load could process any data"); } return inputWS; }
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 EQSANSLoad::exec() { // Verify the validity of the inputs // TODO: this should be done by the new data management algorithm used for // live data reduction (when it's implemented...) const std::string fileName = getPropertyValue("Filename"); EventWorkspace_sptr inputEventWS = getProperty("InputWorkspace"); if (fileName.size() == 0 && !inputEventWS) { g_log.error() << "EQSANSLoad input error: Either a valid file path or an " "input workspace must be provided\n"; throw std::runtime_error("EQSANSLoad input error: Either a valid file path " "or an input workspace must be provided"); } else if (fileName.size() > 0 && inputEventWS) { g_log.error() << "EQSANSLoad input error: Either a valid file path or an " "input workspace must be provided, but not both\n"; throw std::runtime_error("EQSANSLoad input error: Either a valid file path " "or an input workspace must be provided, but not " "both"); } // Read in default TOF cuts const bool skipTOFCorrection = getProperty("SkipTOFCorrection"); m_low_TOF_cut = getProperty("LowTOFCut"); m_high_TOF_cut = getProperty("HighTOFCut"); // Read in default beam center m_center_x = getProperty("BeamCenterX"); m_center_y = getProperty("BeamCenterY"); const bool noBeamCenter = getProperty("NoBeamCenter"); // 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("LoadAlgorithm")) { auto loadProp = make_unique<AlgorithmProperty>("LoadAlgorithm"); setPropertyValue("InputWorkspace", ""); setProperty("NoBeamCenter", false); loadProp->setValue(toString()); reductionManager->declareProperty(std::move(loadProp)); } if (!reductionManager->existsProperty("InstrumentName")) { reductionManager->declareProperty( make_unique<PropertyWithValue<std::string>>("InstrumentName", "EQSANS")); } // Output log m_output_message = ""; // Check whether we need to load the data if (!inputEventWS) { const bool loadMonitors = getProperty("LoadMonitors"); IAlgorithm_sptr loadAlg = createChildAlgorithm("LoadEventNexus", 0, 0.2); loadAlg->setProperty("LoadMonitors", loadMonitors); loadAlg->setProperty("MonitorsAsEvents", false); loadAlg->setProperty("Filename", fileName); if (skipTOFCorrection) { if (m_low_TOF_cut > 0.0) loadAlg->setProperty("FilterByTofMin", m_low_TOF_cut); if (m_high_TOF_cut > 0.0) loadAlg->setProperty("FilterByTofMax", m_high_TOF_cut); } loadAlg->execute(); Workspace_sptr dataWS_asWks = loadAlg->getProperty("OutputWorkspace"); dataWS = boost::dynamic_pointer_cast<MatrixWorkspace>(dataWS_asWks); // Get monitor workspace as necessary std::string mon_wsname = getPropertyValue("OutputWorkspace") + "_monitors"; if (loadMonitors && loadAlg->existsProperty("MonitorWorkspace")) { Workspace_sptr monWSOutput = loadAlg->getProperty("MonitorWorkspace"); MatrixWorkspace_sptr monWS = boost::dynamic_pointer_cast<MatrixWorkspace>(monWSOutput); if ((monWSOutput) && (!monWS)) { // this was a group workspace - EQSansLoad does not support multi period // data yet throw Exception::NotImplementedError("The file contains multi period " "data, support for this is not " "implemented in EQSANSLoad yet"); } declareProperty(Kernel::make_unique<WorkspaceProperty<>>( "MonitorWorkspace", mon_wsname, Direction::Output), "Monitors from the Event NeXus file"); setProperty("MonitorWorkspace", monWS); } } else { MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); EventWorkspace_sptr outputEventWS = boost::dynamic_pointer_cast<EventWorkspace>(outputWS); if (inputEventWS != outputEventWS) { IAlgorithm_sptr copyAlg = createChildAlgorithm("CloneWorkspace", 0, 0.2); copyAlg->setProperty("InputWorkspace", inputEventWS); copyAlg->executeAsChildAlg(); Workspace_sptr dataWS_asWks = copyAlg->getProperty("OutputWorkspace"); dataWS = boost::dynamic_pointer_cast<MatrixWorkspace>(dataWS_asWks); } else { dataWS = boost::dynamic_pointer_cast<MatrixWorkspace>(inputEventWS); } } // Get the sample-detector distance double sdd = 0.0; const double sample_det_dist = getProperty("SampleDetectorDistance"); if (!isEmpty(sample_det_dist)) { sdd = sample_det_dist; } else { if (!dataWS->run().hasProperty("detectorZ")) { g_log.error() << "Could not determine Z position: the " "SampleDetectorDistance property was not set " "and the run logs do not contain the detectorZ property\n"; throw std::invalid_argument( "Could not determine Z position: stopping execution"); } const std::string dzName = "detectorZ"; Mantid::Kernel::Property *prop = dataWS->run().getProperty(dzName); Mantid::Kernel::TimeSeriesProperty<double> *dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double> *>(prop); if (!dp) { throw std::runtime_error("Could not cast (interpret) the property " + dzName + " as a time series property value."); } sdd = dp->getStatistics().mean; // Modify SDD according to offset if given const double sample_det_offset = getProperty("SampleDetectorDistanceOffset"); if (!isEmpty(sample_det_offset)) { sdd += sample_det_offset; } } dataWS->mutableRun().addProperty("sample_detector_distance", sdd, "mm", true); // Move the detector to its correct position IAlgorithm_sptr mvAlg = createChildAlgorithm("MoveInstrumentComponent", 0.2, 0.4); mvAlg->setProperty<MatrixWorkspace_sptr>("Workspace", dataWS); mvAlg->setProperty("ComponentName", "detector1"); mvAlg->setProperty("Z", sdd / 1000.0); mvAlg->setProperty("RelativePosition", false); mvAlg->executeAsChildAlg(); g_log.information() << "Moving detector to " << sdd / 1000.0 << " meters\n"; m_output_message += " Detector position: " + Poco::NumberFormatter::format(sdd / 1000.0, 3) + " m\n"; // Get the run number so we can find the proper config file int run_number = 0; std::string config_file = ""; if (dataWS->run().hasProperty("run_number")) { const std::string run_str = dataWS->run().getPropertyValueAsType<std::string>("run_number"); Poco::NumberParser::tryParse(run_str, run_number); // Find a proper config file config_file = findConfigFile(run_number); } else { g_log.error() << "Could not find run number for workspace " << getPropertyValue("OutputWorkspace") << '\n'; m_output_message += " Could not find run number for data file\n"; } // Process the config file bool use_config = getProperty("UseConfig"); if (use_config && config_file.size() > 0) { // Special case to force reading the beam center from the config file // We're adding this to be compatible with the original EQSANS load // written in python if (m_center_x == 0.0 && m_center_y == 0.0) { setProperty("UseConfigBeam", true); } readConfigFile(config_file); } else if (use_config) { use_config = false; g_log.error() << "Cound not find config file for workspace " << getPropertyValue("OutputWorkspace") << '\n'; m_output_message += " Could not find configuration file for run " + Poco::NumberFormatter::format(run_number) + "\n"; } // If we use the config file, move the moderator position if (use_config) { if (m_moderator_position > -13.0) g_log.error() << "Moderator position seems close to the sample, please check\n"; g_log.information() << "Moving moderator to " << m_moderator_position << '\n'; m_output_message += " Moderator position: " + Poco::NumberFormatter::format(m_moderator_position) + " m\n"; mvAlg = createChildAlgorithm("MoveInstrumentComponent", 0.4, 0.45); mvAlg->setProperty<MatrixWorkspace_sptr>("Workspace", dataWS); mvAlg->setProperty("ComponentName", "moderator"); mvAlg->setProperty("Z", m_moderator_position); mvAlg->setProperty("RelativePosition", false); mvAlg->executeAsChildAlg(); } // Get source aperture radius getSourceSlitSize(); // Move the beam center to its proper position if (!noBeamCenter) { if (isEmpty(m_center_x) || isEmpty(m_center_y)) { if (reductionManager->existsProperty("LatestBeamCenterX") && reductionManager->existsProperty("LatestBeamCenterY")) { m_center_x = reductionManager->getProperty("LatestBeamCenterX"); m_center_y = reductionManager->getProperty("LatestBeamCenterY"); } } moveToBeamCenter(); // Add beam center to reduction properties, as the last beam center position // that was used. // This will give us our default position next time. if (!reductionManager->existsProperty("LatestBeamCenterX")) reductionManager->declareProperty(make_unique<PropertyWithValue<double>>( "LatestBeamCenterX", m_center_x)); else reductionManager->setProperty("LatestBeamCenterX", m_center_x); if (!reductionManager->existsProperty("LatestBeamCenterY")) reductionManager->declareProperty(make_unique<PropertyWithValue<double>>( "LatestBeamCenterY", m_center_y)); else reductionManager->setProperty("LatestBeamCenterY", m_center_y); } // Modify TOF const bool correct_for_flight_path = getProperty("CorrectForFlightPath"); double wl_min = 0.0; double wl_max = 0.0; double wl_combined_max = 0.0; if (skipTOFCorrection) { m_output_message += " Skipping EQSANS TOF correction: assuming a single frame\n"; dataWS->mutableRun().addProperty("is_frame_skipping", 0, true); if (correct_for_flight_path) { g_log.error() << "CorrectForFlightPath and SkipTOFCorrection can't be " "set to true at the same time\n"; m_output_message += " Skipped flight path correction: see error log\n"; } } else { m_output_message += " Flight path correction "; if (!correct_for_flight_path) m_output_message += "NOT "; m_output_message += "applied\n"; DataObjects::EventWorkspace_sptr dataWS_evt = boost::dynamic_pointer_cast<EventWorkspace>(dataWS); IAlgorithm_sptr tofAlg = createChildAlgorithm("EQSANSTofStructure", 0.5, 0.7); tofAlg->setProperty<EventWorkspace_sptr>("InputWorkspace", dataWS_evt); tofAlg->setProperty("LowTOFCut", m_low_TOF_cut); tofAlg->setProperty("HighTOFCut", m_high_TOF_cut); tofAlg->setProperty("FlightPathCorrection", correct_for_flight_path); tofAlg->executeAsChildAlg(); wl_min = tofAlg->getProperty("WavelengthMin"); wl_max = tofAlg->getProperty("WavelengthMax"); if (wl_min != wl_min || wl_max != wl_max) { g_log.error() << "Bad wavelength range\n"; g_log.error() << m_output_message << '\n'; } const bool frame_skipping = tofAlg->getProperty("FrameSkipping"); dataWS->mutableRun().addProperty("wavelength_min", wl_min, "Angstrom", true); dataWS->mutableRun().addProperty("wavelength_max", wl_max, "Angstrom", true); dataWS->mutableRun().addProperty("is_frame_skipping", int(frame_skipping), true); wl_combined_max = wl_max; m_output_message += " Wavelength range: " + Poco::NumberFormatter::format(wl_min) + " - " + Poco::NumberFormatter::format(wl_max); if (frame_skipping) { const double wl_min2 = tofAlg->getProperty("WavelengthMinFrame2"); const double wl_max2 = tofAlg->getProperty("WavelengthMaxFrame2"); wl_combined_max = wl_max2; dataWS->mutableRun().addProperty("wavelength_min_frame2", wl_min2, "Angstrom", true); dataWS->mutableRun().addProperty("wavelength_max_frame2", wl_max2, "Angstrom", true); m_output_message += " and " + Poco::NumberFormatter::format(wl_min2) + " - " + Poco::NumberFormatter::format(wl_max2) + " Angstrom\n"; } else m_output_message += " Angstrom\n"; } // Convert to wavelength const double ssd = fabs(dataWS->getInstrument()->getSource()->getPos().Z()) * 1000.0; const double conversion_factor = 3.9560346 / (sdd + ssd); m_output_message += " TOF to wavelength conversion factor: " + Poco::NumberFormatter::format(conversion_factor) + "\n"; if (skipTOFCorrection) { DataObjects::EventWorkspace_sptr dataWS_evt = boost::dynamic_pointer_cast<EventWorkspace>(dataWS); if (dataWS_evt->getNumberEvents() == 0) throw std::invalid_argument("No event to process: check your TOF cuts"); wl_min = dataWS_evt->getTofMin() * conversion_factor; wl_max = dataWS_evt->getTofMax() * conversion_factor; wl_combined_max = wl_max; g_log.information() << "Wavelength range: " << wl_min << " to " << wl_max << '\n'; dataWS->mutableRun().addProperty("wavelength_min", wl_min, "Angstrom", true); dataWS->mutableRun().addProperty("wavelength_max", wl_max, "Angstrom", true); } IAlgorithm_sptr scAlg = createChildAlgorithm("ScaleX", 0.7, 0.71); scAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", dataWS); scAlg->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", dataWS); scAlg->setProperty("Factor", conversion_factor); scAlg->executeAsChildAlg(); dataWS->getAxis(0)->setUnit("Wavelength"); // Rebin so all the wavelength bins are aligned const bool preserveEvents = getProperty("PreserveEvents"); const double wl_step = getProperty("WavelengthStep"); const double wl_min_rounded = round(wl_min * 100.0) / 100.0; const double wl_max_rounded = round(wl_combined_max * 100.0) / 100.0; std::string params = Poco::NumberFormatter::format(wl_min_rounded, 2) + "," + Poco::NumberFormatter::format(wl_step) + "," + Poco::NumberFormatter::format(wl_max_rounded, 2); g_log.information() << "Rebin parameters: " << params << '\n'; IAlgorithm_sptr rebinAlg = createChildAlgorithm("Rebin", 0.71, 0.72); rebinAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", dataWS); if (preserveEvents) rebinAlg->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", dataWS); rebinAlg->setPropertyValue("Params", params); rebinAlg->setProperty("PreserveEvents", preserveEvents); rebinAlg->executeAsChildAlg(); if (!preserveEvents) dataWS = rebinAlg->getProperty("OutputWorkspace"); dataWS->mutableRun().addProperty("event_ws", getPropertyValue("OutputWorkspace"), true); setProperty<MatrixWorkspace_sptr>( "OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(dataWS)); // m_output_message = "Loaded " + fileName + '\n' + m_output_message; setPropertyValue("OutputMessage", m_output_message); }
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"); }