/// Get the source slit size from the slit information of the run properties void EQSANSLoad::getSourceSlitSize() { if (!dataWS->run().hasProperty("vBeamSlit")) { m_output_message += " Could not determine source aperture diameter: "; m_output_message += "slit parameters were not found in the run log\n"; return; } Mantid::Kernel::Property* prop = dataWS->run().getProperty("vBeamSlit"); Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop); int slit1 = (int)dp->getStatistics().mean; prop = dataWS->run().getProperty("vBeamSlit2"); dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop); int slit2 = (int)dp->getStatistics().mean; prop = dataWS->run().getProperty("vBeamSlit3"); dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop); int slit3 = (int)dp->getStatistics().mean; if (slit1<0 && slit2<0 && slit3<0) { m_output_message += " Could not determine source aperture diameter\n"; return; } // Default slit size double S1 = 20.0; double L1 = -1.0; const double ssd = fabs(dataWS->getInstrument()->getSource()->getPos().Z())*1000.0; int slits[3] = {slit1, slit2, slit3}; for (int i=0; i<3; i++) { int m = slits[i]-1; if (m>=0 && m<6) { double x = m_slit_positions[i][m]; double y = ssd - m_slit_to_source[i]; if (L1<0 || x/y<S1/L1) { L1 = y; S1 = x; } } } dataWS->mutableRun().addProperty("source-aperture-diameter", S1, "mm", true); m_output_message += " Source aperture diameter: "; Poco::NumberFormatter::append(m_output_message, S1, 1); m_output_message += " mm\n"; }
double RefReduction::calculateAngleREFL(MatrixWorkspace_sptr workspace) { Mantid::Kernel::Property* prop = workspace->run().getProperty("ths"); Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop); const double ths = dp->getStatistics().mean; prop = workspace->run().getProperty("tthd"); dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop); const double tthd = dp->getStatistics().mean; double offset = getProperty("AngleOffset"); if (isEmpty(offset)) offset = 0.0; return tthd - ths + offset; }
double RefReduction::calculateAngleREFM(MatrixWorkspace_sptr workspace) { double dangle = getProperty("DetectorAngle"); if (isEmpty(dangle)) { Mantid::Kernel::Property* prop = workspace->run().getProperty("DANGLE"); Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop); dangle = dp->getStatistics().mean; } double dangle0 = getProperty("DetectorAngle0"); if (isEmpty(dangle0)) { Mantid::Kernel::Property* prop = workspace->run().getProperty("DANGLE0"); Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop); dangle0 = dp->getStatistics().mean; } Mantid::Kernel::Property* prop = workspace->run().getProperty("SampleDetDis"); Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop); const double det_distance = dp->getStatistics().mean/1000.0; double direct_beam_pix = getProperty("DirectPixel"); if (isEmpty(direct_beam_pix)) { Mantid::Kernel::Property* prop = workspace->run().getProperty("DIRPIX"); Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop); direct_beam_pix = dp->getStatistics().mean; } double ref_pix = getProperty("ReflectivityPixel"); if (ref_pix==0 || isEmpty(ref_pix)) { const std::vector<int> peakRange = getProperty("SignalPeakPixelRange"); if (peakRange.size()<2) { g_log.error() << "SignalPeakPixelRange parameter should be a vector of two values" << std::endl; throw std::invalid_argument("SignalPeakPixelRange parameter should be a vector of two values"); } ref_pix = (peakRange[0] + peakRange[1])/2.0; } double theta = (dangle-dangle0)*M_PI/180.0/2.0 + ((direct_beam_pix-ref_pix)*PIXEL_SIZE)/ (2.0*det_distance); return theta*180.0/M_PI; }
IEventWorkspace_sptr RefReduction::loadData(const std::string dataRun, const std::string polarization) { const std::string instrument = getProperty("Instrument"); // Check whether dataRun refers to an existing workspace // Create a good name for the raw workspace std::string ws_name = "__ref_"+dataRun+"-"+polarization+"_raw"; IEventWorkspace_sptr rawWS; if (AnalysisDataService::Instance().doesExist(dataRun)) { rawWS = AnalysisDataService::Instance().retrieveWS<EventWorkspace>(dataRun); g_log.notice() << "Found workspace: " << dataRun << std::endl; m_output_message += " |Input data run is a workspace: " + dataRun + "\n"; } else if (AnalysisDataService::Instance().doesExist(ws_name)) { rawWS = AnalysisDataService::Instance().retrieveWS<EventWorkspace>(ws_name); g_log.notice() << "Using existing workspace: " << ws_name << std::endl; m_output_message += " |Found workspace from previous reduction: " + ws_name + "\n"; } else { // If we can't find a workspace, find a file to load std::string path = FileFinder::Instance().getFullPath(dataRun); if (path.size()==0 || !Poco::File(path).exists()) { try { std::vector<std::string> paths = FileFinder::Instance().findRuns(instrument+dataRun); path = paths[0]; } catch(Exception::NotFoundError&) { /* Pass. We report the missing file later. */ } } if (path.size()==0 || !Poco::File(path).exists()) { try { std::vector<std::string> paths = FileFinder::Instance().findRuns(dataRun); path = paths[0]; } catch(Exception::NotFoundError&) { /* Pass. We report the missing file later. */ } } if (Poco::File(path).exists()) { g_log.notice() << "Found: " << path << std::endl; m_output_message += " |Loading from " + path + "\n"; IAlgorithm_sptr loadAlg = createChildAlgorithm("LoadEventNexus", 0, 0.2); loadAlg->setProperty("Filename", path); if (polarization.compare(PolStateNone)!=0) loadAlg->setProperty("NXentryName", polarization); loadAlg->executeAsChildAlg(); rawWS = loadAlg->getProperty("OutputWorkspace"); if (rawWS->getNumberEvents()==0) { g_log.notice() << "No data in " << polarization << std::endl; m_output_message += " |No data for " + polarization + "\n"; return rawWS; } // Move the detector to the right position if (instrument.compare("REF_M")==0) { double det_distance = rawWS->getInstrument()->getDetector(0)->getPos().Z(); Mantid::Kernel::Property* prop = rawWS->run().getProperty("SampleDetDis"); Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop); double sdd = dp->getStatistics().mean/1000.0; IAlgorithm_sptr mvAlg = createChildAlgorithm("MoveInstrumentComponent", 0.2, 0.25); mvAlg->setProperty<MatrixWorkspace_sptr>("Workspace", rawWS); mvAlg->setProperty("ComponentName", "detector1"); mvAlg->setProperty("Z", sdd-det_distance); mvAlg->setProperty("RelativePosition", true); mvAlg->executeAsChildAlg(); g_log.notice() << "Ensuring correct Z position: Correction = " << Poco::NumberFormatter::format(sdd-det_distance) << " m" << std::endl; } AnalysisDataService::Instance().addOrReplace(ws_name, rawWS); } else { g_log.error() << "Could not find a data file for " << dataRun << std::endl; throw std::invalid_argument("Could not find a data file for the given input"); } } // Crop TOF as needed and set binning double tofMin = getProperty("TOFMin"); double tofMax = getProperty("TOFMax"); if (isEmpty(tofMin) || isEmpty(tofMax)) { const MantidVec& x = rawWS->readX(0); if (isEmpty(tofMin)) tofMin = *std::min_element(x.begin(), x.end()); if (isEmpty(tofMax)) tofMax = *std::max_element(x.begin(), x.end()); } int nBins = getProperty("NBins"); double tofStep = getProperty("TOFStep"); if (!isEmpty(nBins)) tofStep = (tofMax-tofMin)/nBins; else nBins = (int)floor( (tofMax-tofMin)/tofStep ); std::vector<double> params; params.push_back(tofMin); params.push_back(tofStep); params.push_back(tofMax); IAlgorithm_sptr rebinAlg = createChildAlgorithm("Rebin", 0.25, 0.3); rebinAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", rawWS); rebinAlg->setProperty("Params", params); rebinAlg->setProperty("PreserveEvents", true); rebinAlg->executeAsChildAlg(); MatrixWorkspace_sptr outputWS = rebinAlg->getProperty("OutputWorkspace"); m_output_message += " |TOF binning: " + Poco::NumberFormatter::format(tofMin) + " to " + Poco::NumberFormatter::format(tofMax) + " in steps of " + Poco::NumberFormatter::format(tofStep) + " microsecs\n"; // Normalise by current IAlgorithm_sptr normAlg = createChildAlgorithm("NormaliseByCurrent", 0.3, 0.35); normAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", outputWS); //normAlg->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", outputWS); normAlg->executeAsChildAlg(); outputWS = normAlg->getProperty("OutputWorkspace"); // Convert to wavelength IAlgorithm_sptr convAlg = createChildAlgorithm("ConvertUnits", 0.35, 0.4); convAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", outputWS); convAlg->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", outputWS); convAlg->setProperty("Target", "Wavelength"); convAlg->executeAsChildAlg(); // Rebin in wavelength const MantidVec& x = outputWS->readX(0); double wlMin = *std::min_element(x.begin(), x.end()); double wlMax = *std::max_element(x.begin(), x.end()); std::vector<double> wl_params; wl_params.push_back(wlMin); wl_params.push_back((wlMax-wlMin)/nBins); wl_params.push_back(wlMax); IAlgorithm_sptr rebinAlg2 = createChildAlgorithm("Rebin", 0.25, 0.3); rebinAlg2->setProperty<MatrixWorkspace_sptr>("InputWorkspace", outputWS); rebinAlg2->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", outputWS); rebinAlg2->setProperty("Params", wl_params); rebinAlg2->setProperty("PreserveEvents", true); rebinAlg2->executeAsChildAlg(); IEventWorkspace_sptr outputEvtWS = boost::dynamic_pointer_cast<IEventWorkspace>(outputWS); return outputEvtWS; }
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 EQSANSLoad::exec() { // Read in default TOF cuts 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"); TableWorkspace_sptr reductionTable = getProperty("ReductionTableWorkspace"); ReductionTableHandler reductionHandler(reductionTable); if (!reductionTable) { const std::string reductionTableName = getPropertyValue("ReductionTableWorkspace"); if (reductionTableName.size()>0) setProperty("ReductionTableWorkspace", reductionHandler.getTable()); } if (reductionHandler.findStringEntry("LoadAlgorithm").size()==0) reductionHandler.addEntry("LoadAlgorithm", toString()); const std::string fileName = getPropertyValue("Filename"); // Output log m_output_message = ""; IAlgorithm_sptr loadAlg = createSubAlgorithm("LoadEventNexus", 0, 0.2); loadAlg->setProperty("Filename", fileName); loadAlg->executeAsSubAlg(); IEventWorkspace_sptr dataWS_tmp = loadAlg->getProperty("OutputWorkspace"); dataWS = boost::dynamic_pointer_cast<MatrixWorkspace>(dataWS_tmp); // 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 { Mantid::Kernel::Property* prop = dataWS->run().getProperty("detectorZ"); Mantid::Kernel::TimeSeriesProperty<double>* dp = dynamic_cast<Mantid::Kernel::TimeSeriesProperty<double>* >(prop); 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 = createSubAlgorithm("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->executeAsSubAlg(); g_log.information() << "Moving detector to " << sdd/1000.0 << std::endl; 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")) { Mantid::Kernel::Property* prop = dataWS->run().getProperty("run_number"); Mantid::Kernel::PropertyWithValue<std::string>* dp = dynamic_cast<Mantid::Kernel::PropertyWithValue<std::string>* >(prop); const std::string run_str = *dp; 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") << std::endl; 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) { readConfigFile(config_file); } else if (use_config) { use_config = false; g_log.error() << "Cound not find config file for workspace " << getPropertyValue("OutputWorkspace") << std::endl; 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" << std::endl; g_log.information() << "Moving moderator to " << m_moderator_position << std::endl; m_output_message += " Moderator position: " + Poco::NumberFormatter::format(m_moderator_position, 3) + " m\n"; mvAlg = createSubAlgorithm("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->executeAsSubAlg(); } // Get source aperture radius getSourceSlitSize(); // Move the beam center to its proper position moveToBeamCenter(); // Modify TOF bool correct_for_flight_path = getProperty("CorrectForFlightPath"); 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_tmp); IAlgorithm_sptr tofAlg = createSubAlgorithm("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->executeAsSubAlg(); const double wl_min = tofAlg->getProperty("WavelengthMin"); const double wl_max = tofAlg->getProperty("WavelengthMax"); 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); double wl_combined_max = wl_max; m_output_message += " Wavelength range: " + Poco::NumberFormatter::format(wl_min, 1) + " - " + Poco::NumberFormatter::format(wl_max, 1); 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, 1) + " - " + Poco::NumberFormatter::format(wl_max2, 1) + " 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"; IAlgorithm_sptr scAlg = createSubAlgorithm("ScaleX", 0.7, 0.71); scAlg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", dataWS); scAlg->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", dataWS); scAlg->setProperty("Factor", conversion_factor); scAlg->executeAsSubAlg(); dataWS->getAxis(0)->setUnit("Wavelength"); // Rebin so all the wavelength bins are aligned const bool preserveEvents = getProperty("PreserveEvents"); std::string params = Poco::NumberFormatter::format(wl_min, 2) + ",0.1," + Poco::NumberFormatter::format(wl_combined_max, 2); IAlgorithm_sptr rebinAlg = createSubAlgorithm("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->executeAsSubAlg(); if (!preserveEvents) dataWS = rebinAlg->getProperty("OutputWorkspace"); dataWS->mutableRun().addProperty("event_ws", getPropertyValue("OutputWorkspace"), true); setProperty<MatrixWorkspace_sptr>("OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(dataWS)); setPropertyValue("OutputMessage", m_output_message); }