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; }
/** * 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; }
//! 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; }
/** 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(); } }