/** Convenience method for checking whether or not a vector is aligned with the along beam vector. @param v vector to be tested against along beam vector @return result of whther the along beam and test vector are parallel. */ bool ReferenceFrame::isVectorPointingAlongBeam(const V3D &v) const { V3D vec = v; vec.normalize(); // Normalized (unit) parallel vectors should produce a scalar product of 1 return m_vecPointingAlongBeam.scalar_prod(vec) == 1; }
void CacheGeometryRenderer::Initialize(int noPts, int noFaces, double* points, int* faces)const { (void) noPts; //Avoid compiler warning if (!boolDisplaylistCreated || glIsList(iDisplaylistId) == GL_FALSE) { iDisplaylistId = glGenLists(1); glNewList(iDisplaylistId, GL_COMPILE); //Construct display list for object representation glBegin(GL_TRIANGLES); int index1, index2, index3; V3D normal; for (int i = 0; i < noFaces; i++) { index1 = faces[i * 3] * 3; index2 = faces[i * 3 + 1] * 3; index3 = faces[i * 3 + 2] * 3; //Calculate normal and normalize V3D v1(points[index1], points[index1 + 1], points[index1 + 2]); V3D v2(points[index2], points[index2 + 1], points[index2 + 2]); V3D v3(points[index3], points[index3 + 1], points[index3 + 2]); normal = (v1 - v2).cross_prod(v2 - v3); normal.normalize(); glNormal3d(normal[0], normal[1], normal[2]); glVertex3dv(points + index1); glVertex3dv(points + index2); glVertex3dv(points + index3); } glEnd(); glEndList(); boolDisplaylistCreated = true; } }
MLPTesting(): c_(&camera_){ static_assert(imgSize_*dx_*dy_<255,"imgSize to large for gradients"); pixel_ = cv::Point2f(patchSize_/2+1,patchSize_/2+1); bearing_ = V3D(patchSize_/2+1,patchSize_/2+1,1); bearing_.normalize(); c_.set_c(pixel_); warp_c_ << 0.1, 0.5, 0.7, -0.2; c_.set_warp_c(warp_c_); warp_nor_ = c_.get_warp_nor(); stat_.localQualityRange_ = 3; stat_.localVisibilityRange_ = 4; stat_.minGlobalQualityRange_ = 5; img1_ = cv::Mat::zeros(imgSize_,imgSize_,CV_8UC1); uint8_t* img_ptr = (uint8_t*) img1_.data; for(int i=0;i<imgSize_;i++){ for(int j=0;j<imgSize_;j++, ++img_ptr){ *img_ptr = i*dy_+j*dx_; } } img2_ = cv::Mat::zeros(imgSize_,imgSize_,CV_8UC1); img_ptr = (uint8_t*) img2_.data; for(int i=0;i<imgSize_;i++){ for(int j=0;j<imgSize_;j++, ++img_ptr){ if(j<imgSize_/2 & i<imgSize_/2){ *img_ptr = 0; } else { *img_ptr = 255; } } } pyr1_.computeFromImage(img1_); pyr2_.computeFromImage(img2_); }
bool lineIntersectsSphere(const V3D &line, const V3D &lineStart, const V3D &peakCenter, const double peakRadius) { V3D peakToStart = peakCenter - lineStart; V3D unitLine = line; unitLine.normalize(); double proj = peakToStart.scalar_prod(unitLine); // All we are doing here is // projecting the peak to // segment start vector onto // the segment itself. V3D closestPointOnSegment; if (proj <= 0) // The projection is outside the segment. So use the start // point of the segment. { closestPointOnSegment = lineStart; // Start of line } else if (proj >= line.norm()) // The projection is greater than the segment // length. So use the end point of the // segment. { closestPointOnSegment = lineStart + line; // End of line. } else // The projection falls somewhere between the start and end of the line // segment. { V3D projectionVector = unitLine * proj; closestPointOnSegment = projectionVector + lineStart; } return (peakCenter - closestPointOnSegment).norm() <= peakRadius; }
/** * Creates a Cube * @param Point1 :: first point of the cube * @param Point2 :: second point of the cube * @param Point3 :: thrid point of the cube * @param Point4 :: fourth point of the cube */ void GluGeometryRenderer::CreateCube(const V3D &Point1, const V3D &Point2, const V3D &Point3, const V3D &Point4) { V3D vec0 = Point1; V3D vec1 = Point2 - Point1; V3D vec2 = Point3 - Point1; V3D vec3 = Point4 - Point1; V3D vertex[8]; vertex[0] = vec0; vertex[1] = vec0 + vec3; vertex[2] = vec0 + vec3 + vec1; vertex[3] = vec0 + vec1; vertex[4] = vec0 + vec2; vertex[5] = vec0 + vec2 + vec3; vertex[6] = vec0 + vec2 + vec3 + vec1; vertex[7] = vec0 + vec1 + vec2; // int // faceindex[6][4]={{0,1,2,3},{0,3,7,4},{3,2,6,7},{2,1,5,6},{0,4,5,1},{4,7,6,5}}; // int // faceindex[6][4]={{0,3,2,1},{0,4,7,3},{3,7,6,2},{2,6,5,1},{0,1,5,4},{4,5,6,7}}; int faceindex[6][4] = { {0, 1, 2, 3}, // top {0, 3, 7, 4}, // left {3, 2, 6, 7}, // back {2, 1, 5, 6}, // right {0, 4, 5, 1}, // front {4, 7, 6, 5}, // bottom }; V3D normal; // first face glBegin(GL_QUADS); for (auto &row : faceindex) { normal = (vertex[row[0]] - vertex[row[1]]) .cross_prod((vertex[row[0]] - vertex[row[2]])); normal.normalize(); glNormal3d(normal[0], normal[1], normal[2]); for (int j = 0; j < 4; j++) { int ij = row[j]; if (ij == 0) glTexCoord2i(0, 0); if (ij == 1) glTexCoord2i(1, 0); if (ij == 2) glTexCoord2i(1, 1); if (ij == 3) glTexCoord2i(0, 1); if (ij == 4) glTexCoord2i(0, 0); if (ij == 5) glTexCoord2i(1, 0); if (ij == 6) glTexCoord2i(1, 1); if (ij == 7) glTexCoord2i(0, 1); glVertex3d(vertex[ij][0], vertex[ij][1], vertex[ij][2]); } } glEnd(); }
/** * Calculate the attenuation correction factor the volume given a start and * end point. * @param rng A reference to a PseudoRandomNumberGenerator producing * random number between [0,1] * @param startPos Origin of the initial track * @param endPos Final position of neutron after scattering (assumed to be * outside of the "volume") * @param lambdaBefore Wavelength, in \f$\\A^-1\f$, before scattering * @param lambdaAfter Wavelength, in \f$\\A^-1\f$, after scattering * @return The fraction of the beam that has been attenuated. A negative number * indicates the track was not valid. */ double MCInteractionVolume::calculateAbsorption( Kernel::PseudoRandomNumberGenerator &rng, const Kernel::V3D &startPos, const Kernel::V3D &endPos, double lambdaBefore, double lambdaAfter) const { // Generate scatter point. If there is an environment present then // first select whether the scattering occurs on the sample or the // environment. The attenuation for the path leading to the scatter point // is calculated in reverse, i.e. defining the track from the scatter pt // backwards for simplicity with how the Track object works. This avoids // having to understand exactly which object the scattering occurred in. V3D scatterPos; if (m_env && (rng.nextValue() > 0.5)) { scatterPos = m_env->generatePoint(rng, m_activeRegion, MAX_SCATTER_ATTEMPTS); } else { scatterPos = m_sample.generatePointInObject(rng, m_activeRegion, MAX_SCATTER_ATTEMPTS); } auto toStart = startPos - scatterPos; toStart.normalize(); Track beforeScatter(scatterPos, toStart); int nlinks = m_sample.interceptSurface(beforeScatter); if (m_env) { nlinks += m_env->interceptSurfaces(beforeScatter); } // This should not happen but numerical precision means that it can // occasionally occur with tracks that are very close to the surface if (nlinks == 0) { return -1.0; } // Function to calculate total attenuation for a track auto calculateAttenuation = [](const Track &path, double lambda) { double factor(1.0); for (const auto &segment : path) { const double length = segment.distInsideObject; const auto &segObj = *(segment.object); const auto &segMat = segObj.material(); factor *= attenuation(segMat.numberDensity(), segMat.totalScatterXSection(lambda) + segMat.absorbXSection(lambda), length); } return factor; }; // Now track to final destination V3D scatteredDirec = endPos - scatterPos; scatteredDirec.normalize(); Track afterScatter(scatterPos, scatteredDirec); m_sample.interceptSurface(afterScatter); if (m_env) { m_env->interceptSurfaces(afterScatter); } return calculateAttenuation(beforeScatter, lambdaBefore) * calculateAttenuation(afterScatter, lambdaAfter); }
/// Calculate the distances traversed by the neutrons within the sample /// @param detector :: The detector we are working on /// @param L2s :: A vector of the sample-detector distance for each segment of /// the sample void AbsorptionCorrection::calculateDistances(const IDetector &detector, std::vector<double> &L2s) const { V3D detectorPos(detector.getPos()); if (detector.nDets() > 1) { // We need to make sure this is right for grouped detectors - should use // average theta & phi detectorPos.spherical(detectorPos.norm(), detector.getTwoTheta(V3D(), V3D(0, 0, 1)) * 180.0 / M_PI, detector.getPhi() * 180.0 / M_PI); } for (size_t i = 0; i < m_numVolumeElements; ++i) { // Create track for distance in cylinder between scattering point and // detector V3D direction = detectorPos - m_elementPositions[i]; direction.normalize(); Track outgoing(m_elementPositions[i], direction); int temp = m_sampleObject->interceptSurface(outgoing); /* Most of the time, the number of hits is 1. Sometime, we have more than * one intersection due to * arithmetic imprecision. If it is the case, then selecting the first * intersection is valid. * In principle, one could check the consistency of all distances if hits is * larger than one by doing: * Mantid::Geometry::Track::LType::const_iterator it=outgoing.begin(); * and looping until outgoing.end() checking the distances with it->Dist */ // Not hitting the cylinder from inside, usually means detector is badly // defined, // i.e, position is (0,0,0). if (temp < 1) { // FOR NOW AT LEAST, JUST IGNORE THIS ERROR AND USE A ZERO PATH LENGTH, // WHICH I RECKON WILL MAKE A // NEGLIGIBLE DIFFERENCE ANYWAY (ALWAYS SEEMS TO HAPPEN WITH ELEMENT RIGHT // AT EDGE OF SAMPLE) L2s[i] = 0.0; // std::ostringstream message; // message << "Problem with detector at " << detectorPos << " ID:" << // detector->getID() << '\n'; // message << "This usually means that this detector is defined inside the // sample cylinder"; // g_log.error(message.str()); // throw std::runtime_error("Problem in // AbsorptionCorrection::calculateDistances"); } else // The normal situation { L2s[i] = outgoing.cbegin()->distFromStart; } } }
/** Set the U rotation matrix, to provide the transformation, which translate *an * arbitrary vector V expressed in RLU (hkl) * into another coordinate system defined by vectors u and v, expressed in RLU *(hkl) * Author: Alex Buts * @param u :: first vector of new coordinate system (in hkl units) * @param v :: second vector of the new coordinate system * @return the U matrix calculated * The transformation from old coordinate system to new coordinate system is *performed by * the whole UB matrix **/ const DblMatrix &OrientedLattice::setUFromVectors(const V3D &u, const V3D &v) { const DblMatrix &BMatrix = this->getB(); V3D buVec = BMatrix * u; V3D bvVec = BMatrix * v; // try to make an orthonormal system if (buVec.norm2() < 1e-10) throw std::invalid_argument("|B.u|~0"); if (bvVec.norm2() < 1e-10) throw std::invalid_argument("|B.v|~0"); buVec.normalize(); // 1st unit vector, along Bu V3D bwVec = buVec.cross_prod(bvVec); if (bwVec.normalize() < 1e-5) throw std::invalid_argument( "u and v are parallel"); // 3rd unit vector, perpendicular to Bu,Bv bvVec = bwVec.cross_prod( buVec); // 2nd unit vector, perpendicular to Bu, in the Bu,Bv plane DblMatrix tau(3, 3), lab(3, 3), U(3, 3); /*lab = U tau / 0 1 0 \ /bu[0] bv[0] bw[0]\ | 0 0 1 | = U |bu[1] bv[1] bw[1]| \ 1 0 0 / \bu[2] bv[2] bw[2]/ */ lab[0][1] = 1.; lab[1][2] = 1.; lab[2][0] = 1.; tau[0][0] = buVec[0]; tau[0][1] = bvVec[0]; tau[0][2] = bwVec[0]; tau[1][0] = buVec[1]; tau[1][1] = bvVec[1]; tau[1][2] = bwVec[1]; tau[2][0] = buVec[2]; tau[2][1] = bvVec[2]; tau[2][2] = bwVec[2]; tau.Invert(); U = lab * tau; this->setU(U); return getU(); }
/** * Generate a random position within the final detector in the lab frame * @param nominalPos The poisiton of the centre point of the detector * @param energy The final energy of the neutron * @param scatterPt The position of the scatter event that lead to this * detector * @param direcBeforeSc Directional vector that lead to scatter point that hit * this detector * @param scang [Output] The value of the scattering angle for the generated * point * @param distToExit [Output] The distance covered within the object from * scatter to exit * @return A new position in the detector */ V3D VesuvioCalculateMS::generateDetectorPos( const V3D &nominalPos, const double energy, const V3D &scatterPt, const V3D &direcBeforeSc, double &scang, double &distToExit) const { // Inverse attenuation length (m-1) for vesuvio det. const double mu = 7430.0 / sqrt(energy); // Probability of detection in path thickness. const double ps = 1.0 - exp(-mu * m_detThick); V3D detPos; scang = 0.0; distToExit = 0.0; size_t ntries(0); do { // Beam direction by moving to front of "box"define by detector dimensions // and then // computing expected distance travelled based on probability detPos[m_beamIdx] = (nominalPos[m_beamIdx] - 0.5 * m_detThick) - (log(1.0 - m_randgen->flat() * ps) / mu); // perturb away from nominal position detPos[m_acrossIdx] = nominalPos[m_acrossIdx] + (m_randgen->flat() - 0.5) * m_detWidth; detPos[m_upIdx] = nominalPos[m_upIdx] + (m_randgen->flat() - 0.5) * m_detHeight; // Distance to exit the sample for this order V3D scToDet = detPos - scatterPt; scToDet.normalize(); Geometry::Track scatterToDet(scatterPt, scToDet); if (m_sampleShape->interceptSurface(scatterToDet) > 0) { scang = direcBeforeSc.angle(scToDet); const auto &link = scatterToDet.cbegin(); distToExit = link->distInsideObject; break; } // if point is very close surface then there may be no valid intercept so // try again ++ntries; } while (ntries < MAX_SCATTER_PT_TRIES); if (ntries == MAX_SCATTER_PT_TRIES) { // Assume it is very close to the surface so that the distance travelled // would // be a neglible contribution distToExit = 0.0; } return detPos; }
void CacheGeometryRenderer::Initialize(int noPts, int noFaces, double *points, int *faces) const { (void)noPts; // Avoid compiler warning glBegin(GL_TRIANGLES); V3D normal; for (int i = 0; i < noFaces; i++) { int index1 = faces[i * 3] * 3; int index2 = faces[i * 3 + 1] * 3; int index3 = faces[i * 3 + 2] * 3; // Calculate normal and normalize V3D v1(points[index1], points[index1 + 1], points[index1 + 2]); V3D v2(points[index2], points[index2 + 1], points[index2 + 2]); V3D v3(points[index3], points[index3 + 1], points[index3 + 2]); normal = (v1 - v2).cross_prod(v2 - v3); normal.normalize(); glNormal3d(normal[0], normal[1], normal[2]); glVertex3dv(points + index1); glVertex3dv(points + index2); glVertex3dv(points + index3); } glEnd(); }
/** Corrects a spectra for the detector efficiency calculated from detector information Gets the detector information and uses this to calculate its efficiency * @param spectraIn :: index of the spectrum to get the efficiency for * @throw invalid_argument if the shape of a detector is isn't a cylinder aligned along one axis * @throw runtime_error if the SpectraDetectorMap has not been filled * @throw NotFoundError if the detector or its gas pressure or wall thickness were not found */ void DetectorEfficiencyCor::correctForEfficiency(int64_t spectraIn) { IDetector_const_sptr det = m_inputWS->getDetector(spectraIn); if( det->isMonitor() || det->isMasked() ) { return; } MantidVec & yout = m_outputWS->dataY(spectraIn); MantidVec & eout = m_outputWS->dataE(spectraIn); // Need the original values so this is not a reference const MantidVec yValues = m_inputWS->readY(spectraIn); const MantidVec eValues = m_inputWS->readE(spectraIn); // get a pointer to the detectors that created the spectrum const std::set<detid_t> dets = m_inputWS->getSpectrum(spectraIn)->getDetectorIDs(); std::set<detid_t>::const_iterator it = dets.begin(); std::set<detid_t>::const_iterator iend = dets.end(); if ( it == iend ) { throw Exception::NotFoundError("No detectors found", spectraIn); } // Storage for the reciprocal wave vectors that are calculated as the //correction proceeds std::vector<double> oneOverWaveVectors(yValues.size()); for( ; it != iend ; ++it ) { IDetector_const_sptr det_member = m_inputWS->getInstrument()->getDetector(*it); Parameter_sptr par = m_paraMap->get(det_member.get(),"3He(atm)"); if ( !par ) { throw Exception::NotFoundError("3He(atm)", spectraIn); } const double atms = par->value<double>(); par = m_paraMap->get(det_member.get(),"wallT(m)"); if ( !par ) { throw Exception::NotFoundError("wallT(m)", spectraIn); } const double wallThickness = par->value<double>(); double detRadius(0.0); V3D detAxis; getDetectorGeometry(det_member, detRadius, detAxis); // now get the sin of the angle, it's the magnitude of the cross product of unit vector along the detector tube axis and a unit vector directed from the sample to the detector centre V3D vectorFromSample = det_member->getPos() - m_samplePos; vectorFromSample.normalize(); Quat rot = det_member->getRotation(); // rotate the original cylinder object axis to get the detector axis in the actual instrument rot.rotate(detAxis); detAxis.normalize(); // Scalar product is quicker than cross product double cosTheta = detAxis.scalar_prod(vectorFromSample); double sinTheta = std::sqrt(1.0 - cosTheta*cosTheta); // Detector constant const double det_const = g_helium_prefactor*(detRadius - wallThickness)*atms/sinTheta; MantidVec::const_iterator yinItr = yValues.begin(); MantidVec::const_iterator einItr = eValues.begin(); MantidVec::iterator youtItr = yout.begin(); MantidVec::iterator eoutItr = eout.begin(); MantidVec::const_iterator xItr = m_inputWS->readX(spectraIn).begin(); std::vector<double>::iterator wavItr = oneOverWaveVectors.begin(); for( ; youtItr != yout.end(); ++youtItr, ++eoutItr) { if( it == dets.begin() ) { *youtItr = 0.0; *eoutItr = 0.0; *wavItr = calculateOneOverK(*xItr, *(xItr + 1 )); } const double oneOverWave = *wavItr; const double factor = 1.0/detectorEfficiency(det_const*oneOverWave); *youtItr += (*yinItr)*factor; *eoutItr += (*einItr)*factor; ++yinItr; ++einItr; ++xItr; ++wavItr; } } }
/** Execute the algorithm. */ void SaveIsawPeaks::exec() { // Section header std::string header = "2 SEQN H K L COL ROW CHAN L2 2_THETA AZ WL D IPK INTI SIGI RFLG"; std::string filename = getPropertyValue("Filename"); PeaksWorkspace_sptr ws = getProperty("InputWorkspace"); std::vector<Peak> peaks = ws->getPeaks(); // We must sort the peaks first by run, then bank #, and save the list of workspace indices of it typedef std::map<int, std::vector<size_t> > bankMap_t; typedef std::map<int, bankMap_t> runMap_t; std::set<int> uniqueBanks; runMap_t runMap; for (size_t i=0; i < peaks.size(); ++i) { Peak & p = peaks[i]; int run = p.getRunNumber(); int bank = 0; std::string bankName = p.getBankName(); if (bankName.size() <= 4) { g_log.information() << "Could not interpret bank number of peak " << i << "(" << bankName << ")\n"; continue; } // Take out the "bank" part of the bank name and convert to an int bankName = bankName.substr(4, bankName.size()-4); Strings::convert(bankName, bank); // Save in the map runMap[run][bank].push_back(i); // Track unique bank numbers uniqueBanks.insert(bank); } Instrument_const_sptr inst = ws->getInstrument(); if (!inst) throw std::runtime_error("No instrument in PeaksWorkspace. Cannot save peaks file."); double l1; V3D beamline; double beamline_norm; V3D samplePos; inst->getInstrumentParameters(l1, beamline, beamline_norm, samplePos); std::ofstream out; bool append = getProperty("AppendFile"); if (append) { out.open( filename.c_str(), std::ios::app); } else { out.open( filename.c_str()); out << "Version: 2.0 Facility: SNS " ; out << " Instrument: " << inst->getName() << " Date: " ; //TODO: The experiment date might be more useful than the instrument date. // For now, this allows the proper instrument to be loaded back after saving. Kernel::DateAndTime expDate = inst->getValidFromDate() + 1.0; out << expDate.to_ISO8601_string() << std::endl; out << "6 L1 T0_SHIFT" << std::endl; out << "7 "<< std::setw( 10 ) ; out << std::setprecision( 4 ) << std::fixed << ( l1*100 ) ; out << std::setw( 12 ) << std::setprecision( 3 ) << std::fixed ; // Time offset of 0.00 for now out << "0.000" << std::endl; // ============================== Save .detcal info ========================================= if (true) { out << "4 DETNUM NROWS NCOLS WIDTH HEIGHT DEPTH DETD CenterX CenterY CenterZ BaseX BaseY BaseZ UpX UpY UpZ" << std::endl; // Here would save each detector... std::set<int>::iterator it; for (it = uniqueBanks.begin(); it != uniqueBanks.end(); it++) { // Build up the bank name int bank = *it; std::ostringstream mess; mess << "bank" << bank; std::string bankName = mess.str(); // Retrieve it RectangularDetector_const_sptr det = boost::dynamic_pointer_cast<const RectangularDetector>(inst->getComponentByName(bankName)); if (det) { // Center of the detector V3D center = det->getPos(); // Distance to center of detector double detd = (center - inst->getSample()->getPos()).norm(); // Base unit vector (along the horizontal, X axis) V3D base = det->getAtXY(det->xpixels()-1,0)->getPos() - det->getAtXY(0,0)->getPos(); base.normalize(); // Up unit vector (along the vertical, Y axis) V3D up = det->getAtXY(0,det->ypixels()-1)->getPos() - det->getAtXY(0,0)->getPos(); up.normalize(); // Write the line out << "5 " << std::setw(6) << std::right << bank << " " << std::setw(6) << std::right << det->xpixels() << " " << std::setw(6) << std::right << det->ypixels() << " " << std::setw(7) << std::right << std::fixed << std::setprecision(4) << 100.0*det->xsize() << " " << std::setw(7) << std::right << std::fixed << std::setprecision(4) << 100.0*det->ysize() << " " << " 0.2000 " << std::setw(6) << std::right << std::fixed << std::setprecision(2) << 100.0*detd << " " << std::setw(9) << std::right << std::fixed << std::setprecision(4) << 100.0*center.X() << " " << std::setw(9) << std::right << std::fixed << std::setprecision(4) << 100.0*center.Y() << " " << std::setw(9) << std::right << std::fixed << std::setprecision(4) << 100.0*center.Z() << " " << std::setw(8) << std::right << std::fixed << std::setprecision(5) << base.X() << " " << std::setw(8) << std::right << std::fixed << std::setprecision(5) << base.Y() << " " << std::setw(8) << std::right << std::fixed << std::setprecision(5) << base.Z() << " " << std::setw(8) << std::right << std::fixed << std::setprecision(5) << up.X() << " " << std::setw(8) << std::right << std::fixed << std::setprecision(5) << up.Y() << " " << std::setw(8) << std::right << std::fixed << std::setprecision(5) << up.Z() << " " << std::endl; } } } } // ============================== Save all Peaks ========================================= // Sequence number int seqNum = 1; // Go in order of run numbers runMap_t::iterator runMap_it; for (runMap_it = runMap.begin(); runMap_it != runMap.end(); runMap_it++) { // Start of a new run int run = runMap_it->first; bankMap_t & bankMap = runMap_it->second; bankMap_t::iterator bankMap_it; for (bankMap_it = bankMap.begin(); bankMap_it != bankMap.end(); bankMap_it++) { // Start of a new bank. int bank = bankMap_it->first; std::vector<size_t> & ids = bankMap_it->second; if (ids.size() > 0) { // Write the bank header out << "0 NRUN DETNUM CHI PHI OMEGA MONCNT" << std::endl; out << "1" << std::setw( 5 ) << run << std::setw( 7 ) << std::right << bank; // Determine goniometer angles by calculating from the goniometer matrix of a peak in the list Goniometer gon(peaks[ids[0]].getGoniometerMatrix()); std::vector<double> angles = gon.getEulerAngles("yzy"); double phi = angles[2]; double chi = angles[1]; double omega = angles[0]; out << std::setw( 7 ) << std::fixed << std::setprecision( 2 ) << chi << " "; out << std::setw( 7 ) << std::fixed << std::setprecision( 2 ) << phi << " "; out << std::setw( 7 ) << std::fixed << std::setprecision( 2 ) << omega << " "; out << std::setw( 7 ) << (int)( 0 ) << std::endl; out << header << std::endl; // Go through each peak at this run / bank for (size_t i=0; i < ids.size(); i++) { size_t wi = ids[i]; Peak & p = peaks[wi]; // Sequence (run) number out << "3" << std::setw( 7 ) << seqNum; // HKL is flipped by -1 due to different q convention in ISAW vs mantid. out << std::setw( 5 ) << Utils::round(-p.getH()) << std::setw( 5 ) << Utils::round(-p.getK()) << std::setw( 5 ) << Utils::round(-p.getL()); // Row/column out << std::setw( 8 ) << std::fixed << std::setprecision( 2 ) << static_cast<double>(p.getCol()) << " "; out << std::setw( 8 ) << std::fixed << std::setprecision( 2 ) << static_cast<double>(p.getRow()) << " "; out << std::setw( 8 ) << std::fixed << std::setprecision( 0 ) << p.getTOF() << " "; out << std::setw( 9 ) << std::fixed << std::setprecision( 3 ) << (p.getL2()*100.0) << " "; // This is the scattered beam direction V3D dir = p.getDetPos() - inst->getSample()->getPos(); double scattering, azimuth; // Two-theta = polar angle = scattering angle = between +Z vector and the scattered beam scattering = dir.angle( V3D(0.0, 0.0, 1.0) ); // "Azimuthal" angle: project the beam onto the XY plane, and measure the angle between that and the +X axis (right-handed) azimuth = atan2( dir.Y(), dir.X() ); out << std::setw( 9 ) << std::fixed << std::setprecision( 5 ) << scattering << " "; //two-theta scattering out << std::setw( 9 ) << std::fixed << std::setprecision( 5 ) << azimuth << " "; out << std::setw( 10 ) << std::fixed << std::setprecision( 6 ) << p.getWavelength() << " "; out << std::setw( 9 ) << std::fixed << std::setprecision( 4 ) << p.getDSpacing() << " "; out << std::setw( 8 ) << std::fixed << int(p.getBinCount()) << std::setw( 10 ) << " " << std::fixed << std::setprecision( 2 ) << p.getIntensity() << " "; out << std::setw( 7 ) << std::fixed << std::setprecision( 2 ) << p.getSigmaIntensity() << " "; int thisReflag = 310; out << std::setw( 5 ) << thisReflag; out << std::endl; // Count the sequence seqNum++; } } } } out.flush(); out.close(); // //REMOVE: // std::string line; // std::ifstream myfile (filename.c_str()); // if (myfile.is_open()) // { // while ( myfile.good() ) // { // getline (myfile,line); // std::cout << line << std::endl; // } // myfile.close(); // } }
void SofQWCentre::exec() { using namespace Geometry; MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace"); // Do the full check for common binning if (!WorkspaceHelpers::commonBoundaries(*inputWorkspace)) { g_log.error( "The input workspace must have common binning across all spectra"); throw std::invalid_argument( "The input workspace must have common binning across all spectra"); } std::vector<double> verticalAxis; MatrixWorkspace_sptr outputWorkspace = setUpOutputWorkspace( inputWorkspace, getProperty("QAxisBinning"), verticalAxis); setProperty("OutputWorkspace", outputWorkspace); // Holds the spectrum-detector mapping std::vector<specnum_t> specNumberMapping; std::vector<detid_t> detIDMapping; m_EmodeProperties.initCachedValues(*inputWorkspace, this); int emode = m_EmodeProperties.m_emode; // Get a pointer to the instrument contained in the workspace Instrument_const_sptr instrument = inputWorkspace->getInstrument(); // Get the distance between the source and the sample (assume in metres) IComponent_const_sptr source = instrument->getSource(); IComponent_const_sptr sample = instrument->getSample(); V3D beamDir = sample->getPos() - source->getPos(); beamDir.normalize(); try { double l1 = source->getDistance(*sample); g_log.debug() << "Source-sample distance: " << l1 << '\n'; } catch (Exception::NotFoundError &) { g_log.error("Unable to calculate source-sample distance"); throw Exception::InstrumentDefinitionError( "Unable to calculate source-sample distance", inputWorkspace->getTitle()); } // Conversion constant for E->k. k(A^-1) = sqrt(energyToK*E(meV)) const double energyToK = 8.0 * M_PI * M_PI * PhysicalConstants::NeutronMass * PhysicalConstants::meV * 1e-20 / (PhysicalConstants::h * PhysicalConstants::h); // Loop over input workspace bins, reassigning data to correct bin in output // qw workspace const size_t numHists = inputWorkspace->getNumberHistograms(); const size_t numBins = inputWorkspace->blocksize(); Progress prog(this, 0.0, 1.0, numHists); for (int64_t i = 0; i < int64_t(numHists); ++i) { try { // Now get the detector object for this histogram IDetector_const_sptr spectrumDet = inputWorkspace->getDetector(i); if (spectrumDet->isMonitor()) continue; const double efixed = m_EmodeProperties.getEFixed(*spectrumDet); // For inelastic scattering the simple relationship q=4*pi*sinTheta/lambda // does not hold. In order to // be completely general we must calculate the momentum transfer by // calculating the incident and final // wave vectors and then use |q| = sqrt[(ki - kf)*(ki - kf)] DetectorGroup_const_sptr detGroup = boost::dynamic_pointer_cast<const DetectorGroup>(spectrumDet); std::vector<IDetector_const_sptr> detectors; if (detGroup) { detectors = detGroup->getDetectors(); } else { detectors.push_back(spectrumDet); } const size_t numDets = detectors.size(); // cache to reduce number of static casts const double numDets_d = static_cast<double>(numDets); const auto &Y = inputWorkspace->y(i); const auto &E = inputWorkspace->e(i); const auto &X = inputWorkspace->x(i); // Loop over the detectors and for each bin calculate Q for (size_t idet = 0; idet < numDets; ++idet) { IDetector_const_sptr det = detectors[idet]; // Calculate kf vector direction and then Q for each energy bin V3D scatterDir = (det->getPos() - sample->getPos()); scatterDir.normalize(); for (size_t j = 0; j < numBins; ++j) { const double deltaE = 0.5 * (X[j] + X[j + 1]); // Compute ki and kf wave vectors and therefore q = ki - kf double ei(0.0), ef(0.0); if (emode == 1) { ei = efixed; ef = efixed - deltaE; if (ef < 0) { std::string mess = "Energy transfer requested in Direct mode exceeds incident " "energy.\n Found for det ID: " + std::to_string(idet) + " bin No " + std::to_string(j) + " with Ei=" + boost::lexical_cast<std::string>(efixed) + " and energy transfer: " + boost::lexical_cast<std::string>(deltaE); throw std::runtime_error(mess); } } else { ei = efixed + deltaE; ef = efixed; if (ef < 0) { std::string mess = "Incident energy of a neutron is negative. Are you trying to " "process Direct data in Indirect mode?\n Found for det ID: " + std::to_string(idet) + " bin No " + std::to_string(j) + " with efied=" + boost::lexical_cast<std::string>(efixed) + " and energy transfer: " + boost::lexical_cast<std::string>(deltaE); throw std::runtime_error(mess); } } if (ei < 0) throw std::runtime_error( "Negative incident energy. Check binning."); const V3D ki = beamDir * sqrt(energyToK * ei); const V3D kf = scatterDir * (sqrt(energyToK * (ef))); const double q = (ki - kf).norm(); // Test whether it's in range of the Q axis if (q < verticalAxis.front() || q > verticalAxis.back()) continue; // Find which q bin this point lies in const MantidVec::difference_type qIndex = std::upper_bound(verticalAxis.begin(), verticalAxis.end(), q) - verticalAxis.begin() - 1; // Add this spectra-detector pair to the mapping specNumberMapping.push_back( outputWorkspace->getSpectrum(qIndex).getSpectrumNo()); detIDMapping.push_back(det->getID()); // And add the data and it's error to that bin, taking into account // the number of detectors contributing to this bin outputWorkspace->mutableY(qIndex)[j] += Y[j] / numDets_d; // Standard error on the average outputWorkspace->mutableE(qIndex)[j] = sqrt((pow(outputWorkspace->e(qIndex)[j], 2) + pow(E[j], 2)) / numDets_d); } } } catch (Exception::NotFoundError &) { // Get to here if exception thrown when calculating distance to detector // Presumably, if we get to here the spectrum will be all zeroes anyway // (from conversion to E) continue; } prog.report(); } // If the input workspace was a distribution, need to divide by q bin width if (inputWorkspace->isDistribution()) this->makeDistribution(outputWorkspace, verticalAxis); // Set the output spectrum-detector mapping SpectrumDetectorMapping outputDetectorMap(specNumberMapping, detIDMapping); outputWorkspace->updateSpectraUsing(outputDetectorMap); // Replace any NaNs in outputWorkspace with zeroes if (this->getProperty("ReplaceNaNs")) { auto replaceNans = this->createChildAlgorithm("ReplaceSpecialValues"); replaceNans->setChild(true); replaceNans->initialize(); replaceNans->setProperty("InputWorkspace", outputWorkspace); replaceNans->setProperty("OutputWorkspace", outputWorkspace); replaceNans->setProperty("NaNValue", 0.0); replaceNans->setProperty("InfinityValue", 0.0); replaceNans->setProperty("BigNumberThreshold", DBL_MAX); replaceNans->execute(); } }
std::string LoadIsawPeaks::ApplyCalibInfo(std::ifstream & in, std::string startChar,Geometry::Instrument_const_sptr instr_old, Geometry::Instrument_const_sptr instr, double &T0) { ParameterMap_sptr parMap1= instr_old->getParameterMap(); ParameterMap_sptr parMap= instr->getParameterMap(); while( in.good() && (startChar.size() <1 || startChar !="7") ) { readToEndOfLine( in, true); startChar = getWord(in, false); } if( !(in.good())) { //g_log.error()<<"Peaks file has no time shift and L0 info"<<std::endl; throw std::invalid_argument("Peaks file has no time shift and L0 info"); } std::string L1s= getWord(in,false); std::string T0s =getWord(in, false); if( L1s.length() < 1 || T0s.length() < 1) { g_log.error()<<"Missing L1 or Time offset"<<std::endl; throw std::invalid_argument("Missing L1 or Time offset"); } double L1; try { std::istringstream iss( L1s+" "+T0s, std::istringstream::in); iss>>L1; iss>>T0; V3D sampPos=instr->getSample()->getPos(); SCDCalibratePanels::FixUpSourceParameterMap(instr, L1/100, sampPos,parMap1); }catch(...) { g_log.error()<<"Invalid L1 or Time offset"<<std::endl; throw std::invalid_argument("Invalid L1 or Time offset"); } readToEndOfLine( in, true); startChar = getWord(in , false); while( in.good() && (startChar.size() <1 || startChar !="5") ) { readToEndOfLine( in, true); startChar = getWord(in, false); } if( !(in.good())) { g_log.error()<<"Peaks file has no detector panel info"<<std::endl; throw std::invalid_argument("Peaks file has no detector panel info"); } while( startChar =="5") { std::string line; for( int i=0; i<16;i++) { std::string s= getWord(in, false); if( s.size() < 1) { g_log.error()<<"Not enough info to describe panel "<<std::endl; throw std::length_error("Not enough info to describe panel "); } line +=" "+s;; } readToEndOfLine(in, true); startChar = getWord( in, false);// blank lines ?? and # lines ignore std::istringstream iss( line, std::istringstream::in); int bankNum,nrows,ncols; double width,height,depth,detD,Centx,Centy,Centz,Basex,Basey,Basez, Upx,Upy,Upz; try { iss>>bankNum>>nrows>>ncols>>width>>height>>depth>>detD >>Centx>>Centy>>Centz>>Basex>>Basey>>Basez >>Upx>>Upy>>Upz; }catch(...) { g_log.error()<<"incorrect type of data for panel "<<std::endl; throw std::length_error("incorrect type of data for panel "); } std::string SbankNum = boost::lexical_cast<std::string>(bankNum); std::string bankName = "bank"+SbankNum; boost::shared_ptr<const Geometry::IComponent> bank =instr_old->getComponentByName( bankName ); if( !bank) { g_log.error()<<"There is no bank "<< bankName<<" in the instrument"<<std::endl; throw std::length_error("There is no bank "+ bankName+" in the instrument"); } V3D dPos= V3D(Centx,Centy,Centz)/100.0- bank->getPos(); V3D Base(Basex,Basey,Basez), Up(Upx,Upy,Upz); V3D ToSamp =Base.cross_prod(Up); Base.normalize(); Up.normalize(); ToSamp.normalize(); Quat thisRot(Base,Up,ToSamp); Quat bankRot(bank->getRotation()); bankRot.inverse(); Quat dRot = thisRot*bankRot; boost::shared_ptr< const Geometry::RectangularDetector>bankR= boost::dynamic_pointer_cast <const Geometry::RectangularDetector>( bank); double DetWScale = 1, DetHtScale = 1; if( bank) { DetWScale = width/bankR->xsize()/100; DetHtScale = height/bankR->ysize()/100; } std::vector<std::string> bankNames; bankNames.push_back(bankName); SCDCalibratePanels::FixUpBankParameterMap(bankNames,instr, dPos, dRot,DetWScale,DetHtScale , parMap1, false); } return startChar; }
void GoniometerAnglesFromPhiRotation::exec() { PeaksWorkspace_sptr PeaksRun1 = getProperty("PeaksWorkspace1"); PeaksWorkspace_sptr PeaksRun2 = getProperty("PeaksWorkspace2"); double Tolerance = getProperty("Tolerance"); Kernel::Matrix<double> Gon1(3, 3); Kernel::Matrix<double> Gon2(3, 3); if (!CheckForOneRun(PeaksRun1, Gon1) || !CheckForOneRun(PeaksRun2, Gon2)) { g_log.error("Each peaks workspace MUST have only one run"); throw std::invalid_argument("Each peaks workspace MUST have only one run"); } Kernel::Matrix<double> UB1, UB2; bool Run1HasOrientedLattice = true; if (!PeaksRun1->sample().hasOrientedLattice()) { Run1HasOrientedLattice = false; const std::string fft("FindUBUsingFFT"); API::IAlgorithm_sptr findUB = this->createChildAlgorithm(fft); findUB->initialize(); findUB->setProperty<PeaksWorkspace_sptr>("PeaksWorkspace", getProperty("PeaksWorkspace1")); findUB->setProperty("MIND", (double) getProperty("MIND")); findUB->setProperty("MAXD", (double) getProperty("MAXD")); findUB->setProperty("Tolerance", Tolerance); findUB->executeAsChildAlg(); if (!PeaksRun1->sample().hasOrientedLattice()) { g_log.notice(std::string("Could not find UB for ") + std::string(PeaksRun1->name())); throw std::invalid_argument( std::string("Could not find UB for ") + std::string(PeaksRun1->name())); } } //-------------get UB raw :No goniometer---------------- UB1 = PeaksRun1->sample().getOrientedLattice().getUB(); UB1 = getUBRaw(UB1, Gon1); int N1; double avErrIndx, avErrAll; IndexRaw(PeaksRun1, UB1, N1, avErrIndx, avErrAll, Tolerance); if (N1 < .6 * PeaksRun1->getNumberPeaks()) { g_log.notice(std::string("UB did not index well for ") + std::string(PeaksRun1->name())); throw std::invalid_argument( std::string("UB did not index well for ") + std::string(PeaksRun1->name())); } //---------------------------------------------- Geometry::OrientedLattice lat2 = PeaksRun1->sample().getOrientedLattice(); lat2.setUB(UB1); PeaksRun2->mutableSample().setOrientedLattice(&lat2); PeaksWorkspace_sptr Peakss = getProperty("PeaksWorkspace2"); if (!Run1HasOrientedLattice) PeaksRun1->mutableSample().setOrientedLattice(NULL); double dphi = (double) getProperty("Phi2") - (double) getProperty("Run1Phi"); Kernel::Matrix<double> Gon22(3, 3, true); for (int i = 0; i < PeaksRun2->getNumberPeaks(); i++) { PeaksRun2->getPeak(i).setGoniometerMatrix(Gon22); } int RunNum = PeaksRun2->getPeak(0).getRunNumber(); std::string RunNumStr = boost::lexical_cast<std::string>(RunNum); int Npeaks = PeaksRun2->getNumberPeaks(); std::vector<double> MinData(5); //n indexed, av err, phi, chi,omega MinData[0] = 0.0; std::vector<V3D> directionList = IndexingUtils::MakeHemisphereDirections(50); API::FrameworkManager::Instance(); for (size_t d = 0; d < directionList.size(); d++) for (int sgn = 1; sgn > -2; sgn -= 2) { V3D dir = directionList[d]; dir.normalize(); Quat Q(sgn * dphi, dir); Q.normalize(); Kernel::Matrix<double> Rot(Q.getRotation()); Kernel::Matrix<double> UB2(Rot * UB1); int Nindexed; double avErrIndx, avErrAll; IndexRaw(PeaksRun2, Rot * UB1, Nindexed, avErrIndx, avErrAll, Tolerance); if (Nindexed > MinData[0]) { MinData[0] = Nindexed; MinData[1] = sgn; MinData[2] = dir[0]; MinData[3] = dir[1]; MinData[4] = dir[2]; } } g_log.debug()<<"Best direction unOptimized is ("<<(MinData[1]*MinData[2])<<"," <<(MinData[1]*MinData[3])<<","<<(MinData[1]*MinData[4])<<")"<<std::endl; //----------------------- Optimize around best ------------------------------------------- // --------Create Workspace ------------------- boost::shared_ptr<DataObjects::Workspace2D> ws = boost::dynamic_pointer_cast< DataObjects::Workspace2D>( WorkspaceFactory::Instance().create("Workspace2D", 1, 3 * Npeaks, 3 * Npeaks)); MantidVecPtr Xvals, Yvals; for (int i = 0; i < Npeaks; ++i) { Xvals.access().push_back(i); Yvals.access().push_back(0.0); Xvals.access().push_back(i); Yvals.access().push_back(0.0); Xvals.access().push_back(i); Yvals.access().push_back(0.0); } ws->setX(0, Xvals); ws->setData(0, Yvals); // -------------Set up other Fit function arguments------------------ V3D dir(MinData[2], MinData[3], MinData[4]); dir.normalize(); Quat Q(MinData[1] * dphi, dir); Q.normalize(); Kernel::Matrix<double> Rot(Q.getRotation()); Goniometer Gon(Rot); std::vector<double> omchiphi = Gon.getEulerAngles("yzy"); MinData[2] = omchiphi[2]; MinData[3] = omchiphi[1]; MinData[4] = omchiphi[0]; std::string FunctionArgs = "name=PeakHKLErrors, PeakWorkspaceName=" + PeaksRun2->name() + ",OptRuns=" + RunNumStr + ",phi" + RunNumStr + "=" + boost::lexical_cast<std::string>(MinData[2]) + ",chi" + RunNumStr + "=" + boost::lexical_cast<std::string>(MinData[3]) + ",omega" + RunNumStr + "=" + boost::lexical_cast<std::string>(MinData[4]); std::string Constr = boost::lexical_cast<std::string>(MinData[2] - 5) + "<phi" + RunNumStr + "<" + boost::lexical_cast<std::string>(MinData[2] + 5); Constr += "," + boost::lexical_cast<std::string>(MinData[3] - 5) + "<chi" + RunNumStr + "<" + boost::lexical_cast<std::string>(MinData[3] + 5) + ","; Constr += boost::lexical_cast<std::string>(MinData[4] - 5) + "<omega" + RunNumStr + "<" + boost::lexical_cast<std::string>(MinData[4] + 5); std::string Ties = "SampleXOffset=0.0,SampleYOffset=0.0,SampleZOffset=0.0,GonRotx=0.0,GonRoty=0.0,GonRotz=0.0"; boost::shared_ptr<Algorithm> Fit = createChildAlgorithm("Fit"); Fit->initialize(); Fit->setProperty("Function", FunctionArgs); Fit->setProperty("Ties", Ties); Fit->setProperty("Constraints", Constr); Fit->setProperty("InputWorkspace", ws); Fit->setProperty("CreateOutput", true); std::string outputName = "out"; Fit->setProperty("Output", outputName); Fit->executeAsChildAlg(); //std::string status = Fit->getProperty("OutputStatus"); boost::shared_ptr<API::ITableWorkspace> results = Fit->getProperty("OutputParameters"); double chisq = Fit->getProperty("OutputChi2overDoF"); MinData[0] = chisq; MinData[2] = results->Double(6, 1); MinData[3] = results->Double(7, 1); MinData[4] = results->Double(8, 1); g_log.debug()<<"Best direction Optimized is ("<<(MinData[2])<<"," <<(MinData[3])<<","<<(MinData[4])<<")\n"; // ---------------------Find number indexed ----------------------- Quat Q1 = Quat(MinData[4], V3D(0, 1, 0)) * Quat(MinData[3], V3D(0, 0, 1)) * Quat(MinData[2], V3D(0, 1, 0)); int Nindexed; Kernel::Matrix<double> Mk(Q1.getRotation()); IndexRaw(PeaksRun2, Mk * UB1, Nindexed, avErrIndx, avErrAll, Tolerance); //------------------------------------ Convert/Save Results ----------------------------- double deg, ax1, ax2, ax3; Q1.getAngleAxis(deg, ax1, ax2, ax3); if (dphi * deg < 0) { deg = -deg; ax1 = -ax1; ax2 = -ax2; ax3 = -ax3; } double phi2 = (double) getProperty("Run1Phi") + dphi; double chi2 = acos(ax2) / M_PI * 180; double omega2 = atan2(ax3, -ax1) / M_PI * 180; g_log.notice() << "============================ Results ============================" << std::endl; g_log.notice() << " phi,chi, and omega= (" << phi2 << "," << chi2 << "," << omega2 << ")" << std::endl; g_log.notice() << " #indexed =" << Nindexed << std::endl; g_log.notice() << " ==============================================" << std::endl; //std::cout << "============================ Results ============================" << std::endl; // std::cout << " phi,chi, and omega= (" << phi2 << "," << chi2 << "," << omega2 << ")" // << std::endl; // std::cout << " #indexed =" << Nindexed << std::endl; // std::cout << " ==============================================" << std::endl; setProperty("Phi2", phi2); setProperty("Chi2", chi2); setProperty("Omega2", omega2); setProperty("NIndexed", Nindexed); setProperty("AvErrIndex", avErrIndx); setProperty("AvErrAll", avErrAll); Q1 = Quat(omega2, V3D(0, 1, 0)) * Quat(chi2, V3D(0, 0, 1)) * Quat(phi2, V3D(0, 1, 0)); Kernel::Matrix<double> Gon2a(Q1.getRotation()); for (int i = 0; i < PeaksRun2->getNumberPeaks(); i++) { PeaksRun2->getPeak(i).setGoniometerMatrix(Gon2a); } OrientedLattice latt2(PeaksRun2->mutableSample().getOrientedLattice()); //Kernel::Matrix<double> UB = latt2.getUB(); Rot.Invert(); Gon2a.Invert(); latt2.setUB(Gon2a * Mk * UB1); PeaksRun2->mutableSample().setOrientedLattice(&latt2); }