/** * Update the shape cache if necessary * @param det :: a pointer to the detector to query * @param detRadius :: An output parameter that contains the detector radius * @param detAxis :: An output parameter that contains the detector axis vector */ void He3TubeEfficiency::getDetectorGeometry(const Geometry::IDetector &det, double &detRadius, Kernel::V3D &detAxis) { boost::shared_ptr<const Geometry::Object> shape_sptr = det.shape(); if (!shape_sptr) { throw std::runtime_error( "Detector geometry error: detector with id: " + std::to_string(det.getID()) + " does not have shape. Is this a detectors group?\n" "The algorithm works for instruments with one-to-one " "spectra-to-detector maps only!"); } std::map<const Geometry::Object *, std::pair<double, Kernel::V3D>>::const_iterator it = this->shapeCache.find(shape_sptr.get()); if (it == this->shapeCache.end()) { double xDist = distToSurface(Kernel::V3D(DIST_TO_UNIVERSE_EDGE, 0, 0), shape_sptr.get()); double zDist = distToSurface(Kernel::V3D(0, 0, DIST_TO_UNIVERSE_EDGE), shape_sptr.get()); if (std::abs(zDist - xDist) < 1e-8) { detRadius = zDist / 2.0; detAxis = Kernel::V3D(0, 1, 0); // assume radii in z and x and the axis is in the y PARALLEL_CRITICAL(deteff_shapecachea) { this->shapeCache.insert( std::pair<const Geometry::Object *, std::pair<double, Kernel::V3D>>( shape_sptr.get(), std::pair<double, Kernel::V3D>(detRadius, detAxis))); } return; }
/** Method calculates averaged polar coordinates of the detector's group (which may consist of one detector) *@param det -- reference to the Mantid Detector *@param Observer -- sample position or the centre of the polar system of coordinates to calculate detector's parameters. *@param Detector -- return Detector class containing averaged polar coordinates of the detector or detector's group in spherical coordinate system with centre at Observer */ void FindDetectorsPar::calcDetPar(const Geometry::IDetector &det, const Kernel::V3D &Observer, DetParameters &Detector) { // get number of basic detectors within the composit detector size_t nDetectors = det.nDets(); // define summator AvrgDetector detSum; // do we want spherical or linear box sizes? detSum.setUseSpherical(!m_SizesAreLinear); if (nDetectors == 1) { detSum.addDetInfo(det, Observer); } else { // access contributing detectors; auto detGroup = dynamic_cast<const Geometry::DetectorGroup *>(&det); if (!detGroup) { g_log.error() << "calc_cylDetPar: can not downcast IDetector_sptr to " "detector group for det->ID: " << det.getID() << '\n'; throw(std::bad_cast()); } for (const auto &det : detGroup->getDetectors()) { detSum.addDetInfo(*det, Observer); } } // calculate averages and return the detector parameters detSum.returnAvrgDetPar(Detector); }
/** * Return the efixed for this detector. In Direct mode this has to be property set up earlier and in Indirect mode it may be the property of a component if not specified globally for the instrument. * @param det A pointer to a detector object * @return The value of efixed */ double SofQCommon::getEFixed(const Geometry::IDetector &det) const { double efixed(0.0); if (m_emode == 1) // Direct { efixed = m_efixed; } else // Indirect { if (m_efixedGiven) efixed = m_efixed; // user provided a value else { const std::vector<double> param = det.getNumberParameter("EFixed"); if (param.empty()) throw std::runtime_error( "Cannot find EFixed parameter for component \"" + det.getName() + "\". This is required in indirect mode. Please check the IDF " "contains these values."); efixed = param[0]; } } return efixed; }
/** method to cacluate the detectors parameters and add them to the detectors *averages *@param det -- reference to the Mantid Detector *@param Observer -- sample position or the centre of the polar system of *coordinates to calculate detector's parameters. */ void AvrgDetector::addDetInfo(const Geometry::IDetector &det, const Kernel::V3D &Observer) { m_nComponents++; Kernel::V3D detPos = det.getPos(); Kernel::V3D toDet = (detPos - Observer); double dist2Det, Polar, Azimut, ringPolar, ringAzim; // identify the detector' position in the beam coordinate system: toDet.getSpherical(dist2Det, Polar, Azimut); if (m_nComponents <= 1) { m_FlightPathSum = dist2Det; m_PolarSum = Polar; m_AzimutSum = Azimut; m_AzimBase = Polar; m_PolarBase = Azimut; ringPolar = Polar; ringAzim = Azimut; } else { ringPolar = nearAngle(m_AzimBase, Polar); ringAzim = nearAngle(m_PolarBase, Azimut); m_FlightPathSum += dist2Det; m_PolarSum += ringPolar; m_AzimutSum += ringAzim; } // centre of the azimuthal ring (the ring detectors form around the beam) Kernel::V3D ringCentre(0, 0, toDet.Z()); // Get the bounding box Geometry::BoundingBox bbox; std::vector<Kernel::V3D> coord(3); // ez along beamline, which is always oz; Kernel::V3D er(0, 1, 0), ez(0, 0, 1); if (dist2Det != 0.0) er = toDet / dist2Det; // direction to the detector // tangential to the ring and anticlockwise. Kernel::V3D e_tg = er.cross_prod(ez); if (e_tg.nullVector(1e-12)) { e_tg = V3D(1., 0., 0.); } else { e_tg.normalize(); } // make orthogonal -- projections are calculated in this coordinate system ez = e_tg.cross_prod(er); coord[0] = er; // new X coord[1] = ez; // new y coord[2] = e_tg; // new z bbox.setBoxAlignment(ringCentre, coord); det.getBoundingBox(bbox); // linear extensions of the bounding box orientied tangentially to the equal // scattering angle circle double azimMin = bbox.zMin(); double azimMax = bbox.zMax(); double polarMin = bbox.yMin(); // bounding box has been rotated according to // coord above, so z is along e_tg double polarMax = bbox.yMax(); if (m_useSphericalSizes) { if (dist2Det == 0) dist2Det = 1; // convert to angular units double polarHalfSize = rad2deg * atan2(0.5 * (polarMax - polarMin), dist2Det); double azimHalfSize = rad2deg * atan2(0.5 * (azimMax - azimMin), dist2Det); polarMin = ringPolar - polarHalfSize; polarMax = ringPolar + polarHalfSize; azimMin = ringAzim - azimHalfSize; azimMax = ringAzim + azimHalfSize; } if (m_AzimMin > azimMin) m_AzimMin = azimMin; if (m_AzimMax < azimMax) m_AzimMax = azimMax; if (m_PolarMin > polarMin) m_PolarMin = polarMin; if (m_PolarMax < polarMax) m_PolarMax = polarMax; }