/// Uniform distribution inline glm::vec3 getHemispherical(const glm::vec3& n) { auto r = getSpherical(); if(glm::dot(r, n) < 0.0) r = -r; return r; }
/** * A map detector ID and Q ranges * This method looks unnecessary as it could be calculated on the fly but * the parallelization means that lazy instantation slows it down due to the * necessary CRITICAL sections required to update the cache. The Q range * values are required very frequently so the total time is more than * offset by this precaching step */ DetectorAngularCache initAngularCaches(const MatrixWorkspace *const workspace) { const size_t nhist = workspace->getNumberHistograms(); std::vector<double> thetas(nhist); std::vector<double> thetaWidths(nhist); std::vector<double> detectorHeights(nhist); auto inst = workspace->getInstrument(); const auto samplePos = inst->getSample()->getPos(); const V3D upDirVec = inst->getReferenceFrame()->vecPointingUp(); for (size_t i = 0; i < nhist; ++i) // signed for OpenMP { IDetector_const_sptr det; try { det = workspace->getDetector(i); } catch (Exception::NotFoundError &) { // Catch if no detector. Next line tests whether this happened - test // placed // outside here because Mac Intel compiler doesn't like 'continue' in a // catch // in an openmp block. } // If no detector found, skip onto the next spectrum if (!det || det->isMonitor()) { thetas[i] = -1.0; // Indicates a detector to skip thetaWidths[i] = -1.0; continue; } // We have to convert theta from radians to degrees const double theta = workspace->detectorSignedTwoTheta(*det) * rad2deg; thetas[i] = theta; /** * Determine width from shape geometry. A group is assumed to contain * detectors with the same shape & r, theta value, i.e. a ring mapped-group * The shape is retrieved and rotated to match the rotation of the detector. * The angular width is computed using the l2 distance from the sample */ if (auto group = boost::dynamic_pointer_cast<const DetectorGroup>(det)) { // assume they all have same shape and same r,theta auto dets = group->getDetectors(); det = dets[0]; } const auto pos = det->getPos() - samplePos; double l2(0.0), t(0.0), p(0.0); pos.getSpherical(l2, t, p); // Get the shape auto shape = det->shape(); // Defined in its own reference frame with centre at 0,0,0 BoundingBox bbox = shape->getBoundingBox(); auto maxPoint(bbox.maxPoint()); auto minPoint(bbox.minPoint()); auto span = maxPoint - minPoint; detectorHeights[i] = span.scalar_prod(upDirVec); thetaWidths[i] = 2.0 * std::fabs(std::atan((detectorHeights[i] / 2) / l2)) * 180.0 / M_PI; } DetectorAngularCache cache; cache.thetas = thetas; cache.thetaWidths = thetaWidths; cache.detectorHeights = detectorHeights; return cache; }