예제 #1
0
파일: RadiusSum.cpp 프로젝트: mcvine/mantid
double RadiusSum::getMinBinSizeForInstrument(API::MatrixWorkspace_sptr inWS) {
  // Assumption made: the detectors are placed one after the other, so the
  // minimum
  // reasonalbe size for the bin is the width of one detector.

  double width;
  size_t i = 0;
  while (true) {
    i++;

    // this should never happen because it was done in
    // getBoundariesOfInstrument,
    // but it is here to avoid risk of infiniti loop
    if (i >= inWS->getNumberHistograms())
      throw std::invalid_argument(
          "Did not find any non monitor detector position");

    auto det = inWS->getDetector(i);
    if (det->isMonitor())
      continue;

    Geometry::BoundingBox bbox;
    det->getBoundingBox(bbox);

    width = bbox.width().norm();
    break;
  }

  return width;
}
예제 #2
0
/**
 * Generate a random point on the profile that is within the given bounding
 * area. If the point is outside the area then it is pulled to the boundary of
 * the bounding area.
 * @param rng A reference to a random number generator
 * @param bounds A reference to the bounding area that defines the maximum
 * allowed region for the generated point.
 * @return An IBeamProfile::Ray describing the start and direction
 */
IBeamProfile::Ray RectangularBeamProfile::generatePoint(
    Kernel::PseudoRandomNumberGenerator &rng,
    const Geometry::BoundingBox &bounds) const {
  auto rngRay = generatePoint(rng);
  auto &rngPt = rngRay.startPos;
  const V3D minBound(bounds.minPoint()), maxBound(bounds.maxPoint());
  if (rngPt[m_upIdx] > maxBound[m_upIdx])
    rngPt[m_upIdx] = maxBound[m_upIdx];
  else if (rngPt[m_upIdx] < minBound[m_upIdx])
    rngPt[m_upIdx] = minBound[m_upIdx];

  if (rngPt[m_horIdx] > maxBound[m_horIdx])
    rngPt[m_horIdx] = maxBound[m_horIdx];
  else if (rngPt[m_horIdx] < minBound[m_horIdx])
    rngPt[m_horIdx] = minBound[m_horIdx];
  return rngRay;
}
예제 #3
0
//! is the object visible?
bool geometry::Camera::visible(const geometry::BoundingBox &bounds, 
	const math::matrix4x4<float> &viewTransform) const {

	// perform test in view coordinates rather than word or screen space		
	const int N = 8;
	int idx = 0;
	math::matrix4x1<float> points[N];

	float w = bounds.width(), h = bounds.height(), d = bounds.depth();

	points[0] = math::matrix4x1<float>(bounds.minimum, 1);
	points[++idx] = points[0] + math::matrix4x1<float>(w, 0, 0, 0);
	points[++idx] = points[0] + math::matrix4x1<float>(0, 0, d, 0);
	points[++idx] = points[0] + math::matrix4x1<float>(w, 0, d, 0);
	points[++idx] = points[0] + math::matrix4x1<float>(0, h, 0, 0);
	points[++idx] = points[0] + math::matrix4x1<float>(w, h, 0, 0);
	points[++idx] = points[0] + math::matrix4x1<float>(0, h, d, 0);
	points[++idx] = points[0] + math::matrix4x1<float>(w, h, d, 0);

	math::matrix3x1<float> normals[5];
	float fovH = this->fovH();
	float fovV = this->fovV();
	normals[0] = math::matrix3x1<float>(std::sin(fovH/2.0f), 0, std::cos(fovH/2.0f));
	normals[1] = math::matrix3x1<float>(-std::sin(fovH/2.0f), 0, std::cos(fovH/2.0f));
	normals[2] = math::matrix3x1<float>(0, std::sin(fovV/2.0f), std::cos(fovV/2.0f));
	normals[3] = math::matrix3x1<float>(0, -std::sin(fovV/2.0f), std::cos(fovV/2.0f));
	normals[4] = math::matrix3x1<float>(0, 0, 1);

	bool allNegative[5] = { true };

	for (int i = 0; i < N; i++) {
		points[i] = viewTransform * points[i];
		for (int n = 0; n < 5 && allNegative[n]; n++) {
			if (points[i].dot(normals[n]) > 0) {
				allNegative[n] = false;
			}
		}
	}
	bool invisible = false;
	for (int n = 0; n < 5; n++) {
		invisible = invisible | allNegative[n];
	}
	return !invisible;
}
예제 #4
0
/** method to cacluate the detectors parameters and add them to the detectors
*averages
*@param spDet    -- shared pointer 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_const_sptr &spDet,
                              const Kernel::V3D &Observer) {
  m_nComponents++;
  Kernel::V3D detPos = spDet->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);

  Kernel::V3D er(0, 1, 0), e_th,
      ez(0, 0, 1); // ez along beamline, which is always oz;
  if (dist2Det)
    er = toDet / dist2Det; // direction to the detector
  Kernel::V3D e_tg =
      er.cross_prod(ez); // tangential to the ring and anticloakwise;
  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);

  spDet->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;
}
/**
 * Cache frequently accessed values
 * @param instrument : The instrument for this run
 * @param detID : The det ID for this observation
 */
void CachedExperimentInfo::initCaches(
    const Geometry::Instrument_const_sptr &instrument, const detid_t detID) {
  // Throws if detector does not exist
  // Takes into account possible detector mapping
  IDetector_const_sptr det = m_exptInfo.getDetectorByID(detID);

  // Instrument distances
  boost::shared_ptr<const ReferenceFrame> refFrame =
      instrument->getReferenceFrame();
  m_beam = refFrame->pointingAlongBeam();
  m_up = refFrame->pointingUp();
  m_horiz = refFrame->pointingHorizontal();

  IComponent_const_sptr source = instrument->getSource();
  IComponent_const_sptr sample = instrument->getSample();
  IComponent_const_sptr aperture =
      instrument->getComponentByName("aperture", 1);
  if (!aperture) {
    throw std::invalid_argument(
        "No component named \"aperture\" found in instrument.");
  }
  IObjComponent_const_sptr firstChopper = instrument->getChopperPoint(0);
  const Kernel::V3D samplePos = sample->getPos();
  const Kernel::V3D beamDir = samplePos - source->getPos();

  // Cache
  m_twoTheta = det->getTwoTheta(samplePos, beamDir);
  m_phi = det->getPhi();
  m_modToChop = firstChopper->getDistance(*source);
  m_apertureToChop = firstChopper->getDistance(*aperture);
  m_chopToSample = sample->getDistance(*firstChopper);
  m_sampleToDet = det->getDistance(*sample);

  // Aperture
  Geometry::BoundingBox apertureBox;
  aperture->getBoundingBox(apertureBox);
  if (apertureBox.isNull()) {
    throw std::invalid_argument("CachedExperimentInfo::initCaches - Aperture "
                                "has no bounding box, cannot sample from it");
  }
  m_apertureSize.first = apertureBox.maxPoint()[0] - apertureBox.minPoint()[0];
  m_apertureSize.second = apertureBox.maxPoint()[1] - apertureBox.minPoint()[1];

  // Sample volume
  const API::Sample &sampleDescription = m_exptInfo.sample();
  const Geometry::Object &shape = sampleDescription.getShape();
  m_sampleWidths = shape.getBoundingBox().width();

  // Detector volume
  // Make sure it encompasses all possible detectors
  det->getBoundingBox(m_detBox);
  if (m_detBox.isNull()) {
    throw std::invalid_argument("CachedExperimentInfo::initCaches - Detector "
                                "has no bounding box, cannot sample from it. "
                                "ID:" +
                                boost::lexical_cast<std::string>(det->getID()));
  }

  const double rad2deg = 180. / M_PI;
  const double thetaInDegs = twoTheta() * rad2deg;
  const double phiInDegs = phi() * rad2deg;

  m_gonimeter = new Goniometer;
  m_gonimeter->makeUniversalGoniometer();
  m_gonimeter->setRotationAngle("phi", thetaInDegs);
  m_gonimeter->setRotationAngle("chi", phiInDegs);
  m_sampleToDetMatrix =
      m_exptInfo.sample().getOrientedLattice().getU() * m_gonimeter->getR();

  // EFixed
  m_efixed = m_exptInfo.getEFixed(det);
}
/** Loads the instrument into a workspace.
 */
void VesuvioL1ThetaResolution::calculateDetector(
    const IDetector &detector, std::function<double()> &flatRandomVariateGen,
    std::vector<double> &l1Values, std::vector<double> &thetaValues) {
  const int numEvents = getProperty("NumEvents");
  l1Values.reserve(numEvents);
  thetaValues.reserve(numEvents);

  double sampleWidth = getProperty("SampleWidth");
  // If the sample is large fix the width to the approximate beam width
  if (sampleWidth > 4.0)
    sampleWidth = 4.0;

  // Get detector dimensions
  Geometry::IObject_const_sptr pixelShape = detector.shape();
  if (!pixelShape || !pixelShape->hasValidShape()) {
    throw std::invalid_argument("Detector pixel has no defined shape!");
  }
  Geometry::BoundingBox detBounds = pixelShape->getBoundingBox();
  V3D detBoxWidth = detBounds.width();
  const double detWidth = detBoxWidth.X() * 100;
  const double detHeight = detBoxWidth.Y() * 100;

  g_log.debug() << "detWidth=" << detWidth << "\ndetHeight=" << detHeight
                << '\n';

  // Scattering angle in rad
  const double theta = m_instWorkspace->detectorTwoTheta(detector);
  if (theta == 0.0)
    return;

  // Final flight path in cm
  const double l1av = detector.getDistance(*m_sample) * 100.0;

  const double x0 = l1av * sin(theta);
  const double y0 = l1av * cos(theta);

  // Get as many events as defined by NumEvents
  // This loop is not iteration limited but highly unlikely to ever become
  // infinate
  while (l1Values.size() < static_cast<size_t>(numEvents)) {
    const double xs = -sampleWidth / 2 + sampleWidth * flatRandomVariateGen();
    const double ys = 0.0;
    const double zs = -sampleWidth / 2 + sampleWidth * flatRandomVariateGen();
    const double rs = sqrt(pow(xs, 2) + pow(zs, 2));

    if (rs <= sampleWidth / 2) {
      const double a = -detWidth / 2 + detWidth * flatRandomVariateGen();
      const double xd = x0 - a * cos(theta);
      const double yd = y0 + a * sin(theta);
      const double zd = -detHeight / 2 + detHeight * flatRandomVariateGen();

      const double l1 =
          sqrt(pow(xd - xs, 2) + pow(yd - ys, 2) + pow(zd - zs, 2));
      double angle = acos(yd / l1);

      if (xd < 0.0)
        angle *= -1;

      // Convert angle to degrees
      angle *= 180.0 / M_PI;

      l1Values.push_back(l1);
      thetaValues.push_back(angle);
    }

    interruption_point();
  }
}