/** * Creates a new parameterized instrument for which the parameter values can be *changed * * @param Peaks - a PeaksWorkspace used to get the original instrument. The *instrument from the 0th peak is * the one that is used. * * NOTE: All the peaks in the PeaksWorkspace must use the same instrument. */ boost::shared_ptr<Geometry::Instrument> PeakHKLErrors::getNewInstrument(PeaksWorkspace_sptr Peaks) const { Geometry::Instrument_const_sptr instSave = Peaks->getPeak(0).getInstrument(); auto pmap = boost::make_shared<Geometry::ParameterMap>(); if (!instSave) { g_log.error(" Peaks workspace does not have an instrument"); throw std::invalid_argument(" Not all peaks have an instrument"); } if (!hasParameterMap) { pmapSv = instSave->getParameterMap(); hasParameterMap = true; if (!instSave->isParametrized()) { boost::shared_ptr<Geometry::Instrument> instClone(instSave->clone()); auto Pinsta = boost::make_shared<Geometry::Instrument>(instSave, pmap); instChange = Pinsta; IComponent_const_sptr sample = instChange->getSample(); sampPos = sample->getRelativePos(); } else // catch(... ) { auto P1 = boost::make_shared<Geometry::Instrument>( instSave->baseInstrument(), instSave->makeLegacyParameterMap()); instChange = P1; IComponent_const_sptr sample = instChange->getSample(); sampPos = sample->getRelativePos(); } } if (!instChange) { g_log.error("Cannot 'clone' instrument"); throw std::logic_error("Cannot clone instrument"); } //------------------"clone" orig instruments pmap ------------------- cLone(pmap, instSave, pmapSv); V3D sampOffsets(getParameter("SampleXOffset"), getParameter("SampleYOffset"), getParameter("SampleZOffset")); IComponent_const_sptr sample = instChange->getSample(); pmap->addPositionCoordinate(sample.get(), std::string("x"), sampPos.X() + sampOffsets.X()); pmap->addPositionCoordinate(sample.get(), std::string("y"), sampPos.Y() + sampOffsets.Y()); pmap->addPositionCoordinate(sample.get(), std::string("z"), sampPos.Z() + sampOffsets.Z()); return instChange; }
/** Gets the distances between the source and detectors whose IDs you pass to it * @param WS :: the input workspace * @param mon0Spec :: Spectrum number of the output from the first monitor * @param mon1Spec :: Spectrum number of the output from the second monitor * @param monitor0Dist :: the calculated distance to the detector whose ID was * passed to this function first * @param monitor1Dist :: calculated distance to the detector whose ID was * passed to this function second * @throw NotFoundError if no detector is found for the detector ID given */ void GetEi::getGeometry(API::MatrixWorkspace_const_sptr WS, specid_t mon0Spec, specid_t mon1Spec, double &monitor0Dist, double &monitor1Dist) const { const IComponent_const_sptr source = WS->getInstrument()->getSource(); // retrieve a pointer to the first detector and get its distance size_t monWI = 0; try { monWI = WS->getIndexFromSpectrumNumber(mon0Spec); } catch (std::runtime_error &) { g_log.error() << "Could not find the workspace index for the monitor at spectrum " << mon0Spec << "\n"; g_log.error() << "Error retrieving data for the first monitor" << std::endl; throw std::bad_cast(); } const std::set<detid_t> &dets = WS->getSpectrum(monWI)->getDetectorIDs(); if (dets.size() != 1) { g_log.error() << "The detector for spectrum number " << mon0Spec << " was either not found or is a group, grouped monitors " "are not supported by this algorithm\n"; g_log.error() << "Error retrieving data for the first monitor" << std::endl; throw std::bad_cast(); } IDetector_const_sptr det = WS->getInstrument()->getDetector(*dets.begin()); monitor0Dist = det->getDistance(*(source.get())); // repeat for the second detector try { monWI = WS->getIndexFromSpectrumNumber(mon0Spec); } catch (std::runtime_error &) { g_log.error() << "Could not find the workspace index for the monitor at spectrum " << mon0Spec << "\n"; g_log.error() << "Error retrieving data for the second monitor\n"; throw std::bad_cast(); } const std::set<detid_t> &dets2 = WS->getSpectrum(monWI)->getDetectorIDs(); if (dets2.size() != 1) { g_log.error() << "The detector for spectrum number " << mon1Spec << " was either not found or is a group, grouped monitors " "are not supported by this algorithm\n"; g_log.error() << "Error retrieving data for the second monitor\n"; throw std::bad_cast(); } det = WS->getInstrument()->getDetector(*dets2.begin()); monitor1Dist = det->getDistance(*(source.get())); }
/** Executes the algorithm. * * @throw std::runtime_error Thrown with Workspace problems */ void RotateInstrumentComponent::exec() { // Get the workspace MatrixWorkspace_sptr WS = getProperty("Workspace"); const std::string ComponentName = getProperty("ComponentName"); const int DetID = getProperty("DetectorID"); const double X = getProperty("X"); const double Y = getProperty("Y"); const double Z = getProperty("Z"); const double angle = getProperty("Angle"); const bool RelativeRotation = getProperty("RelativeRotation"); if (X + Y + Z == 0.0) throw std::invalid_argument("The rotation axis must not be a zero vector"); Instrument_const_sptr inst = WS->getInstrument(); IComponent_const_sptr comp; // Find the component to move if (DetID != -1) { comp = inst->getDetector(DetID); if (comp == 0) { std::ostringstream mess; mess<<"Detector with ID "<<DetID<<" was not found."; g_log.error(mess.str()); throw std::runtime_error(mess.str()); } } else if (!ComponentName.empty()) { comp = inst->getComponentByName(ComponentName); if (comp == 0) { std::ostringstream mess; mess<<"Component with name "<<ComponentName<<" was not found."; g_log.error(mess.str()); throw std::runtime_error(mess.str()); } } else { g_log.error("DetectorID or ComponentName must be given."); throw std::invalid_argument("DetectorID or ComponentName must be given."); } // First set new relative or absolute rotation Quat Rot; if (RelativeRotation) { Quat Rot0 = comp->getRelativeRot(); Rot = Rot0 * Quat(angle,V3D(X,Y,Z)); } else { Rot = Quat(angle,V3D(X,Y,Z)); // Then find the corresponding relative position boost::shared_ptr<const IComponent> parent = comp->getParent(); if (parent) { Quat rot0 = parent->getRelativeRot(); rot0.inverse(); Rot = Rot * rot0; } } //Need to get the address to the base instrument component Geometry::ParameterMap& pmap = WS->instrumentParameters(); // Add a parameter for the new rotation pmap.addQuat(comp.get(), "rot", Rot); return; }