예제 #1
0
/**
 * 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;
    }
예제 #2
0
/** 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);
}
예제 #3
0
/**
 * 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;
}
예제 #4
0
/** 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;
}