//---------------------------------------------------------------------- // Includes //---------------------------------------------------------------------- #include "MantidWorkflowAlgorithms/AlignAndFocusPowder.h" #include "MantidAPI/FileProperty.h" #include "MantidAPI/MatrixWorkspace.h" #include "MantidAPI/PropertyManagerDataService.h" #include "MantidDataObjects/GroupingWorkspace.h" #include "MantidDataObjects/MaskWorkspace.h" #include "MantidDataObjects/OffsetsWorkspace.h" #include "MantidDataObjects/TableWorkspace.h" #include "MantidDataObjects/Workspace2D.h" #include "MantidKernel/ArrayProperty.h" #include "MantidKernel/EnabledWhenProperty.h" #include "MantidKernel/PropertyManager.h" #include "MantidKernel/RebinParamsValidator.h" #include "MantidKernel/System.h" #include "MantidKernel/ConfigService.h" #include "MantidKernel/InstrumentInfo.h" #include "MantidAPI/FileFinder.h" using Mantid::Geometry::Instrument_const_sptr; using namespace Mantid::Kernel; using namespace Mantid::API; using namespace Mantid::DataObjects; namespace Mantid { namespace WorkflowAlgorithms { using namespace Kernel; using API::WorkspaceProperty; using API::MatrixWorkspace_sptr; using API::MatrixWorkspace; using API::FileProperty; // Register the class into the algorithm factory DECLARE_ALGORITHM(AlignAndFocusPowder) AlignAndFocusPowder::AlignAndFocusPowder() : API::DataProcessorAlgorithm(), m_l1(0.0), m_resampleX(0), dspace(false), xmin(0.0), xmax(0.0), LRef(0.0), DIFCref(0.0), minwl(0.0), maxwl(0.), tmin(0.0), tmax(0.0), m_preserveEvents(false), m_processLowResTOF(false), m_lowResSpecOffset(0), m_progress(NULL) {} AlignAndFocusPowder::~AlignAndFocusPowder() { if (m_progress) delete m_progress; } const std::string AlignAndFocusPowder::name() const { return "AlignAndFocusPowder"; } int AlignAndFocusPowder::version() const { return 1; } const std::string AlignAndFocusPowder::category() const { return "Workflow\\Diffraction"; } //---------------------------------------------------------------------------------------------- /** Initialisation method. Declares properties to be used in algorithm. */ void AlignAndFocusPowder::init() { declareProperty(new WorkspaceProperty<MatrixWorkspace>("InputWorkspace", "", Direction::Input), "The input workspace"); declareProperty(new WorkspaceProperty<MatrixWorkspace>("OutputWorkspace", "", Direction::Output), "The result of diffraction focussing of InputWorkspace"); // declareProperty( // new WorkspaceProperty<MatrixWorkspace>("LowResTOFWorkspace", "", // Direction::Output, PropertyMode::Optional), // "The name of the workspace containing the filtered low resolution TOF // data."); std::vector<std::string> exts; exts.push_back(".h5"); exts.push_back(".hd5"); exts.push_back(".hdf"); exts.push_back(".cal"); declareProperty( new FileProperty("CalFileName", "", FileProperty::OptionalLoad, exts), "The name of the CalFile with offset, masking, and grouping data"); declareProperty( new WorkspaceProperty<GroupingWorkspace>( "GroupingWorkspace", "", Direction::Input, PropertyMode::Optional), "Optional: A GroupingWorkspace giving the grouping info."); declareProperty( new WorkspaceProperty<ITableWorkspace>( "CalibrationWorkspace", "", Direction::Input, PropertyMode::Optional), "Optional: A Workspace containing the calibration information. Either " "this or CalibrationFile needs to be specified."); declareProperty( new WorkspaceProperty<OffsetsWorkspace>( "OffsetsWorkspace", "", Direction::Input, PropertyMode::Optional), "Optional: An OffsetsWorkspace giving the detector calibration values."); declareProperty(new WorkspaceProperty<MaskWorkspace>("MaskWorkspace", "", Direction::Input, PropertyMode::Optional), "Optional: A workspace giving which detectors are masked."); declareProperty(new WorkspaceProperty<TableWorkspace>("MaskBinTable", "", Direction::Input, PropertyMode::Optional), "Optional: A workspace giving pixels and bins to mask."); declareProperty( new ArrayProperty<double>( "Params" /*, boost::make_shared<RebinParamsValidator>()*/), "A comma separated list of first bin boundary, width, last bin boundary. " "Optionally\n" "this can be followed by a comma and more widths and last boundary " "pairs.\n" "Negative width values indicate logarithmic binning."); declareProperty("ResampleX", 0, "Number of bins in x-axis. Non-zero value " "overrides \"Params\" property. Negative " "value means logorithmic binning."); setPropertySettings("Params", new EnabledWhenProperty("ResampleX", IS_DEFAULT)); declareProperty("Dspacing", true, "Bin in Dspace. (True is Dspace; False is TOF)"); declareProperty(new ArrayProperty<double>("DMin"), "Minimum for Dspace axis. (Default 0.) "); mapPropertyName("DMin", "d_min"); declareProperty(new ArrayProperty<double>("DMax"), "Maximum for Dspace axis. (Default 0.) "); mapPropertyName("DMax", "d_max"); declareProperty("TMin", EMPTY_DBL(), "Minimum for TOF axis. Defaults to 0. "); mapPropertyName("TMin", "tof_min"); declareProperty("TMax", EMPTY_DBL(), "Maximum for TOF or dspace axis. Defaults to 0. "); mapPropertyName("TMax", "tof_max"); declareProperty("PreserveEvents", true, "If the InputWorkspace is an " "EventWorkspace, this will preserve " "the full event list (warning: this " "will use much more memory!)."); declareProperty("RemovePromptPulseWidth", 0., "Width of events (in " "microseconds) near the prompt " "pulse to remove. 0 disables"); declareProperty("CompressTolerance", 0.01, "Compress events (in " "microseconds) within this " "tolerance. (Default 0.01) "); declareProperty("UnwrapRef", 0., "Reference total flight path for frame " "unwrapping. Zero skips the correction"); declareProperty( "LowResRef", 0., "Reference DIFC for resolution removal. Zero skips the correction"); declareProperty( "CropWavelengthMin", 0., "Crop the data at this minimum wavelength. Overrides LowResRef."); declareProperty("CropWavelengthMax", EMPTY_DBL(), "Crop the data at this maximum wavelength. Forces use of " "CropWavelengthMin."); declareProperty("PrimaryFlightPath", -1.0, "If positive, focus positions are changed. (Default -1) "); declareProperty(new ArrayProperty<int32_t>("SpectrumIDs"), "Optional: Spectrum IDs (note that it is not detector ID or " "workspace indices)."); declareProperty(new ArrayProperty<double>("L2"), "Optional: Secondary flight (L2) paths for each detector"); declareProperty(new ArrayProperty<double>("Polar"), "Optional: Polar angles (two thetas) for detectors"); declareProperty(new ArrayProperty<double>("Azimuthal"), "Azimuthal angles (out-of-plain) for detectors"); declareProperty("LowResSpectrumOffset", -1, "Offset on spectrum ID of low resolution spectra from high " "resolution one. " "If negative, then all the low resolution TOF will not be " "processed. Otherwise, low resolution TOF " "will be stored in an additional set of spectra. " "If offset is equal to 0, then the low resolution will have " "same spectrum IDs as the normal ones. " "Otherwise, the low resolution spectra will have spectrum " "IDs offset from normal ones. "); declareProperty("ReductionProperties", "__powdereduction", Direction::Input); } template <typename NumT> void splitVectors(const std::vector<NumT> &orig, const size_t numVal, const std::string &label, std::vector<NumT> &left, std::vector<NumT> &right) { // clear the outputs left.clear(); right.clear(); // check that there is work to do if (orig.empty()) return; // do the spliting if (orig.size() == numVal) { left.assign(orig.begin(), orig.end()); right.assign(orig.begin(), orig.end()); } else if (orig.size() == 2 * numVal) { left.assign(orig.begin(), orig.begin() + numVal); right.assign(orig.begin() + numVal, orig.begin()); } else { std::stringstream msg; msg << "Input number of " << label << " ids is not equal to " << "the number of histograms or empty (" << orig.size() << " != 0 or " << numVal << " or " << (2 * numVal) << ")"; throw std::runtime_error(msg.str()); } } //---------------------------------------------------------------------------------------------- /** * Function to get a vector property either from a PropertyManager or the * algorithm * properties. If both PM and algorithm properties are specified, the algorithm * one wins. * The return value is the first element in the vector if it is not empty. * @param name : The algorithm property to retrieve. * @param avec : The vector to hold the property value. * @return : The default value of the requested property. */ double AlignAndFocusPowder::getVecPropertyFromPmOrSelf(const std::string &name, std::vector<double> &avec) { avec = getProperty(name); if (!avec.empty()) { return avec[0]; } // No overrides provided. return 0.0; } //---------------------------------------------------------------------------------------------- /** Executes the algorithm * @throw Exception::FileError If the grouping file cannot be opened or read * successfully * @throw runtime_error If unable to run one of the Child Algorithms * successfully */ void AlignAndFocusPowder::exec() { // retrieve the properties m_inputW = getProperty("InputWorkspace"); m_inputEW = boost::dynamic_pointer_cast<EventWorkspace>(m_inputW); m_instName = m_inputW->getInstrument()->getName(); m_instName = Kernel::ConfigService::Instance().getInstrument(m_instName).shortName(); std::string calFileName = getPropertyValue("CalFileName"); m_calibrationWS = getProperty("CalibrationWorkspace"); m_maskWS = getProperty("MaskWorkspace"); m_groupWS = getProperty("GroupingWorkspace"); DataObjects::TableWorkspace_sptr maskBinTableWS = getProperty("MaskBinTable"); m_l1 = getProperty("PrimaryFlightPath"); specids = getProperty("SpectrumIDs"); l2s = getProperty("L2"); tths = getProperty("Polar"); phis = getProperty("Azimuthal"); m_params = getProperty("Params"); dspace = getProperty("DSpacing"); auto dmin = getVecPropertyFromPmOrSelf("DMin", m_dmins); auto dmax = getVecPropertyFromPmOrSelf("DMax", m_dmaxs); LRef = getProperty("UnwrapRef"); DIFCref = getProperty("LowResRef"); minwl = getProperty("CropWavelengthMin"); maxwl = getProperty("CropWavelengthMax"); if (maxwl == 0.) maxwl = EMPTY_DBL(); // python can only specify 0 for unused tmin = getProperty("TMin"); tmax = getProperty("TMax"); m_preserveEvents = getProperty("PreserveEvents"); m_resampleX = getProperty("ResampleX"); // determine some bits about d-space and binning if (m_resampleX != 0) { m_params.clear(); // ignore the normal rebin parameters } else if (m_params.size() == 1) { if (dmax > 0.) dspace = true; else dspace = false; } if (dspace) { if (m_params.size() == 1 && dmax > 0) { double step = m_params[0]; m_params.clear(); if (step > 0 || dmin > 0) { m_params.push_back(dmin); m_params.push_back(step); m_params.push_back(dmax); g_log.information() << "d-Spacing Binning: " << m_params[0] << " " << m_params[1] << " " << m_params[2] << "\n"; } } } else { if (m_params.size() == 1 && tmax > 0) { double step = m_params[0]; if (step > 0 || tmin > 0) { m_params[0] = tmin; m_params.push_back(step); m_params.push_back(tmax); g_log.information() << "TOF Binning: " << m_params[0] << " " << m_params[1] << " " << m_params[2] << "\n"; } } } xmin = 0; xmax = 0; if (tmin > 0.) { xmin = tmin; } if (tmax > 0.) { xmax = tmax; } if (!dspace && m_params.size() == 3) { xmin = m_params[0]; xmax = m_params[2]; } // Low resolution int lowresoffset = getProperty("LowResSpectrumOffset"); if (lowresoffset < 0) { m_processLowResTOF = false; } else { m_processLowResTOF = true; m_lowResSpecOffset = static_cast<size_t>(lowresoffset); } loadCalFile(calFileName); // Now setup the output workspace m_outputW = getProperty("OutputWorkspace"); if (m_outputW == m_inputW) { if (m_inputEW) { m_outputEW = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); } } else { if (m_inputEW) { // Make a brand new EventWorkspace m_outputEW = boost::dynamic_pointer_cast<EventWorkspace>( WorkspaceFactory::Instance().create( "EventWorkspace", m_inputEW->getNumberHistograms(), 2, 1)); // Copy geometry over. WorkspaceFactory::Instance().initializeFromParent(m_inputEW, m_outputEW, false); // You need to copy over the data as well. m_outputEW->copyDataFrom((*m_inputEW)); // Cast to the matrixOutputWS and save it m_outputW = boost::dynamic_pointer_cast<MatrixWorkspace>(m_outputEW); // m_outputW->setName(getProperty("OutputWorkspace")); } else { // Not-an-event workspace m_outputW = WorkspaceFactory::Instance().create(m_inputW); // m_outputW->setName(getProperty("OutputWorkspace")); } } if (m_processLowResTOF) { if (!m_inputEW) { throw std::runtime_error( "Input workspace is not EventWorkspace. It is not supported now."); } else { // Make a brand new EventWorkspace m_lowResEW = boost::dynamic_pointer_cast<EventWorkspace>( WorkspaceFactory::Instance().create( "EventWorkspace", m_inputEW->getNumberHistograms(), 2, 1)); // Cast to the matrixOutputWS and save it m_lowResW = boost::dynamic_pointer_cast<MatrixWorkspace>(m_lowResEW); // m_lowResW->setName(lowreswsname); } } // set up a progress bar with the "correct" number of steps m_progress = new Progress(this, 0., 1., 22); if (m_inputEW) { double tolerance = getProperty("CompressTolerance"); if (tolerance > 0.) { g_log.information() << "running CompressEvents(Tolerance=" << tolerance << ")\n"; API::IAlgorithm_sptr compressAlg = createChildAlgorithm("CompressEvents"); compressAlg->setProperty("InputWorkspace", m_outputEW); compressAlg->setProperty("OutputWorkspace", m_outputEW); compressAlg->setProperty("OutputWorkspace", m_outputEW); compressAlg->setProperty("Tolerance", tolerance); compressAlg->executeAsChildAlg(); m_outputEW = compressAlg->getProperty("OutputWorkspace"); m_outputW = boost::dynamic_pointer_cast<MatrixWorkspace>(m_outputEW); } else { g_log.information() << "Not compressing event list\n"; doSortEvents(m_outputW); // still sort to help some thing out } } m_progress->report(); if (xmin > 0. || xmax > 0.) { bool doCorrection(true); if (m_outputEW) { // extra check for event workspaces doCorrection = (m_outputEW->getNumberEvents() > 0); } if (doCorrection) { double tempmin; double tempmax; m_outputW->getXMinMax(tempmin, tempmax); g_log.information() << "running CropWorkspace(TOFmin=" << xmin << ", TOFmax=" << xmax << ")\n"; API::IAlgorithm_sptr cropAlg = createChildAlgorithm("CropWorkspace"); cropAlg->setProperty("InputWorkspace", m_outputW); cropAlg->setProperty("OutputWorkspace", m_outputW); if ((xmin > 0.) && (xmin > tempmin)) cropAlg->setProperty("Xmin", xmin); if ((xmax > 0.) && (xmax < tempmax)) cropAlg->setProperty("Xmax", xmax); cropAlg->executeAsChildAlg(); m_outputW = cropAlg->getProperty("OutputWorkspace"); m_outputEW = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); } } m_progress->report(); // filter the input events if appropriate double removePromptPulseWidth = getProperty("RemovePromptPulseWidth"); if (removePromptPulseWidth > 0.) { g_log.information() << "running RemovePromptPulse(Width=" << removePromptPulseWidth << ")\n"; API::IAlgorithm_sptr filterPAlg = createChildAlgorithm("RemovePromptPulse"); filterPAlg->setProperty("InputWorkspace", m_outputW); filterPAlg->setProperty("OutputWorkspace", m_outputW); filterPAlg->setProperty("Width", removePromptPulseWidth); filterPAlg->executeAsChildAlg(); m_outputW = filterPAlg->getProperty("OutputWorkspace"); m_outputEW = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); } m_progress->report(); if (maskBinTableWS) { g_log.information() << "running MaskBinsFromTable\n"; API::IAlgorithm_sptr alg = createChildAlgorithm("MaskBinsFromTable"); alg->setProperty("InputWorkspace", m_outputW); alg->setProperty("OutputWorkspace", m_outputW); alg->setProperty("MaskingInformation", maskBinTableWS); alg->executeAsChildAlg(); m_outputW = alg->getProperty("OutputWorkspace"); m_outputEW = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); } m_progress->report(); if (m_maskWS) { g_log.information() << "running MaskDetectors\n"; API::IAlgorithm_sptr maskAlg = createChildAlgorithm("MaskDetectors"); maskAlg->setProperty("Workspace", m_outputW); maskAlg->setProperty("MaskedWorkspace", m_maskWS); maskAlg->executeAsChildAlg(); Workspace_sptr tmpW = maskAlg->getProperty("Workspace"); m_outputW = boost::dynamic_pointer_cast<MatrixWorkspace>(tmpW); m_outputEW = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); } m_progress->report(); if (!dspace) m_outputW = rebin(m_outputW); m_progress->report(); if (m_calibrationWS) { g_log.information() << "running AlignDetectors\n"; API::IAlgorithm_sptr alignAlg = createChildAlgorithm("AlignDetectors"); alignAlg->setProperty("InputWorkspace", m_outputW); alignAlg->setProperty("OutputWorkspace", m_outputW); alignAlg->setProperty("CalibrationWorkspace", m_calibrationWS); alignAlg->executeAsChildAlg(); m_outputW = alignAlg->getProperty("OutputWorkspace"); } else { m_outputW = convertUnits(m_outputW, "dSpacing"); } m_progress->report(); if (LRef > 0. || minwl > 0. || DIFCref > 0. || (!isEmpty(maxwl))) { m_outputW = convertUnits(m_outputW, "TOF"); } m_progress->report(); // Beyond this point, low resolution TOF workspace is considered. if (LRef > 0.) { g_log.information() << "running UnwrapSNS(LRef=" << LRef << ",Tmin=" << tmin << ",Tmax=" << tmax << ")\n"; API::IAlgorithm_sptr removeAlg = createChildAlgorithm("UnwrapSNS"); removeAlg->setProperty("InputWorkspace", m_outputW); removeAlg->setProperty("OutputWorkspace", m_outputW); removeAlg->setProperty("LRef", LRef); if (tmin > 0.) removeAlg->setProperty("Tmin", tmin); if (tmax > tmin) removeAlg->setProperty("Tmax", tmax); removeAlg->executeAsChildAlg(); m_outputW = removeAlg->getProperty("OutputWorkspace"); } m_progress->report(); if (minwl > 0. || (!isEmpty(maxwl))) { // just crop the worksapce // turn off the low res stuff m_processLowResTOF = false; EventWorkspace_sptr ews = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); if (ews) g_log.information() << "Number of events = " << ews->getNumberEvents() << ". "; g_log.information("\n"); m_outputW = convertUnits(m_outputW, "Wavelength"); g_log.information() << "running CropWorkspace(WavelengthMin=" << minwl; if (!isEmpty(maxwl)) g_log.information() << ", WavelengthMax=" << maxwl; g_log.information() << ")\n"; API::IAlgorithm_sptr removeAlg = createChildAlgorithm("CropWorkspace"); removeAlg->setProperty("InputWorkspace", m_outputW); removeAlg->setProperty("OutputWorkspace", m_outputW); removeAlg->setProperty("XMin", minwl); removeAlg->setProperty("XMax", maxwl); removeAlg->executeAsChildAlg(); m_outputW = removeAlg->getProperty("OutputWorkspace"); if (ews) g_log.information() << "Number of events = " << ews->getNumberEvents() << ". "; } else if (DIFCref > 0.) { g_log.information() << "running RemoveLowResTof(RefDIFC=" << DIFCref << ",K=3.22)\n"; EventWorkspace_sptr ews = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); if (ews) g_log.information() << "Number of events = " << ews->getNumberEvents() << ". "; g_log.information("\n"); API::IAlgorithm_sptr removeAlg = createChildAlgorithm("RemoveLowResTOF"); removeAlg->setProperty("InputWorkspace", m_outputW); removeAlg->setProperty("OutputWorkspace", m_outputW); removeAlg->setProperty("ReferenceDIFC", DIFCref); removeAlg->setProperty("K", 3.22); if (tmin > 0.) removeAlg->setProperty("Tmin", tmin); if (m_processLowResTOF) removeAlg->setProperty("LowResTOFWorkspace", m_lowResW); removeAlg->executeAsChildAlg(); m_outputW = removeAlg->getProperty("OutputWorkspace"); if (m_processLowResTOF) m_lowResW = removeAlg->getProperty("LowResTOFWorkspace"); } m_progress->report(); EventWorkspace_sptr ews = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); if (ews) { size_t numhighevents = ews->getNumberEvents(); if (m_processLowResTOF) { EventWorkspace_sptr lowes = boost::dynamic_pointer_cast<EventWorkspace>(m_lowResW); size_t numlowevents = lowes->getNumberEvents(); g_log.information() << "Number of high TOF events = " << numhighevents << "; " << "Number of low TOF events = " << numlowevents << ".\n"; } } m_progress->report(); // Convert units if (LRef > 0. || minwl > 0. || DIFCref > 0. || (!isEmpty(maxwl))) { m_outputW = convertUnits(m_outputW, "dSpacing"); if (m_processLowResTOF) m_lowResW = convertUnits(m_lowResW, "dSpacing"); } m_progress->report(); if (dspace) { m_outputW = rebin(m_outputW); if (m_processLowResTOF) m_lowResW = rebin(m_lowResW); } m_progress->report(); doSortEvents(m_outputW); if (m_processLowResTOF) doSortEvents(m_lowResW); m_progress->report(); // Diffraction focus m_outputW = diffractionFocus(m_outputW); if (m_processLowResTOF) m_lowResW = diffractionFocus(m_lowResW); m_progress->report(); doSortEvents(m_outputW); if (m_processLowResTOF) doSortEvents(m_lowResW); m_progress->report(); // this next call should probably be in for rebin as well // but it changes the system tests if (dspace && m_resampleX != 0) { m_outputW = rebin(m_outputW); if (m_processLowResTOF) m_lowResW = rebin(m_lowResW); } m_progress->report(); // edit the instrument geometry if (m_groupWS && (m_l1 > 0 || !tths.empty() || !l2s.empty() || !phis.empty())) { size_t numreg = m_outputW->getNumberHistograms(); // set up the vectors for doing everything std::vector<int32_t> specidsReg; std::vector<int32_t> specidsLow; splitVectors(specids, numreg, "specids", specidsReg, specidsLow); std::vector<double> tthsReg; std::vector<double> tthsLow; splitVectors(tths, numreg, "two-theta", tthsReg, tthsLow); std::vector<double> l2sReg; std::vector<double> l2sLow; splitVectors(l2s, numreg, "L2", l2sReg, l2sLow); std::vector<double> phisReg; std::vector<double> phisLow; splitVectors(phis, numreg, "phi", phisReg, phisLow); // Edit instrument m_outputW = editInstrument(m_outputW, tthsReg, specidsReg, l2sReg, phisReg); if (m_processLowResTOF) { m_lowResW = editInstrument(m_lowResW, tthsLow, specidsLow, l2sLow, phisLow); } } m_progress->report(); // Conjoin 2 workspaces if there is low resolution if (m_processLowResTOF) { m_outputW = conjoinWorkspaces(m_outputW, m_lowResW, m_lowResSpecOffset); } m_progress->report(); // Convert units to TOF m_outputW = convertUnits(m_outputW, "TOF"); m_progress->report(); // compress again if appropriate double tolerance = getProperty("CompressTolerance"); m_outputEW = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); if ((m_outputEW) && (tolerance > 0.)) { g_log.information() << "running CompressEvents(Tolerance=" << tolerance << ")\n"; API::IAlgorithm_sptr compressAlg = createChildAlgorithm("CompressEvents"); compressAlg->setProperty("InputWorkspace", m_outputEW); compressAlg->setProperty("OutputWorkspace", m_outputEW); compressAlg->setProperty("OutputWorkspace", m_outputEW); compressAlg->setProperty("Tolerance", tolerance); compressAlg->executeAsChildAlg(); m_outputEW = compressAlg->getProperty("OutputWorkspace"); m_outputW = boost::dynamic_pointer_cast<MatrixWorkspace>(m_outputEW); } m_progress->report(); if ((!m_params.empty()) && (m_params.size() != 1)) { m_params.erase(m_params.begin()); m_params.pop_back(); } if (!m_dmins.empty()) m_dmins.clear(); if (!m_dmaxs.empty()) m_dmaxs.clear(); m_outputW = rebin(m_outputW); m_progress->report(); // return the output workspace setProperty("OutputWorkspace", m_outputW); return; } //---------------------------------------------------------------------------------------------- /** Call edit instrument geometry */ API::MatrixWorkspace_sptr AlignAndFocusPowder::editInstrument( API::MatrixWorkspace_sptr ws, std::vector<double> polars, std::vector<specid_t> specids, std::vector<double> l2s, std::vector<double> phis) { g_log.information() << "running EditInstrumentGeometry\n"; API::IAlgorithm_sptr editAlg = createChildAlgorithm("EditInstrumentGeometry"); editAlg->setProperty("Workspace", ws); if (m_l1 > 0.) editAlg->setProperty("PrimaryFlightPath", m_l1); if (!polars.empty()) editAlg->setProperty("Polar", polars); if (!specids.empty()) editAlg->setProperty("SpectrumIDs", specids); if (!l2s.empty()) editAlg->setProperty("L2", l2s); if (!phis.empty()) editAlg->setProperty("Azimuthal", phis); editAlg->executeAsChildAlg(); ws = editAlg->getProperty("Workspace"); return ws; } //---------------------------------------------------------------------------------------------- /** Call diffraction focus to a matrix workspace. */ API::MatrixWorkspace_sptr AlignAndFocusPowder::diffractionFocus(API::MatrixWorkspace_sptr ws) { if (!m_groupWS) { g_log.information() << "not focussing data\n"; return ws; } g_log.information() << "running DiffractionFocussing. \n"; API::IAlgorithm_sptr focusAlg = createChildAlgorithm("DiffractionFocussing"); focusAlg->setProperty("InputWorkspace", ws); focusAlg->setProperty("OutputWorkspace", ws); focusAlg->setProperty("GroupingWorkspace", m_groupWS); focusAlg->setProperty("PreserveEvents", m_preserveEvents); focusAlg->executeAsChildAlg(); ws = focusAlg->getProperty("OutputWorkspace"); return ws; } //---------------------------------------------------------------------------------------------- /** Convert units */ API::MatrixWorkspace_sptr AlignAndFocusPowder::convertUnits(API::MatrixWorkspace_sptr matrixws, std::string target) { g_log.information() << "running ConvertUnits(Target=" << target << ")\n"; API::IAlgorithm_sptr convert2Alg = createChildAlgorithm("ConvertUnits"); convert2Alg->setProperty("InputWorkspace", matrixws); convert2Alg->setProperty("OutputWorkspace", matrixws); convert2Alg->setProperty("Target", target); convert2Alg->executeAsChildAlg(); matrixws = convert2Alg->getProperty("OutputWorkspace"); return matrixws; } //---------------------------------------------------------------------------------------------- /** Rebin */ API::MatrixWorkspace_sptr AlignAndFocusPowder::rebin(API::MatrixWorkspace_sptr matrixws) { if (m_resampleX != 0) { // ResampleX g_log.information() << "running ResampleX(NumberBins=" << abs(m_resampleX) << ", LogBinning=" << (m_resampleX < 0) << ", dMin(" << m_dmins.size() << "), dmax(" << m_dmaxs.size() << "))\n"; API::IAlgorithm_sptr alg = createChildAlgorithm("ResampleX"); alg->setProperty("InputWorkspace", matrixws); alg->setProperty("OutputWorkspace", matrixws); if ((!m_dmins.empty()) && (!m_dmaxs.empty())) { size_t numHist = m_outputW->getNumberHistograms(); if ((numHist == m_dmins.size()) && (numHist == m_dmaxs.size())) { alg->setProperty("XMin", m_dmins); alg->setProperty("XMax", m_dmaxs); } else { g_log.information() << "Number of dmin and dmax values don't match the " << "number of workspace indices. Ignoring the parameters.\n"; } } alg->setProperty("NumberBins", abs(m_resampleX)); alg->setProperty("LogBinning", (m_resampleX < 0)); alg->executeAsChildAlg(); matrixws = alg->getProperty("OutputWorkspace"); return matrixws; } else { g_log.information() << "running Rebin( "; for (auto param = m_params.begin(); param != m_params.end(); ++param) g_log.information() << (*param) << " "; g_log.information() << ")\n"; API::IAlgorithm_sptr rebin3Alg = createChildAlgorithm("Rebin"); rebin3Alg->setProperty("InputWorkspace", matrixws); rebin3Alg->setProperty("OutputWorkspace", matrixws); rebin3Alg->setProperty("Params", m_params); rebin3Alg->executeAsChildAlg(); matrixws = rebin3Alg->getProperty("OutputWorkspace"); return matrixws; } } //---------------------------------------------------------------------------------------------- /** Add workspace2 to workspace1 by adding spectrum. */ MatrixWorkspace_sptr AlignAndFocusPowder::conjoinWorkspaces(API::MatrixWorkspace_sptr ws1, API::MatrixWorkspace_sptr ws2, size_t offset) { // Get information from ws1: maximum spectrum number, and store original // spectrum IDs size_t nspec1 = ws1->getNumberHistograms(); specid_t maxspecid1 = 0; std::vector<specid_t> origspecids; for (size_t i = 0; i < nspec1; ++i) { specid_t tmpspecid = ws1->getSpectrum(i)->getSpectrumNo(); origspecids.push_back(tmpspecid); if (tmpspecid > maxspecid1) maxspecid1 = tmpspecid; } g_log.information() << "[DBx536] Max spectrum number of ws1 = " << maxspecid1 << ", Offset = " << offset << ".\n"; size_t nspec2 = ws2->getNumberHistograms(); // Conjoin 2 workspaces Algorithm_sptr alg = this->createChildAlgorithm("AppendSpectra"); alg->initialize(); ; alg->setProperty("InputWorkspace1", ws1); alg->setProperty("InputWorkspace2", ws2); alg->setProperty("OutputWorkspace", ws1); alg->setProperty("ValidateInputs", false); alg->executeAsChildAlg(); API::MatrixWorkspace_sptr outws = alg->getProperty("OutputWorkspace"); // FIXED : Restore the original spectrum IDs to spectra from ws1 for (size_t i = 0; i < nspec1; ++i) { specid_t tmpspecid = outws->getSpectrum(i)->getSpectrumNo(); outws->getSpectrum(i)->setSpectrumNo(origspecids[i]); g_log.information() << "[DBx540] Conjoined spectrum " << i << ": restore spectrum number to " << outws->getSpectrum(i)->getSpectrumNo() << " from spectrum number = " << tmpspecid << ".\n"; } // Rename spectrum number if (offset >= 1) { for (size_t i = 0; i < nspec2; ++i) { specid_t newspecid = maxspecid1 + static_cast<specid_t>((i) + offset); outws->getSpectrum(nspec1 + i)->setSpectrumNo(newspecid); // ISpectrum* spec = outws->getSpectrum(nspec1+i); // if (spec) // spec->setSpectrumNo(3); } } return outws; } void AlignAndFocusPowder::convertOffsetsToCal( DataObjects::OffsetsWorkspace_sptr &offsetsWS) { if (!offsetsWS) return; IAlgorithm_sptr alg = createChildAlgorithm("ConvertDiffCal"); alg->setProperty("OffsetsWorkspace", offsetsWS); alg->setPropertyValue("OutputWorkspace", m_instName + "_cal"); alg->executeAsChildAlg(); m_calibrationWS = alg->getProperty("OutputWorkspace"); AnalysisDataService::Instance().addOrReplace(m_instName + "_cal", m_calibrationWS); } //---------------------------------------------------------------------------------------------- /** * Loads the .cal file if necessary. */ void AlignAndFocusPowder::loadCalFile(const std::string &calFileName) { // check if the workspaces exist with their canonical names so they are not // reloaded for chunks if ((!m_groupWS) && (!calFileName.empty())) { try { m_groupWS = AnalysisDataService::Instance().retrieveWS<GroupingWorkspace>( m_instName + "_group"); } catch (Exception::NotFoundError &) { ; // not noteworthy } } if ((!m_calibrationWS) && (!calFileName.empty())) { OffsetsWorkspace_sptr offsetsWS = getProperty("OffsetsWorkspace"); if (offsetsWS) { convertOffsetsToCal(offsetsWS); } else { try { m_calibrationWS = AnalysisDataService::Instance().retrieveWS<ITableWorkspace>( m_instName + "_cal"); } catch (Exception::NotFoundError &) { ; // not noteworthy } if (!m_calibrationWS) { try { OffsetsWorkspace_sptr offsetsWS = AnalysisDataService::Instance().retrieveWS<OffsetsWorkspace>( m_instName + "_offsets"); convertOffsetsToCal(offsetsWS); } catch (Exception::NotFoundError &) { ; // not noteworthy } } } } if ((!m_maskWS) && (!calFileName.empty())) { try { m_maskWS = AnalysisDataService::Instance().retrieveWS<MaskWorkspace>( m_instName + "_mask"); } catch (Exception::NotFoundError &) { ; // not noteworthy } } // see if everything exists to exit early if (m_groupWS && m_calibrationWS && m_maskWS) return; // see if the calfile is specified if (calFileName.empty()) return; g_log.information() << "Loading Calibration file \"" << calFileName << "\"\n"; // bunch of booleans to keep track of things bool loadGrouping = !m_groupWS; bool loadCalibration = !m_calibrationWS; bool loadMask = !m_maskWS; IAlgorithm_sptr alg = createChildAlgorithm("LoadDiffCal"); alg->setProperty("InputWorkspace", m_inputW); alg->setPropertyValue("Filename", calFileName); alg->setProperty<bool>("MakeCalWorkspace", loadCalibration); alg->setProperty<bool>("MakeGroupingWorkspace", loadGrouping); alg->setProperty<bool>("MakeMaskWorkspace", loadMask); alg->setPropertyValue("WorkspaceName", m_instName); alg->executeAsChildAlg(); // replace workspaces as appropriate if (loadGrouping) { m_groupWS = alg->getProperty("OutputGroupingWorkspace"); AnalysisDataService::Instance().addOrReplace(m_instName + "_group", m_groupWS); } if (loadCalibration) { m_calibrationWS = alg->getProperty("OutputCalWorkspace"); AnalysisDataService::Instance().addOrReplace(m_instName + "_cal", m_calibrationWS); } if (loadMask) { m_maskWS = alg->getProperty("OutputMaskWorkspace"); AnalysisDataService::Instance().addOrReplace(m_instName + "_mask", m_maskWS); } return; } //---------------------------------------------------------------------------------------------- /** Perform SortEvents on the output workspaces * but only if they are EventWorkspaces. * * @param ws :: any Workspace. Does nothing if not EventWorkspace. */ void AlignAndFocusPowder::doSortEvents(Mantid::API::Workspace_sptr ws) { EventWorkspace_sptr eventWS = boost::dynamic_pointer_cast<EventWorkspace>(ws); if (!eventWS) return; Algorithm_sptr alg = this->createChildAlgorithm("SortEvents"); alg->setProperty("InputWorkspace", eventWS); alg->setPropertyValue("SortBy", "X Value"); alg->executeAsChildAlg(); } } // namespace WorkflowAlgorithm } // namespace Mantid