/** Extract mask information from a workspace containing instrument * @return vector of detector IDs of detectors that are masked */ std::vector<detid_t> ExtractMaskToTable::extractMaskFromMatrixWorkspace() { // Clear input std::vector<detid_t> maskeddetids; // Get on hold of instrument Instrument_const_sptr instrument = m_dataWS->getInstrument(); if (!instrument) throw runtime_error("There is no instrument in input workspace."); // Extract size_t numdets = instrument->getNumberDetectors(); vector<detid_t> detids = instrument->getDetectorIDs(); for (size_t i = 0; i < numdets; ++i) { detid_t tmpdetid = detids[i]; IDetector_const_sptr tmpdetector = instrument->getDetector(tmpdetid); bool masked = tmpdetector->isMasked(); if (masked) { maskeddetids.push_back(tmpdetid); } g_log.debug() << "[DB] Detector No. " << i << ": ID = " << tmpdetid << ", Masked = " << masked << ".\n"; } g_log.notice() << "Extract mask: There are " << maskeddetids.size() << " detectors that" " are masked." << ".\n"; return maskeddetids; }
/** * @param offsetsWS * @param index * @return The offset adjusted value of DIFC */ double calculateDIFC(OffsetsWorkspace_const_sptr offsetsWS, const size_t index) { Instrument_const_sptr instrument = offsetsWS->getInstrument(); const detid_t detid = getDetID(offsetsWS, index); const double offset = getOffset(offsetsWS, detid); double l1; Kernel::V3D beamline, samplePos; double beamline_norm; instrument->getInstrumentParameters(l1, beamline, beamline_norm, samplePos); Geometry::IDetector_const_sptr detector = instrument->getDetector(detid); // the factor returned is what is needed to convert TOF->d-spacing // the table is supposed to be filled with DIFC which goes the other way const double factor = Instrument::calcConversion(l1, beamline, beamline_norm, samplePos, detector, offset); return 1./factor; }
/** Read the scaling information from a file (e.g. merlin_detector.sca) or from * the RAW file (.raw) * @param scalingFile :: Name of scaling file .sca * @param truepos :: V3D vector of actual positions as read from the file * @return False if unable to open file, True otherwise */ bool SetScalingPSD::processScalingFile(const std::string &scalingFile, std::vector<Kernel::V3D> &truepos) { // Read the scaling information from a text file (.sca extension) or from a // raw file (.raw) // This is really corrected positions as (r,theta,phi) for each detector // Compare these with the instrument values to determine the change in // position and the scaling // which may be necessary for each pixel if in a tube. // movePos is used to updated positions std::map<int, Kernel::V3D> posMap; std::map<int, double> scaleMap; std::map<int, double>::iterator its; Instrument_const_sptr instrument = m_workspace->getInstrument(); if (scalingFile.find(".sca") != std::string::npos || scalingFile.find(".SCA") != std::string::npos) { // read a .sca text format file // format consists of a short header followed by one line per detector std::ifstream sFile(scalingFile.c_str()); if (!sFile) { g_log.error() << "Unable to open scaling file " << scalingFile << std::endl; return false; } std::string str; getline(sFile, str); // skip header line should be <filename> generated by <prog> int detectorCount; getline(sFile, str); // get detector count line std::istringstream istr(str); istr >> detectorCount; if (detectorCount < 1) { g_log.error("Bad detector count in scaling file"); throw std::runtime_error("Bad detector count in scaling file"); } truepos.reserve(detectorCount); getline(sFile, str); // skip title line int detIdLast = -10; Kernel::V3D truPosLast, detPosLast; Progress prog(this, 0.0, 0.5, detectorCount); // Now loop through lines, one for each detector/monitor. The latter are // ignored. while (getline(sFile, str)) { if (str.empty() || str[0] == '#') continue; std::istringstream istr(str); // read 6 values from the line to get the 3 (l2,theta,phi) of interest int detIndex, code; double l2, theta, phi, offset; istr >> detIndex >> offset >> l2 >> code >> theta >> phi; // sanity check on angles - l2 should be +ve but sample file has a few -ve // values // on monitors if (theta > 181.0 || theta < -1 || phi < -181 || phi > 181) { g_log.error("Position angle data out of range in .sca file"); throw std::runtime_error( "Position angle data out of range in .sca file"); } Kernel::V3D truPos; // use abs as correction file has -ve l2 for first few detectors truPos.spherical(fabs(l2), theta, phi); truepos.push_back(truPos); // Geometry::IDetector_const_sptr det; try { det = instrument->getDetector(detIndex); } catch (Kernel::Exception::NotFoundError &) { continue; } Kernel::V3D detPos = det->getPos(); Kernel::V3D shift = truPos - detPos; // scaling applied to dets that are not monitors and have sequential IDs if (detIdLast == detIndex - 1 && !det->isMonitor()) { Kernel::V3D diffI = detPos - detPosLast; Kernel::V3D diffT = truPos - truPosLast; double scale = diffT.norm() / diffI.norm(); Kernel::V3D scaleDir = diffT / diffT.norm(); // Wish to store the scaling in a map, if we already have a scaling // for this detector (i.e. from the other side) we average the two // values. End of tube detectors only have one scaling estimate. scaleMap[detIndex] = scale; its = scaleMap.find(detIndex - 1); if (its == scaleMap.end()) scaleMap[detIndex - 1] = scale; else its->second = 0.5 * (its->second + scale); // std::cout << detIndex << scale << scaleDir << std::endl; } detIdLast = detIndex; detPosLast = detPos; truPosLast = truPos; posMap[detIndex] = shift; // prog.report(); } } else if (scalingFile.find(".raw") != std::string::npos ||
/** 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; }