double getSourceToSampleDistance(API::MatrixWorkspace_sptr dataWS) { const int nguides = dataWS->run().getPropertyValueAsType<int>("number-of-guides"); std::vector<std::string> pars = dataWS->getInstrument()->getStringParameter("aperture-distances"); if (pars.empty()) throw Kernel::Exception::InstrumentDefinitionError( "Unable to find [aperture-distances] instrument parameter"); double SSD = 0; Mantid::Kernel::StringTokenizer tok( pars[0], ",", Mantid::Kernel::StringTokenizer::TOK_IGNORE_EMPTY); if (tok.count() > 0 && tok.count() < 10 && nguides >= 0 && nguides < 9) { const std::string distance_as_string = tok[8 - nguides]; if (!Poco::NumberParser::tryParseFloat(distance_as_string, SSD)) throw Kernel::Exception::InstrumentDefinitionError( "Bad value for source-to-sample distance"); } else throw Kernel::Exception::InstrumentDefinitionError( "Unable to get source-to-sample distance"); // Check for an offset if (dataWS->getInstrument()->hasParameter("source-distance-offset")) { const double offset = readInstrumentParameter("source-distance-offset", dataWS); SSD += offset; } return SSD; }
/** Initialization method: @param bkgWS -- shared pointer to the workspace which contains background @param sourceWS -- shared pointer to the workspace to remove background from @param emode -- energy conversion mode used during internal units conversion (0 -- elastic, 1-direct, 2 indirect, as defined in Units conversion @param pLog -- pointer to the logger class which would report errors @param nThreads -- number of threads to be used for background removal @param inPlace -- if the background removal occurs from the existing workspace or target workspace has to be cloned. */ void BackgroundHelper::initialize(const API::MatrixWorkspace_const_sptr &bkgWS, const API::MatrixWorkspace_sptr &sourceWS, int emode, Kernel::Logger *pLog, int nThreads, bool inPlace) { m_bgWs = bkgWS; m_wkWS = sourceWS; m_Emode = emode; m_pgLog = pLog; m_inPlace = inPlace; std::string bgUnits = bkgWS->getAxis(0)->unit()->unitID(); if (bgUnits != "TOF") throw std::invalid_argument(" Background Workspace: " + bkgWS->getName() + " should be in the units of TOF"); if (!(bkgWS->getNumberHistograms() == 1 || sourceWS->getNumberHistograms() == bkgWS->getNumberHistograms())) throw std::invalid_argument(" Background Workspace: " + bkgWS->getName() + " should have the same number of spectra as " "source workspace or be a single histogram " "workspace"); auto WSUnit = sourceWS->getAxis(0)->unit(); if (!WSUnit) throw std::invalid_argument(" Source Workspace: " + sourceWS->getName() + " should have units"); Geometry::IComponent_const_sptr source = sourceWS->getInstrument()->getSource(); m_Sample = sourceWS->getInstrument()->getSample(); if ((!source) || (!m_Sample)) throw std::invalid_argument( "Instrument on Source workspace:" + sourceWS->getName() + "is not sufficiently defined: failed to get source and/or sample"); m_L1 = source->getDistance(*m_Sample); // just in case. this->deleteUnitsConverters(); // allocate the array of units converters to avoid units reallocation within a // loop m_WSUnit.assign(nThreads, NULL); for (int i = 0; i < nThreads; i++) { m_WSUnit[i] = WSUnit->clone(); } m_singleValueBackground = false; if (bkgWS->getNumberHistograms() == 0) m_singleValueBackground = true; const MantidVec &dataX = bkgWS->dataX(0); const MantidVec &dataY = bkgWS->dataY(0); // const MantidVec& dataE = bkgWS->dataE(0); m_NBg = dataY[0]; m_dtBg = dataX[1] - dataX[0]; // m_ErrSq = dataE[0]*dataE[0]; // needs further clarification m_Efix = this->getEi(sourceWS); }
double LoadHelper::getL1(const API::MatrixWorkspace_sptr& workspace) { Geometry::Instrument_const_sptr instrument = workspace->getInstrument(); Geometry::IComponent_const_sptr sample = instrument->getSample(); double l1 = instrument->getSource()->getDistance(*sample); return l1; }
/** Execute the algorithm. */ void CalculateDIFC::exec() { DataObjects::OffsetsWorkspace_const_sptr offsetsWs = getProperty("OffsetsWorkspace"); API::ITableWorkspace_const_sptr calibWs = getProperty("CalibrationWorkspace"); API::MatrixWorkspace_sptr inputWs = getProperty("InputWorkspace"); API::MatrixWorkspace_sptr outputWs = getProperty("OutputWorkspace"); if ((!bool(inputWs == outputWs)) || (!bool(boost::dynamic_pointer_cast<SpecialWorkspace2D>(outputWs)))) { outputWs = boost::dynamic_pointer_cast<MatrixWorkspace>( boost::make_shared<SpecialWorkspace2D>(inputWs->getInstrument())); outputWs->setTitle("DIFC workspace"); } // convert to actual type being used DataObjects::SpecialWorkspace2D_sptr outputSpecialWs = boost::dynamic_pointer_cast<DataObjects::SpecialWorkspace2D>(outputWs); API::Progress progress(this, 0.0, 1.0, inputWs->getNumberHistograms()); if (bool(calibWs)) { calculateFromTable(progress, *outputSpecialWs, *calibWs); } else { // this method handles calculating from instrument geometry as well const auto &detectorInfo = inputWs->detectorInfo(); calculateFromOffset(progress, *outputSpecialWs, offsetsWs.get(), detectorInfo); } setProperty("OutputWorkspace", outputWs); }
void FindDetectorsPar::populate_values_from_file( const API::MatrixWorkspace_sptr &inputWS) { size_t nHist = inputWS->getNumberHistograms(); if (this->current_ASCII_file.Type == PAR_type) { // in this case data in azimuthal width and polar width are in fact real // sizes in meters; have to transform it in into angular values for (size_t i = 0; i < nHist; i++) { azimuthalWidth[i] = atan2(azimuthalWidth[i], secondaryFlightpath[i]) * rad2deg; polarWidth[i] = atan2(polarWidth[i], secondaryFlightpath[i]) * rad2deg; } m_SizesAreLinear = false; } else { Geometry::IComponent_const_sptr sample = inputWS->getInstrument()->getSample(); secondaryFlightpath.resize(nHist); // Loop over the spectra for (size_t i = 0; i < nHist; i++) { Geometry::IDetector_const_sptr spDet; try { spDet = inputWS->getDetector(i); } catch (Kernel::Exception::NotFoundError &) { continue; } // Check that we aren't writing a monitor... if (spDet->isMonitor()) continue; /// this is the only value, which is not defined in phx file, so we /// calculate it secondaryFlightpath[i] = spDet->getDistance(*sample); } } }
/** Checks and retrieves the monitor spectrum out of the input workspace * @param inputWorkspace The input workspace. * @param wsID The workspace ID. * @returns A workspace containing the monitor spectrum only * @throw std::runtime_error If the properties are invalid */ API::MatrixWorkspace_sptr NormaliseToMonitor::getMonitorWorkspace(API::MatrixWorkspace_sptr inputWorkspace,int &wsID) { // Get the workspace from the ADS. Will throw if it's not there. MatrixWorkspace_sptr monitorWS = getProperty("MonitorWorkspace"); wsID = getProperty("MonitorWorkspaceIndex"); // Check that it's a single spectrum workspace if ( static_cast<int>(monitorWS->getNumberHistograms()) < wsID ) { throw std::runtime_error("The MonitorWorkspace must contain the MonitorWorkspaceIndex"); } // Check that the two workspace come from the same instrument if ( monitorWS->getInstrument()->getName() != inputWorkspace->getInstrument()->getName() ) { throw std::runtime_error("The Input and Monitor workspaces must come from the same instrument"); } // Check that they're in the same units if ( monitorWS->getAxis(0)->unit()->unitID() != inputWorkspace->getAxis(0)->unit()->unitID() ) { throw std::runtime_error("The Input and Monitor workspaces must have the same unit"); } // In this case we need to test whether the bins in the monitor workspace match m_commonBins = (m_commonBins && API::WorkspaceHelpers::matchingBins(inputWorkspace,monitorWS,true) ); // If the workspace passes all these tests, make a local copy because it will get changed return this->extractMonitorSpectrum(monitorWS,wsID); }
/** * Correct the position of the detectors based on the input theta value. * @param toCorrect : Workspace to correct detector posisitions on. * @param twoThetaInDeg : 2* Theta in degrees to use in correction calculations. * @param sample : Pointer to the sample * @param detector : Pointer to a given detector */ void SpecularReflectionPositionCorrect::correctPosition( API::MatrixWorkspace_sptr toCorrect, const double &twoThetaInDeg, IComponent_const_sptr sample, IComponent_const_sptr detector) { auto instrument = toCorrect->getInstrument(); const V3D detectorPosition = detector->getPos(); const V3D samplePosition = sample->getPos(); const V3D sampleToDetector = detectorPosition - samplePosition; auto referenceFrame = instrument->getReferenceFrame(); const double twoThetaInRad = twoThetaInDeg * (M_PI / 180.0); double acrossOffset = 0; double beamOffset = sampleToDetector.scalar_prod( referenceFrame ->vecPointingAlongBeam()); // We just recalculate beam offset. double upOffset = (beamOffset * std::tan(0.5 * twoThetaInRad)); // We only correct vertical position // Apply the movements. moveDetectors(toCorrect, detector, sample, upOffset, acrossOffset, detector->getPos()); }
/** This function will check how to group spectra when calculating median * * */ std::vector<std::vector<size_t> > DetectorDiagnostic::makeMap(API::MatrixWorkspace_sptr countsWS) { std::multimap<Mantid::Geometry::ComponentID,size_t> mymap; Geometry::Instrument_const_sptr instrument = countsWS->getInstrument(); if (m_parents==0) { return makeInstrumentMap(countsWS); } if (!instrument) { g_log.warning("Workspace has no instrument. LevelsUP is ignored"); return makeInstrumentMap(countsWS); } //check if not grouped. If grouped, it will throw if ( countsWS->hasGroupedDetectors() ) { throw std::runtime_error("Median detector test: not able to create detector to spectra map. Try with LevelUp=0."); } for(size_t i=0;i < countsWS->getNumberHistograms();i++) { detid_t d=(*((countsWS->getSpectrum(i))->getDetectorIDs().begin())); std::vector<boost::shared_ptr<const Mantid::Geometry::IComponent> > anc=instrument->getDetector(d)->getAncestors(); //std::vector<boost::shared_ptr<const IComponent> > anc=(*(countsWS->getSpectrum(i)->getDetectorIDs().begin()))->getAncestors(); if (anc.size()<static_cast<size_t>(m_parents)) { g_log.warning("Too many levels up. Will ignore LevelsUp"); m_parents=0; return makeInstrumentMap(countsWS); } mymap.insert(std::pair<Mantid::Geometry::ComponentID,size_t>(anc[m_parents-1]->getComponentID(),i)); } std::vector<std::vector<size_t> > speclist; std::vector<size_t> speclistsingle; std::multimap<Mantid::Geometry::ComponentID,size_t>::iterator m_it, s_it; for (m_it = mymap.begin(); m_it != mymap.end(); m_it = s_it) { Mantid::Geometry::ComponentID theKey = (*m_it).first; std::pair<std::multimap<Mantid::Geometry::ComponentID,size_t>::iterator,std::multimap<Mantid::Geometry::ComponentID,size_t>::iterator> keyRange = mymap.equal_range(theKey); // Iterate over all map elements with key == theKey speclistsingle.clear(); for (s_it = keyRange.first; s_it != keyRange.second; ++s_it) { speclistsingle.push_back( (*s_it).second ); } speclist.push_back(speclistsingle); } return speclist; }
/* * Read a parameter from the instrument description */ double readInstrumentParameter(const std::string ¶meter, API::MatrixWorkspace_sptr dataWS) { std::vector<double> pars = dataWS->getInstrument()->getNumberParameter(parameter); if (pars.empty()) throw Kernel::Exception::InstrumentDefinitionError( "Unable to find [" + parameter + "] instrument parameter"); return pars[0]; }
/** * Execute the MoveInstrumentComponent on all (named) subcomponents * @param toCorrect : Workspace to correct * @param detector : Detector or DetectorGroup * @param sample : Sample Component * @param upOffset : Up offset to apply * @param acrossOffset : Across offset to apply * @param detectorPosition: Actual detector or detector group position. */ void SpecularReflectionPositionCorrect::moveDetectors( API::MatrixWorkspace_sptr toCorrect, IComponent_const_sptr detector, IComponent_const_sptr sample, const double &upOffset, const double &acrossOffset, const V3D &detectorPosition) { auto instrument = toCorrect->getInstrument(); const V3D samplePosition = sample->getPos(); auto referenceFrame = instrument->getReferenceFrame(); if (auto groupDetector = boost::dynamic_pointer_cast<const DetectorGroup>( detector)) // Do we have a group of detectors { const std::vector<IDetector_const_sptr> detectors = groupDetector->getDetectors(); const bool commonParent = hasCommonParent(detectors); if (commonParent) { /* * Same parent component. So lets move that. */ moveDetectors(toCorrect, detectors[0], sample, upOffset, acrossOffset, detectorPosition); // Recursive call } else { /* * We have to move individual components. */ for (size_t i = 0; i < detectors.size(); ++i) { moveDetectors(toCorrect, detectors[i], sample, upOffset, acrossOffset, detectorPosition); // Recursive call } } } else { auto moveComponentAlg = this->createChildAlgorithm("MoveInstrumentComponent"); moveComponentAlg->initialize(); moveComponentAlg->setProperty("Workspace", toCorrect); IComponent_const_sptr root = getParentComponent(detector); const std::string componentName = root->getName(); moveComponentAlg->setProperty("ComponentName", componentName); moveComponentAlg->setProperty("RelativePosition", false); // Movements moveComponentAlg->setProperty( referenceFrame->pointingAlongBeamAxis(), detectorPosition.scalar_prod(referenceFrame->vecPointingAlongBeam())); moveComponentAlg->setProperty(referenceFrame->pointingHorizontalAxis(), acrossOffset); const double detectorVerticalPosition = detectorPosition.scalar_prod(referenceFrame->vecPointingUp()); const double rootVerticalPosition = root->getPos().scalar_prod(referenceFrame->vecPointingUp()); const double dm = rootVerticalPosition - detectorVerticalPosition; moveComponentAlg->setProperty( referenceFrame->pointingUpAxis(), samplePosition.scalar_prod(referenceFrame->vecPointingUp()) + upOffset + dm); // Execute the movement. moveComponentAlg->execute(); } }
double LoadHelper::getL2(const API::MatrixWorkspace_sptr& workspace, int detId) { // Get a pointer to the instrument contained in the workspace Geometry::Instrument_const_sptr instrument = workspace->getInstrument(); // Get the distance between the source and the sample (assume in metres) Geometry::IComponent_const_sptr sample = instrument->getSample(); // Get the sample-detector distance for this detector (in metres) double l2 = workspace->getDetector(detId)->getPos().distance(sample->getPos()); return l2; }
/** Put the parameters into one workspace * @param column :: [input] column of the output table workspace * @param ws :: [input/output] the group workspace parameters are to be put in * @param nProf :: the PROF Number, which is used to determine fitting function * for the parameters. * @param parameterXMLString :: string where the XML document filename is * stored */ void LoadFullprofResolution::putParametersIntoWorkspace( API::Column_const_sptr column, API::MatrixWorkspace_sptr ws, int nProf, std::string ¶meterXMLString) { // Get instrument name from matrix workspace std::string instrumentName = ws->getInstrument()->getName(); // Convert table workspace column into DOM XML document // Set up writer to Paremeter file DOMWriter writer; writer.setNewLine("\n"); writer.setOptions(XMLWriter::PRETTY_PRINT); // Get current time Kernel::DateAndTime date = Kernel::DateAndTime::getCurrentTime(); std::string ISOdate = date.toISO8601String(); std::string ISOdateShort = ISOdate.substr(0, 19); // Remove fraction of seconds // Create document AutoPtr<Document> mDoc = new Document(); AutoPtr<Element> rootElem = mDoc->createElement("parameter-file"); rootElem->setAttribute("date", ISOdateShort); mDoc->appendChild(rootElem); // Add instrument AutoPtr<Element> instrumentElem = mDoc->createElement("component-link"); instrumentElem->setAttribute("name", instrumentName); rootElem->appendChild(instrumentElem); if (nProf == 9) // put parameters into BackToBackExponential function { addBBX_S_Parameters(column, mDoc, instrumentElem); addBBX_A_Parameters(column, mDoc, instrumentElem); addBBX_B_Parameters(column, mDoc, instrumentElem); } else // Assume IkedaCarpenter PV { addALFBEParameter(column, mDoc, instrumentElem, "Alph0"); addALFBEParameter(column, mDoc, instrumentElem, "Beta0"); addALFBEParameter(column, mDoc, instrumentElem, "Alph1"); addALFBEParameter(column, mDoc, instrumentElem, "Beta1"); addSigmaParameters(column, mDoc, instrumentElem); addGammaParameters(column, mDoc, instrumentElem); } // Convert DOM XML document into string std::ostringstream outFile; writer.writeNode(outFile, mDoc); parameterXMLString = outFile.str(); // Useful code for testing upgrades commented out for production use // std::ofstream outfileDebug("C:/Temp/test4_fullprof.xml"); // outfileDebug << parameterXMLString; // outfileDebug.close(); }
/** Loads, checks and passes back the values passed to the algorithm * @param whiteBeam1 :: A white beam vanadium spectrum that will be used to * check detector efficiency variations * @param whiteBeam2 :: The other white beam vanadium spectrum from the same * instrument to use for comparison * @param variation :: The maximum fractional variation above the median that is * allowed for god detectors * @param startWsIndex :: Index number of the first spectrum to use * @param endWsIndex :: Index number of the last spectrum to use * @throw invalid_argument if there is an incapatible property value and so the * algorithm can't continue */ void DetectorEfficiencyVariation::retrieveProperties( API::MatrixWorkspace_sptr &whiteBeam1, API::MatrixWorkspace_sptr &whiteBeam2, double &variation, int &startWsIndex, int &endWsIndex) { whiteBeam1 = getProperty("WhiteBeamBase"); whiteBeam2 = getProperty("WhiteBeamCompare"); if (whiteBeam1->getInstrument()->getName() != whiteBeam2->getInstrument()->getName()) { throw std::invalid_argument("The two input white beam vanadium workspaces " "must be from the same instrument"); } int maxWsIndex = static_cast<int>(whiteBeam1->getNumberHistograms()) - 1; if (maxWsIndex != static_cast<int>(whiteBeam2->getNumberHistograms()) - 1) { // we would get a crash later on if this were not true throw std::invalid_argument("The input white beam vanadium workspaces must " "be have the same number of histograms"); } variation = getProperty("Variation"); startWsIndex = getProperty("StartWorkspaceIndex"); if ((startWsIndex < 0) || (startWsIndex > maxWsIndex)) { g_log.warning("StartWorkspaceIndex out of range, changed to 0"); startWsIndex = 0; } endWsIndex = getProperty("EndWorkspaceIndex"); if (endWsIndex == Mantid::EMPTY_INT()) endWsIndex = maxWsIndex; if ((endWsIndex < 0) || (endWsIndex > maxWsIndex)) { g_log.warning( "EndWorkspaceIndex out of range, changed to max Workspace number"); endWsIndex = maxWsIndex; } if ((endWsIndex < startWsIndex)) { g_log.warning( "EndWorkspaceIndex can not be less than the StartWorkspaceIndex, " "changed to max Workspace number"); endWsIndex = maxWsIndex; } }
/* * Get instrument property as double * @s - input property name * */ double LoadHelper::getInstrumentProperty(const API::MatrixWorkspace_sptr &workspace, std::string s) { std::vector<std::string> prop = workspace->getInstrument()->getStringParameter(s); if (prop.empty()) { g_log.debug("Property <" + s + "> doesn't exist!"); return EMPTY_DBL(); } else { g_log.debug() << "Property <" + s + "> = " << prop[0] << '\n'; return boost::lexical_cast<double>(prop[0]); } }
V3D LoadHelper::getComponentPosition(API::MatrixWorkspace_sptr ws, const std::string &componentName) { try { Geometry::Instrument_const_sptr instrument = ws->getInstrument(); Geometry::IComponent_const_sptr component = instrument->getComponentByName(componentName); V3D pos = component->getPos(); return pos; } catch (Mantid::Kernel::Exception::NotFoundError&) { throw std::runtime_error("Error when trying to move the " + componentName + " : NotFoundError"); } }
/** * Mask the outlier values to get a better median value. * @param medianvec The median value calculated from the current counts. * @param countsWS The counts workspace. Any outliers will be masked here. * @param indexmap Index map. * @returns The number failed. */ int MedianDetectorTest::maskOutliers(const std::vector<double> medianvec, API::MatrixWorkspace_sptr countsWS,std::vector<std::vector<size_t> > indexmap) { // Fractions of the median const double out_lo = getProperty("LowOutlier"); const double out_hi = getProperty("HighOutlier"); int numFailed(0); bool checkForMask = false; Geometry::Instrument_const_sptr instrument = countsWS->getInstrument(); if (instrument != NULL) { checkForMask = ((instrument->getSource() != NULL) && (instrument->getSample() != NULL)); } for (size_t i=0; i<indexmap.size(); ++i) { std::vector<size_t> hists=indexmap.at(i); double median=medianvec.at(i); PARALLEL_FOR1(countsWS) for(int j = 0; j < static_cast<int>(hists.size()); ++j) { const double value = countsWS->readY(hists.at(j))[0]; if ((value == 0.) && checkForMask) { const std::set<detid_t>& detids = countsWS->getSpectrum(hists.at(j))->getDetectorIDs(); if (instrument->isDetectorMasked(detids)) { numFailed -= 1; // it was already masked } } if( (value < out_lo*median) && (value > 0.0) ) { countsWS->maskWorkspaceIndex(hists.at(j)); PARALLEL_ATOMIC ++numFailed; } else if( value > out_hi*median ) { countsWS->maskWorkspaceIndex(hists.at(j)); PARALLEL_ATOMIC ++numFailed; } } PARALLEL_CHECK_INTERUPT_REGION } return numFailed; }
/** * If grouping was not provided, find the instrument from the input workspace * and read the default grouping from its IDF. Returns the forward and backward * groupings as arrays of integers. * @param ws :: [input] Workspace to find grouping for * @param forward :: [output] Forward spectrum indices for given instrument * @param backward :: [output] Backward spectrum indices for given instrument */ void CalMuonDetectorPhases::getGroupingFromInstrument( const API::MatrixWorkspace_sptr &ws, std::vector<int> &forward, std::vector<int> &backward) { // make sure both arrays are empty forward.clear(); backward.clear(); const auto instrument = ws->getInstrument(); auto loader = Kernel::make_unique<API::GroupingLoader>(instrument); if (instrument->getName() == "MUSR" || instrument->getName() == "CHRONUS") { // Two possibilities for grouping - use workspace log auto fieldDir = ws->run().getLogData("main_field_direction"); if (fieldDir) { loader = Kernel::make_unique<API::GroupingLoader>(instrument, fieldDir->value()); } if (!fieldDir) { throw std::invalid_argument( "Cannot use default instrument grouping for MUSR " "as main field direction is unknown"); } } // Load grouping and find forward, backward groups std::string fwdRange, bwdRange; const auto grouping = loader->getGroupingFromIDF(); size_t nGroups = grouping->groups.size(); for (size_t iGroup = 0; iGroup < nGroups; iGroup++) { const std::string name = grouping->groupNames[iGroup]; if (name == "fwd" || name == "left") { fwdRange = grouping->groups[iGroup]; } else if (name == "bwd" || name == "bkwd" || name == "right") { bwdRange = grouping->groups[iGroup]; } } // Use ArrayProperty's functionality to convert string ranges to groups this->setProperty("ForwardSpectra", fwdRange); this->setProperty("BackwardSpectra", bwdRange); forward = getProperty("ForwardSpectra"); backward = getProperty("BackwardSpectra"); }
/**Validates if either input workspace or instrument name is defined @return the inconsistency between Instrument/Workspace properties or empty list if no errors is found. */ std::map<std::string, std::string> LoadMask::validateInputs() { std::map<std::string, std::string> result; API::MatrixWorkspace_sptr inputWS = getProperty("RefWorkspace"); std::string InstrName = getProperty("Instrument"); if (inputWS) { boost::trim(InstrName); boost::algorithm::to_lower(InstrName); size_t len = InstrName.size(); /// input property contains name of instrument definition file rather than /// instrument name itself bool IDF_provided{false}; // Check if the name ends up with .xml which means that idf file name // is provided rather then an instrument name. if (len > 4) { if (InstrName.compare(len - 4, len, ".xml") == 0) { IDF_provided = true; } else { IDF_provided = false; } } else { IDF_provided = false; } try { auto inst = inputWS->getInstrument(); std::string Name = inst->getName(); boost::algorithm::to_lower(Name); if (Name != InstrName && !IDF_provided) { result["RefWorkspace"] = "If both reference workspace and instrument name are defined, " "workspace has to have the instrument with the same name\n" "'Instrument' value: " + InstrName + " Workspace Instrument name: " + Name; } } catch (Kernel::Exception::NotFoundError &) { result["RefWorkspace"] = "If reference workspace is defined, it mast have an instrument"; } } return result; }
/** Convert X axis to Elastic Q representation * @param progress :: Progress indicator * @param targetUnit :: Target conversion unit * @param inputWS :: Input workspace * @param nHist :: Stores the number of histograms */ void ConvertSpectrumAxis2::createElasticQMap(API::Progress &progress, const std::string &targetUnit, API::MatrixWorkspace_sptr &inputWS, size_t nHist) { IComponent_const_sptr source = inputWS->getInstrument()->getSource(); IComponent_const_sptr sample = inputWS->getInstrument()->getSample(); const std::string emodeStr = getProperty("EMode"); int emode = 0; if (emodeStr == "Direct") emode = 1; else if (emodeStr == "Indirect") emode = 2; for (size_t i = 0; i < nHist; i++) { IDetector_const_sptr detector = inputWS->getDetector(i); double twoTheta(0.0), efixed(0.0); if (!detector->isMonitor()) { twoTheta = 0.5 * inputWS->detectorTwoTheta(*detector); efixed = getEfixed(detector, inputWS, emode); // get efixed } else { twoTheta = 0.0; efixed = DBL_MIN; } // Convert to MomentumTransfer double elasticQInAngstroms = Kernel::UnitConversion::run(twoTheta, efixed); if (targetUnit == "ElasticQ") { m_indexMap.emplace(elasticQInAngstroms, i); } else if (targetUnit == "ElasticQSquared") { // The QSquared value. double elasticQSquaredInAngstroms = elasticQInAngstroms * elasticQInAngstroms; m_indexMap.emplace(elasticQSquaredInAngstroms, i); } progress.report("Converting to Elastic Q..."); } }
/** Executes the algorithm. Moving detectors of input workspace to positions indicated in table workspace * * @throw FileError Thrown if unable to get instrument from workspace, * table workspace is incompatible with instrument */ void ApplyCalibration::exec() { // Get pointers to the workspace, parameter map and table API::MatrixWorkspace_sptr inputWS = getProperty("Workspace"); m_pmap = &(inputWS->instrumentParameters()); // Avoids a copy if you get the reference before the instrument API::ITableWorkspace_sptr PosTable = getProperty("PositionTable"); Geometry::Instrument_const_sptr instrument = inputWS->getInstrument(); if(!instrument) { throw std::runtime_error("Workspace to apply calibration to has no defined instrument"); } size_t numDetector = PosTable->rowCount(); ColumnVector<int> detID = PosTable->getVector("Detector ID"); ColumnVector<V3D> detPos = PosTable->getVector("Detector Position"); // numDetector needs to be got as the number of rows in the table and the detID got from the (i)th row of table. for (size_t i = 0; i < numDetector; ++i) { setDetectorPosition(instrument, detID[i], detPos[i], false ); } // Ensure pointer is only valid for execution m_pmap = NULL; }
void LoadHelper::rotateComponent(API::MatrixWorkspace_sptr ws, const std::string &componentName, const Kernel::Quat & rot) { try { Geometry::Instrument_const_sptr instrument = ws->getInstrument(); Geometry::IComponent_const_sptr component = instrument->getComponentByName(componentName); //g_log.debug() << tube->getName() << " : t = " << theta << " ==> t = " << newTheta << "\n"; Geometry::ParameterMap& pmap = ws->instrumentParameters(); Geometry::ComponentHelper::rotateComponent(*component, pmap, rot, Geometry::ComponentHelper::Absolute); } catch (Mantid::Kernel::Exception::NotFoundError&) { throw std::runtime_error("Error when trying to move the " + componentName + " : NotFoundError"); } catch (std::runtime_error &) { throw std::runtime_error("Error when trying to move the " + componentName + " : runtime_error"); } }
/** * Takes a single valued histogram workspace and assesses which histograms are within the limits. * Those that are not are masked on the input workspace. * @param countsWS :: Input/Output Integrated workspace to diagnose. * @param medianvec The median value calculated from the current counts. * @param indexmap Index map. * @param maskWS :: A mask workspace to apply. * @return The number of detectors that failed the tests, not including those skipped. */ int MedianDetectorTest::doDetectorTests(const API::MatrixWorkspace_sptr countsWS, const std::vector<double> medianvec, std::vector<std::vector<size_t> > indexmap, API::MatrixWorkspace_sptr maskWS) { g_log.debug("Applying the criteria to find failing detectors"); // A spectra can't fail if the statistics show its value is consistent with the mean value, // check the error and how many errorbars we are away const double minSigma = getProperty("SignificanceTest"); // prepare to report progress const int numSpec(m_maxSpec - m_minSpec); const int progStep = static_cast<int>(ceil(numSpec/30.0)); int steps(0); const double deadValue(1.0); int numFailed(0); bool checkForMask = false; Geometry::Instrument_const_sptr instrument = countsWS->getInstrument(); if (instrument != NULL) { checkForMask = ((instrument->getSource() != NULL) && (instrument->getSample() != NULL)); } PARALLEL_FOR2(countsWS, maskWS) for (int j=0;j<static_cast<int>(indexmap.size());++j) { std::vector<size_t> hists=indexmap.at(j); double median=medianvec.at(j); const size_t nhist = hists.size(); g_log.debug() << "new component with " <<nhist <<" spectra.\n"; for (size_t i = 0; i < nhist; ++i) { g_log.debug() << "Counts workspace index=" << i << ", Mask workspace index=" << hists.at(i) << std::endl; PARALLEL_START_INTERUPT_REGION ++steps; // update the progressbar information if (steps % progStep == 0) { progress(advanceProgress(progStep*static_cast<double>(RTMarkDetects)/numSpec)); } if (checkForMask) { const std::set<detid_t>& detids = countsWS->getSpectrum(i)->getDetectorIDs(); if (instrument->isDetectorMasked(detids)) { maskWS->dataY(hists.at(i))[0] = deadValue; continue; } if (instrument->isMonitor(detids)) { // Don't include in calculation but don't mask it continue; } } const double signal = countsWS->dataY(hists.at(i))[0]; // Mask out NaN and infinite if( boost::math::isinf(signal) || boost::math::isnan(signal) ) { maskWS->dataY(hists.at(i))[0] = deadValue; PARALLEL_ATOMIC ++numFailed; continue; } const double error = minSigma*countsWS->readE(hists.at(i))[0]; if( (signal < median*m_loFrac && (signal-median < -error)) || (signal > median*m_hiFrac && (signal-median > error)) ) { maskWS->dataY(hists.at(i))[0] = deadValue; PARALLEL_ATOMIC ++numFailed; } PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION // Log finds g_log.information() << numFailed << " spectra failed the median tests.\n"; } return numFailed; }
/** * Finds the median of values in single bin histograms rejecting spectra from masked * detectors and the results of divide by zero (infinite and NaN). * The median is an average that is less affected by small numbers of very large values. * @param input :: A histogram workspace with one entry in each bin * @param excludeZeroes :: If true then zeroes will not be included in the median calculation * @param indexmap :: indexmap * @return The median value of the histograms in the workspace that was passed to it * @throw out_of_range if a value is negative */ std::vector<double> DetectorDiagnostic::calculateMedian(const API::MatrixWorkspace_sptr input, bool excludeZeroes, std::vector<std::vector<size_t> > indexmap) { std::vector<double> medianvec; g_log.debug("Calculating the median count rate of the spectra"); for (size_t j=0; j< indexmap.size(); ++j) { std::vector<double> medianInput; std::vector<size_t> hists=indexmap.at(j); const int nhists = static_cast<int>(hists.size()); // The maximum possible length is that of workspace length medianInput.reserve(nhists); bool checkForMask = false; Geometry::Instrument_const_sptr instrument = input->getInstrument(); if (instrument != NULL) { checkForMask = ((instrument->getSource() != NULL) && (instrument->getSample() != NULL)); } PARALLEL_FOR1(input) for (int i = 0; i<static_cast<int>(hists.size()); ++i) { PARALLEL_START_INTERUPT_REGION if (checkForMask) { const std::set<detid_t>& detids = input->getSpectrum(hists[i])->getDetectorIDs(); if (instrument->isDetectorMasked(detids)) continue; if (instrument->isMonitor(detids)) continue; } const double yValue = input->readY(hists[i])[0]; if ( yValue < 0.0 ) { throw std::out_of_range("Negative number of counts found, could be corrupted raw counts or solid angle data"); } if( boost::math::isnan(yValue) || boost::math::isinf(yValue) || (excludeZeroes && yValue < DBL_EPSILON)) // NaNs/Infs { continue; } // Now we have a good value PARALLEL_CRITICAL(DetectorDiagnostic_median_d) { medianInput.push_back(yValue); } PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION if(medianInput.empty()) { g_log.information("some group has no valid histograms. Will use 0 for median."); medianInput.push_back(0.); } // We need a sorted array to calculate the median std::sort(medianInput.begin(), medianInput.end()); double median = gsl_stats_median_from_sorted_data( &medianInput[0], 1, medianInput.size() ); if ( median < 0 || median > DBL_MAX/10.0 ) { throw std::out_of_range("The calculated value for the median was either negative or unreliably large"); } medianvec.push_back(median); } return medianvec; }