/** 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 DetectorEfficiencyCor::getDetectorGeometry(const Geometry::IDetector_const_sptr & det, double & detRadius, V3D & detAxis) { boost::shared_ptr<const Object> shape_sptr = det->shape(); if(!shape_sptr->hasValidShape()) { throw Exception::NotFoundError("Shape", "Detector has no shape"); } std::map<const Geometry::Object *, std::pair<double, Kernel::V3D> >::const_iterator it = m_shapeCache.find(shape_sptr.get()); if( it == m_shapeCache.end() ) { double xDist = distToSurface( V3D(DIST_TO_UNIVERSE_EDGE, 0, 0), shape_sptr.get() ); double zDist = distToSurface( V3D(0, 0, DIST_TO_UNIVERSE_EDGE), shape_sptr.get() ); if ( std::abs(zDist - xDist) < 1e-8 ) { detRadius = zDist/2.0; detAxis = V3D(0,1,0); // assume radi in z and x and the axis is in the y PARALLEL_CRITICAL(deteff_shapecachea) { m_shapeCache.insert(std::pair<const Object *,std::pair<double, V3D> >(shape_sptr.get(), std::pair<double, V3D>(detRadius, detAxis))); } return; }
/** Non-member helper method to convert x y z enumeration directions into proper 3D vectors. @param direction : direction marker @return 3D vector */ V3D directionToVector(const PointingAlong &direction) { Mantid::Kernel::V3D result; if (direction == X) { result = V3D(1, 0, 0); } else if (direction == Y) { result = V3D(0, 1, 0); } else { result = V3D(0, 0, 1); } return result; }
/// 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; } } }
void jacTransform(MXD& J, const mtInput& input) const{ J.setZero(); const int& camID = input.CfP(ID_).camID_; if(camID != outputCamID_){ input.updateMultiCameraExtrinsics(mpMultiCamera_); const QPD qDC = input.qCM(outputCamID_)*input.qCM(camID).inverted(); // TODO: avoid double computation const V3D CrCD = input.qCM(camID).rotate(V3D(input.MrMC(outputCamID_)-input.MrMC(camID))); const V3D CrCP = input.dep(ID_).getDistance()*input.CfP(ID_).get_nor().getVec(); const V3D DrDP = qDC.rotate(V3D(CrCP-CrCD)); const double d_out = DrDP.norm(); const LWF::NormalVectorElement nor_out(DrDP); // TODO: test if Jacobian works, this new setting of vector is dangerous const Eigen::Matrix<double,1,3> J_d_DrDP = nor_out.getVec().transpose(); const Eigen::Matrix<double,2,3> J_nor_DrDP = nor_out.getM().transpose()/d_out; const Eigen::Matrix<double,3,3> J_DrDP_qDC = gSM(DrDP); const Eigen::Matrix<double,3,3> J_DrDP_CrCP = MPD(qDC).matrix(); const Eigen::Matrix<double,3,3> J_DrDP_CrCD = -MPD(qDC).matrix(); const Eigen::Matrix<double,3,3> J_qDC_qDB = Eigen::Matrix3d::Identity(); const Eigen::Matrix<double,3,3> J_qDC_qCB = -MPD(qDC).matrix(); const Eigen::Matrix<double,3,3> J_CrCD_qCB = gSM(CrCD); const Eigen::Matrix<double,3,3> J_CrCD_BrBC = -MPD(input.qCM(camID)).matrix(); const Eigen::Matrix<double,3,3> J_CrCD_BrBD = MPD(input.qCM(camID)).matrix(); const Eigen::Matrix<double,3,1> J_CrCP_d = input.CfP(ID_).get_nor().getVec()*input.dep(ID_).getDistanceDerivative(); const Eigen::Matrix<double,3,2> J_CrCP_nor = input.dep(ID_).getDistance()*input.CfP(ID_).get_nor().getM(); J.template block<2,2>(mtOutput::template getId<mtOutput::_fea>(),mtInput::template getId<mtInput::_fea>(ID_)) = J_nor_DrDP*J_DrDP_CrCP*J_CrCP_nor; J.template block<2,1>(mtOutput::template getId<mtOutput::_fea>(),mtInput::template getId<mtInput::_fea>(ID_)+2) = J_nor_DrDP*J_DrDP_CrCP*J_CrCP_d; if(!ignoreDistanceOutput_){ J.template block<1,2>(mtOutput::template getId<mtOutput::_fea>()+2,mtInput::template getId<mtInput::_fea>(ID_)) = J_d_DrDP*J_DrDP_CrCP*J_CrCP_nor; J.template block<1,1>(mtOutput::template getId<mtOutput::_fea>()+2,mtInput::template getId<mtInput::_fea>(ID_)+2) = J_d_DrDP*J_DrDP_CrCP*J_CrCP_d; } if(input.aux().doVECalibration_ && camID != outputCamID_){ J.template block<2,3>(mtOutput::template getId<mtOutput::_fea>(),mtInput::template getId<mtInput::_vea>(camID)) = J_nor_DrDP*(J_DrDP_qDC*J_qDC_qCB+J_DrDP_CrCD*J_CrCD_qCB); J.template block<2,3>(mtOutput::template getId<mtOutput::_fea>(),mtInput::template getId<mtInput::_vea>(outputCamID_)) = J_nor_DrDP*J_DrDP_qDC*J_qDC_qDB; J.template block<2,3>(mtOutput::template getId<mtOutput::_fea>(),mtInput::template getId<mtInput::_vep>(camID)) = J_nor_DrDP*J_DrDP_CrCD*J_CrCD_BrBC; J.template block<2,3>(mtOutput::template getId<mtOutput::_fea>(),mtInput::template getId<mtInput::_vep>(outputCamID_)) = J_nor_DrDP*J_DrDP_CrCD*J_CrCD_BrBD; if(!ignoreDistanceOutput_){ J.template block<1,3>(mtOutput::template getId<mtOutput::_fea>()+2,mtInput::template getId<mtInput::_vea>(camID)) = J_d_DrDP*(J_DrDP_qDC*J_qDC_qCB+J_DrDP_CrCD*J_CrCD_qCB); J.template block<1,3>(mtOutput::template getId<mtOutput::_fea>()+2,mtInput::template getId<mtInput::_vea>(outputCamID_)) = J_d_DrDP*J_DrDP_qDC*J_qDC_qDB; J.template block<1,3>(mtOutput::template getId<mtOutput::_fea>()+2,mtInput::template getId<mtInput::_vep>(camID)) = J_d_DrDP*J_DrDP_CrCD*J_CrCD_BrBC; J.template block<1,3>(mtOutput::template getId<mtOutput::_fea>()+2,mtInput::template getId<mtInput::_vep>(outputCamID_)) = J_d_DrDP*J_DrDP_CrCD*J_CrCD_BrBD; } } } else { J.template block<2,2>(mtOutput::template getId<mtOutput::_fea>(),mtInput::template getId<mtInput::_fea>(ID_)) = Eigen::Matrix2d::Identity(); J.template block<1,1>(mtOutput::template getId<mtOutput::_fea>()+2,mtInput::template getId<mtInput::_fea>(ID_)+2) = Eigen::Matrix<double,1,1>::Identity(); } }
void evalTransform(mtOutput& output, const mtInput& input) const{ input.updateMultiCameraExtrinsics(mpMultiCamera_); mpMultiCamera_->transformFeature(outputCamID_,input.CfP(ID_),input.dep(ID_),output.c(),output.d()); if(input.CfP(ID_).trackWarping_ && input.CfP(ID_).com_warp_nor()){ const int& camID = input.CfP(ID_).camID_; const QPD qDC = input.qCM(outputCamID_)*input.qCM(camID).inverted(); // TODO: avoid double computation const V3D CrCD = input.qCM(camID).rotate(V3D(input.MrMC(outputCamID_)-input.MrMC(camID))); const V3D CrCP = input.dep(ID_).getDistance()*input.CfP(ID_).get_nor().getVec(); const V3D DrDP = qDC.rotate(V3D(CrCP-CrCD)); const double d_out = DrDP.norm(); const LWF::NormalVectorElement nor_out(DrDP); const Eigen::Matrix<double,2,3> J_nor_DrDP = nor_out.getM().transpose()/d_out; const Eigen::Matrix<double,3,3> J_DrDP_CrCP = MPD(qDC).matrix(); const Eigen::Matrix<double,3,2> J_CrCP_nor = input.dep(ID_).getDistance()*input.CfP(ID_).get_nor().getM(); output.c().set_warp_nor(J_nor_DrDP*J_DrDP_CrCP*J_CrCP_nor*input.CfP(ID_).get_warp_nor()); } }
/** Create or adjust "rot" parameter for a component * Assumed that name either equals "rotx", "roty" or "rotz" otherwise this * method will not add/modify "rot" parameter * @param comp :: Component * @param name :: Parameter name * @param deg :: Parameter value in degrees * @param pDescription :: a pointer (may be NULL) to a string, containing * parameter's * description. If provided, the contents of the string is copied to the * parameter's * memory */ void ParameterMap::addRotationParam(const IComponent *comp, const std::string &name, const double deg, const std::string *const pDescription) { Parameter_sptr paramRotX = get(comp, rotx()); Parameter_sptr paramRotY = get(comp, roty()); Parameter_sptr paramRotZ = get(comp, rotz()); double rotX, rotY, rotZ; if (paramRotX) rotX = paramRotX->value<double>(); else rotX = 0.0; if (paramRotY) rotY = paramRotY->value<double>(); else rotY = 0.0; if (paramRotZ) rotZ = paramRotZ->value<double>(); else rotZ = 0.0; // adjust rotation Quat quat; if (name.compare(rotx()) == 0) { addDouble(comp, rotx(), deg); quat = Quat(deg, V3D(1, 0, 0)) * Quat(rotY, V3D(0, 1, 0)) * Quat(rotZ, V3D(0, 0, 1)); } else if (name.compare(roty()) == 0) { addDouble(comp, roty(), deg); quat = Quat(rotX, V3D(1, 0, 0)) * Quat(deg, V3D(0, 1, 0)) * Quat(rotZ, V3D(0, 0, 1)); } else if (name.compare(rotz()) == 0) { addDouble(comp, rotz(), deg); quat = Quat(rotX, V3D(1, 0, 0)) * Quat(rotY, V3D(0, 1, 0)) * Quat(deg, V3D(0, 0, 1)); } else { g_log.warning() << "addRotationParam() called with unrecognized coordinate symbol: " << name; return; } // clear the position cache clearPositionSensitiveCaches(); // finally add or update "pos" parameter addQuat(comp, rot(), quat, pDescription); }
/** Execute the algorithm. */ void CalculateUMatrix::exec() { double a=this->getProperty("a"); double b=this->getProperty("b"); double c=this->getProperty("c"); double alpha=this->getProperty("alpha"); double beta=this->getProperty("beta"); double gamma=this->getProperty("gamma"); OrientedLattice o(a,b,c,alpha,beta,gamma); Matrix<double> B=o.getB(); double H,K,L; PeaksWorkspace_sptr ws; ws = boost::dynamic_pointer_cast<PeaksWorkspace>(AnalysisDataService::Instance().retrieve(this->getProperty("PeaksWorkspace")) ); if (!ws) throw std::runtime_error("Problems reading the peaks workspace"); Matrix<double> Hi(4,4),Si(4,4),HS(4,4),zero(4,4); for (int i=0;i<ws->getNumberPeaks();i++) { Peak p=ws->getPeaks()[i]; H=p.getH(); K=p.getK(); L=p.getL(); if(H*H+K*K+L*L>0) { V3D Qhkl=B*V3D(H,K,L); Hi[0][0]=0.; Hi[0][1]=-Qhkl.X(); Hi[0][2]=-Qhkl.Y(); Hi[0][3]=-Qhkl.Z(); Hi[1][0]=Qhkl.X(); Hi[1][1]=0.; Hi[1][2]=Qhkl.Z(); Hi[1][3]=-Qhkl.Y(); Hi[2][0]=Qhkl.Y(); Hi[2][1]=-Qhkl.Z(); Hi[2][2]=0.; Hi[2][3]=Qhkl.X(); Hi[3][0]=Qhkl.Z(); Hi[3][1]=Qhkl.Y(); Hi[3][2]=-Qhkl.X(); Hi[3][3]=0.; V3D Qgon=p.getQSampleFrame(); Si[0][0]=0.; Si[0][1]=-Qgon.X(); Si[0][2]=-Qgon.Y(); Si[0][3]=-Qgon.Z(); Si[1][0]=Qgon.X(); Si[1][1]=0.; Si[1][2]=-Qgon.Z(); Si[1][3]=Qgon.Y(); Si[2][0]=Qgon.Y(); Si[2][1]=Qgon.Z(); Si[2][2]=0.; Si[2][3]=-Qgon.X(); Si[3][0]=Qgon.Z(); Si[3][1]=-Qgon.Y(); Si[3][2]=Qgon.X(); Si[3][3]=0.; HS+=(Hi*Si); } } //check if HS is 0 if (HS==zero) throw std::invalid_argument("The peaks workspace is not indexed or something really bad happened"); Matrix<double> Eval; Matrix<double> Diag; HS.Diagonalise(Eval,Diag); Eval.sortEigen(Diag); Mantid::Kernel::Quat qR(Eval[0][0],Eval[1][0],Eval[2][0],Eval[3][0]);//the first column corresponds to the highest eigenvalue DblMatrix U(qR.getRotation()); o.setU(U); ws->mutableSample().setOrientedLattice(new OrientedLattice(o)); }
/** Get the position relative to the parent IComponent (absolute if no parent) * This is calculated on-the-fly. * * @return position relative to the 0,0 point of the parent panel */ const Kernel::V3D RectangularDetectorPixel::getRelativePos() const { // Calculate the x,y position double x = m_panel->xstart() + double(m_col) * m_panel->xstep(); double y = m_panel->ystart() + double(m_row) * m_panel->ystep(); // The parent m_panel is always the unparametrized version, // so the xstep() etc. returned are the UNSCALED one. if (m_map) { // Apply the scaling factors if (m_map->contains(m_panel, "scalex")) x *= m_map->get(m_panel, "scalex")->value<double>(); if (m_map->contains(m_panel, "scaley")) y *= m_map->get(m_panel, "scaley")->value<double>(); } return V3D(x, y, 0); }
std::vector<VMDBase<TYPE>> VMDBase<TYPE>::makeVectorsOrthogonal(std::vector<VMDBase> &vectors) { if (vectors.size() != 2) throw std::runtime_error( "VMDBase::makeVectorsOrthogonal(): Need 2 input vectors."); if (vectors[0].getNumDims() != 3 || vectors[1].getNumDims() != 3) throw std::runtime_error( "VMDBase::makeVectorsOrthogonal(): Need 3D input vectors."); std::vector<V3D> in, out; for (size_t i = 0; i < vectors.size(); i++) in.push_back(V3D(vectors[i][0], vectors[i][1], vectors[i][2])); out = V3D::makeVectorsOrthogonal(in); std::vector<VMDBase> retVal; for (size_t i = 0; i < out.size(); i++) retVal.push_back(VMDBase(out[i])); return retVal; }
/** Create or adjust "rot" parameter for a component * Assumed that name either equals "rotx", "roty" or "rotz" otherwise this * method will not add/modify "rot" parameter * @param comp :: Component * @param name :: Parameter name * @param deg :: Parameter value in degrees */ void ParameterMap::addRotationParam(const IComponent* comp,const std::string& name, const double deg) { Parameter_sptr param = get(comp,"rot"); Quat quat; Parameter_sptr paramRotX = get(comp,"rotx"); Parameter_sptr paramRotY = get(comp,"roty"); Parameter_sptr paramRotZ = get(comp,"rotz"); double rotX, rotY, rotZ; if ( paramRotX ) rotX = paramRotX->value<double>(); else rotX = 0.0; if ( paramRotY ) rotY = paramRotY->value<double>(); else rotY = 0.0; if ( paramRotZ ) rotZ = paramRotZ->value<double>(); else rotZ = 0.0; // adjust rotation if ( name.compare("rotx")==0 ) { if (paramRotX) paramRotX->set(deg); else addDouble(comp, "rotx", deg); quat = Quat(deg,V3D(1,0,0))*Quat(rotY,V3D(0,1,0))*Quat(rotZ,V3D(0,0,1)); } else if ( name.compare("roty")==0 ) { if (paramRotY) paramRotY->set(deg); else addDouble(comp, "roty", deg); quat = Quat(rotX,V3D(1,0,0))*Quat(deg,V3D(0,1,0))*Quat(rotZ,V3D(0,0,1)); } else if ( name.compare("rotz")==0 ) { if (paramRotZ) paramRotZ->set(deg); else addDouble(comp, "rotz", deg); quat = Quat(rotX,V3D(1,0,0))*Quat(rotY,V3D(0,1,0))*Quat(deg,V3D(0,0,1)); } else { g_log.warning() << "addRotationParam() called with unrecognised coordinate symbol: " << name; return; } //clear the position cache clearCache(); // finally add or update "pos" parameter if (param) param->set(quat); else addQuat(comp, "rot", quat); }
if( it == m_shapeCache.end() ) { double xDist = distToSurface( V3D(DIST_TO_UNIVERSE_EDGE, 0, 0), shape_sptr.get() ); double zDist = distToSurface( V3D(0, 0, DIST_TO_UNIVERSE_EDGE), shape_sptr.get() ); if ( std::abs(zDist - xDist) < 1e-8 ) { detRadius = zDist/2.0; detAxis = V3D(0,1,0); // assume radi in z and x and the axis is in the y PARALLEL_CRITICAL(deteff_shapecachea) { m_shapeCache.insert(std::pair<const Object *,std::pair<double, V3D> >(shape_sptr.get(), std::pair<double, V3D>(detRadius, detAxis))); } return; } double yDist = distToSurface( V3D(0, DIST_TO_UNIVERSE_EDGE, 0), shape_sptr.get() ); if ( std::abs(yDist - zDist) < 1e-8 ) { detRadius = yDist/2.0; detAxis = V3D(1,0,0); // assume that y and z are radi of the cylinder's circular cross-section and the axis is perpendicular, in the x direction PARALLEL_CRITICAL(deteff_shapecacheb) { m_shapeCache.insert(std::pair<const Object *,std::pair<double, V3D> >(shape_sptr.get(), std::pair<double, V3D>(detRadius, detAxis))); } return; } if ( std::abs(xDist - yDist) < 1e-8 ) { detRadius = xDist/2.0;
/** Execute the algorithm. */ void CalculateUMatrix::exec() { double a=this->getProperty("a"); double b=this->getProperty("b"); double c=this->getProperty("c"); double alpha=this->getProperty("alpha"); double beta=this->getProperty("beta"); double gamma=this->getProperty("gamma"); OrientedLattice o(a,b,c,alpha,beta,gamma); Matrix<double> B=o.getB(); double H,K,L; PeaksWorkspace_sptr ws; ws = AnalysisDataService::Instance().retrieveWS<PeaksWorkspace>(this->getProperty("PeaksWorkspace") ); if (!ws) throw std::runtime_error("Problems reading the peaks workspace"); size_t nIndexedpeaks=0; bool found2nc=false; V3D old(0,0,0); Matrix<double> Hi(4,4),Si(4,4),HS(4,4),zero(4,4); for (int i=0;i<ws->getNumberPeaks();i++) { Peak p=ws->getPeaks()[i]; H=p.getH(); K=p.getK(); L=p.getL(); if(H*H+K*K+L*L>0) { nIndexedpeaks++; if (!found2nc) { if (nIndexedpeaks==1) { old=V3D(H,K,L); } else { if (!old.coLinear(V3D(0,0,0),V3D(H,K,L))) found2nc=true; } } V3D Qhkl=B*V3D(H,K,L); Hi[0][0]=0.; Hi[0][1]=-Qhkl.X(); Hi[0][2]=-Qhkl.Y(); Hi[0][3]=-Qhkl.Z(); Hi[1][0]=Qhkl.X(); Hi[1][1]=0.; Hi[1][2]=Qhkl.Z(); Hi[1][3]=-Qhkl.Y(); Hi[2][0]=Qhkl.Y(); Hi[2][1]=-Qhkl.Z(); Hi[2][2]=0.; Hi[2][3]=Qhkl.X(); Hi[3][0]=Qhkl.Z(); Hi[3][1]=Qhkl.Y(); Hi[3][2]=-Qhkl.X(); Hi[3][3]=0.; V3D Qgon=p.getQSampleFrame(); Si[0][0]=0.; Si[0][1]=-Qgon.X(); Si[0][2]=-Qgon.Y(); Si[0][3]=-Qgon.Z(); Si[1][0]=Qgon.X(); Si[1][1]=0.; Si[1][2]=-Qgon.Z(); Si[1][3]=Qgon.Y(); Si[2][0]=Qgon.Y(); Si[2][1]=Qgon.Z(); Si[2][2]=0.; Si[2][3]=-Qgon.X(); Si[3][0]=Qgon.Z(); Si[3][1]=-Qgon.Y(); Si[3][2]=Qgon.X(); Si[3][3]=0.; HS+=(Hi*Si); } } //check if enough peaks are indexed or if HS is 0 if ((nIndexedpeaks<2) || (found2nc==false)) throw std::invalid_argument("Less then two non-colinear peaks indexed"); if (HS==zero) throw std::invalid_argument("Something really bad happened"); Matrix<double> Eval; Matrix<double> Diag; HS.Diagonalise(Eval,Diag); Eval.sortEigen(Diag); Mantid::Kernel::Quat qR(Eval[0][0],Eval[1][0],Eval[2][0],Eval[3][0]);//the first column corresponds to the highest eigenvalue DblMatrix U(qR.getRotation()); o.setU(U); ws->mutableSample().setOrientedLattice(new OrientedLattice(o)); }
void addFullInstrumentToWorkspace(MatrixWorkspace &workspace, bool includeMonitors, bool startYNegative, const std::string &instrumentName) { auto instrument = boost::make_shared<Instrument>(instrumentName); instrument->setReferenceFrame( boost::make_shared<ReferenceFrame>(Y, Z, Right, "")); workspace.setInstrument(instrument); const double pixelRadius(0.05); Object_sptr pixelShape = ComponentCreationHelper::createCappedCylinder( pixelRadius, 0.02, V3D(0.0, 0.0, 0.0), V3D(0., 1.0, 0.), "tube"); const double detZPos(5.0); // Careful! Do not use size_t or auto, the unisgned will break the -=2 below. int ndets = static_cast<int>(workspace.getNumberHistograms()); if (includeMonitors) ndets -= 2; for (int i = 0; i < ndets; ++i) { std::ostringstream lexer; lexer << "pixel-" << i << ")"; Detector *physicalPixel = new Detector(lexer.str(), workspace.getAxis(1)->spectraNo(i), pixelShape, instrument.get()); int ycount(i); if (startYNegative) ycount -= 1; const double ypos = ycount * 2.0 * pixelRadius; physicalPixel->setPos(0.0, ypos, detZPos); instrument->add(physicalPixel); instrument->markAsDetector(physicalPixel); workspace.getSpectrum(i).setDetectorID(physicalPixel->getID()); } // Monitors last if (includeMonitors) // These occupy the last 2 spectra { Detector *monitor1 = new Detector("mon1", workspace.getAxis(1)->spectraNo(ndets), Object_sptr(), instrument.get()); monitor1->setPos(0.0, 0.0, -9.0); instrument->add(monitor1); instrument->markAsMonitor(monitor1); workspace.getSpectrum(ndets).setDetectorID(ndets + 1); Detector *monitor2 = new Detector("mon2", workspace.getAxis(1)->spectraNo(ndets) + 1, Object_sptr(), instrument.get()); monitor2->setPos(0.0, 0.0, -2.0); instrument->add(monitor2); instrument->markAsMonitor(monitor2); workspace.getSpectrum(ndets + 1).setDetectorID(ndets + 2); } // Define a source and sample position // Define a source component ObjComponent *source = new ObjComponent( "moderator", ComponentCreationHelper::createSphere(0.1, V3D(0, 0, 0), "1"), instrument.get()); source->setPos(V3D(0.0, 0.0, -20.0)); instrument->add(source); instrument->markAsSource(source); // Define a sample as a simple sphere ObjComponent *sample = new ObjComponent( "samplePos", ComponentCreationHelper::createSphere(0.1, V3D(0, 0, 0), "1"), instrument.get()); instrument->setPos(0.0, 0.0, 0.0); instrument->add(sample); instrument->markAsSamplePos(sample); // chopper position Component *chop_pos = new Component("chopper-position", Kernel::V3D(0, 0, -10), instrument.get()); instrument->add(chop_pos); }
/** * Construct a PoldiPeakCollection from a Poldi2DFunction * * This method performs the opposite operation of *getFunctionFromPeakCollection. * It takes a function, checks if it's of the proper type and turns the * information into a PoldiPeakCollection. * * @param Poldi2DFunction with one PoldiSpectrumDomainFunction per peak * @return PoldiPeakCollection containing peaks with normalized intensities */ PoldiPeakCollection_sptr PoldiFitPeaks2D::getPeakCollectionFromFunction( const IFunction_sptr &fitFunction) { Poldi2DFunction_sptr poldi2DFunction = boost::dynamic_pointer_cast<Poldi2DFunction>(fitFunction); if (!poldi2DFunction) { throw std::invalid_argument( "Cannot process function that is not a Poldi2DFunction."); } PoldiPeakCollection_sptr normalizedPeaks = boost::make_shared<PoldiPeakCollection>(PoldiPeakCollection::Integral); boost::shared_ptr<const Kernel::DblMatrix> covarianceMatrix = poldi2DFunction->getCovarianceMatrix(); size_t offset = 0; for (size_t i = 0; i < poldi2DFunction->nFunctions(); ++i) { boost::shared_ptr<PoldiSpectrumPawleyFunction> poldiPawleyFunction = boost::dynamic_pointer_cast<PoldiSpectrumPawleyFunction>( poldi2DFunction->getFunction(i)); // If it's a Pawley function, there are several peaks in one function. if (poldiPawleyFunction) { IPawleyFunction_sptr pawleyFunction = poldiPawleyFunction->getPawleyFunction(); if (pawleyFunction) { CompositeFunction_sptr decoratedFunction = boost::dynamic_pointer_cast<CompositeFunction>( pawleyFunction->getDecoratedFunction()); offset = decoratedFunction->getFunction(0)->nParams(); for (size_t j = 0; j < pawleyFunction->getPeakCount(); ++j) { IPeakFunction_sptr profileFunction = pawleyFunction->getPeakFunction(j); size_t nLocalParams = profileFunction->nParams(); boost::shared_ptr<Kernel::DblMatrix> localCov = getLocalCovarianceMatrix(covarianceMatrix, offset, nLocalParams); profileFunction->setCovarianceMatrix(localCov); // Increment offset for next function offset += nLocalParams; V3D peakHKL = pawleyFunction->getPeakHKL(j); PoldiPeak_sptr peak = getPeakFromPeakFunction(profileFunction, peakHKL); normalizedPeaks->addPeak(peak); } } break; } // Otherwise, it's just one peak in this function. boost::shared_ptr<PoldiSpectrumDomainFunction> peakFunction = boost::dynamic_pointer_cast<PoldiSpectrumDomainFunction>( poldi2DFunction->getFunction(i)); if (peakFunction) { IPeakFunction_sptr profileFunction = boost::dynamic_pointer_cast<IPeakFunction>( peakFunction->getProfileFunction()); // Get local covariance matrix size_t nLocalParams = profileFunction->nParams(); boost::shared_ptr<Kernel::DblMatrix> localCov = getLocalCovarianceMatrix(covarianceMatrix, offset, nLocalParams); profileFunction->setCovarianceMatrix(localCov); // Increment offset for next function offset += nLocalParams; PoldiPeak_sptr peak = getPeakFromPeakFunction(profileFunction, V3D(0, 0, 0)); normalizedPeaks->addPeak(peak); } } return normalizedPeaks; }
void SANSDirectBeamScaling::exec() { MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace"); const double beamRadius = getProperty("BeamRadius"); const double attTrans = getProperty("AttenuatorTransmission"); const double attTransErr = getProperty("AttenuatorTransmissionError"); // Extract the required spectra into separate workspaces std::vector<detid_t> udet; std::vector<size_t> index; udet.push_back(getProperty("BeamMonitor")); // Convert UDETs to workspace indices inputWS->getIndicesFromDetectorIDs(udet,index); if (index.size() < 1) { g_log.debug() << "inputWS->getIndicesFromDetectorIDs() returned empty\n"; throw std::invalid_argument("Could not find the incident beam monitor spectra\n"); } const int64_t numHists = inputWS->getNumberHistograms(); Progress progress(this,0.0,1.0,numHists); // Number of X bins const int64_t xLength = inputWS->readY(0).size(); // Monitor counts double monitor = 0.0; const MantidVec& MonIn = inputWS->readY(index[0]); for (int64_t j = 0; j < xLength; j++) monitor += MonIn[j]; const V3D sourcePos = inputWS->getInstrument()->getSource()->getPos(); double counts = 0.0; double error = 0.0; int nPixels = 0; // Sample-detector distance for the contributing pixels double sdd = 0.0; for (int64_t i = 0; i < int64_t(numHists); ++i) { IDetector_const_sptr det; try { det = inputWS->getDetector(i); } catch (Exception::NotFoundError&) { g_log.warning() << "Spectrum index " << i << " has no detector assigned to it - discarding" << std::endl; continue; } // Skip if we have a monitor or if the detector is masked. if ( det->isMonitor() || det->isMasked() ) continue; const MantidVec& YIn = inputWS->readY(i); const MantidVec& EIn = inputWS->readE(i); // Sum up all the counts V3D pos = det->getPos() - V3D(sourcePos.X(), sourcePos.Y(), 0.0); const double pixelDistance = pos.Z(); pos.setZ(0.0); if (pos.norm() <= beamRadius) { // Correct data for all X bins for (int64_t j = 0; j < xLength; j++) { counts += YIn[j]; error += EIn[j]*EIn[j]; } nPixels += 1; sdd += pixelDistance; } progress.report("Absolute Scaling"); } // Get the average SDD for the counted pixels, and transform to mm. sdd = sdd/nPixels*1000.0; error = std::sqrt(error); // Transform from m to mm double sourceAperture = getProperty("SourceApertureRadius"); sourceAperture *= 1000.0; // Transform from m to mm double sampleAperture = getProperty("SampleApertureRadius"); sampleAperture *= 1000.0; //TODO: replace this by some meaningful value const double KCG2FluxPerMon_SUGAR = 1.0; // Solid angle correction scale in 1/(cm^2)/steradian double solidAngleCorrScale = sdd/(M_PI*sourceAperture*sampleAperture); solidAngleCorrScale = solidAngleCorrScale*solidAngleCorrScale*100.0; // Scaling factor in n/(monitor count)/(cm^2)/steradian double scale = counts/monitor*solidAngleCorrScale/KCG2FluxPerMon_SUGAR; double scaleErr = std::abs(error/monitor)*solidAngleCorrScale/KCG2FluxPerMon_SUGAR; scaleErr = std::abs(scale/attTrans)*sqrt( (scaleErr/scale)*(scaleErr/scale) +(attTransErr/attTrans)*(attTransErr/attTrans) ); scale /= attTrans; std::vector<double> output; output.push_back(scale); output.push_back(scaleErr); setProperty("ScaleFactor", output); }
/** Executes the algorithm * * @throw runtime_error Thrown if algorithm cannot execute */ void DiffractionEventCalibrateDetectors::exec() { // Try to retrieve optional properties const int maxIterations = getProperty("MaxIterations"); const double peakOpt = getProperty("LocationOfPeakToOptimize"); // Get the input workspace EventWorkspace_sptr inputW = getProperty("InputWorkspace"); // retrieve the properties const std::string rb_params = getProperty("Params"); // Get some stuff from the input workspace Instrument_const_sptr inst = inputW->getInstrument(); // Build a list of Rectangular Detectors std::vector<boost::shared_ptr<RectangularDetector>> detList; // --------- Loading only one bank ---------------------------------- std::string onebank = getProperty("BankName"); bool doOneBank = (onebank != ""); for (int i = 0; i < inst->nelements(); i++) { boost::shared_ptr<RectangularDetector> det; boost::shared_ptr<ICompAssembly> assem; boost::shared_ptr<ICompAssembly> assem2; det = boost::dynamic_pointer_cast<RectangularDetector>((*inst)[i]); if (det) { if (det->getName().compare(onebank) == 0) detList.push_back(det); if (!doOneBank) detList.push_back(det); } else { // Also, look in the first sub-level for RectangularDetectors (e.g. PG3). // We are not doing a full recursive search since that will be very long // for lots of pixels. assem = boost::dynamic_pointer_cast<ICompAssembly>((*inst)[i]); if (assem) { for (int j = 0; j < assem->nelements(); j++) { det = boost::dynamic_pointer_cast<RectangularDetector>((*assem)[j]); if (det) { if (det->getName().compare(onebank) == 0) detList.push_back(det); if (!doOneBank) detList.push_back(det); } else { // Also, look in the second sub-level for RectangularDetectors (e.g. // PG3). // We are not doing a full recursive search since that will be very // long for lots of pixels. assem2 = boost::dynamic_pointer_cast<ICompAssembly>((*assem)[j]); if (assem2) { for (int k = 0; k < assem2->nelements(); k++) { det = boost::dynamic_pointer_cast<RectangularDetector>( (*assem2)[k]); if (det) { if (det->getName().compare(onebank) == 0) detList.push_back(det); if (!doOneBank) detList.push_back(det); } } } } } } } } // set-up minimizer std::string inname = getProperty("InputWorkspace"); std::string outname = inname + "2"; // getProperty("OutputWorkspace"); IAlgorithm_sptr algS = createChildAlgorithm("SortEvents"); algS->setProperty("InputWorkspace", inputW); algS->setPropertyValue("SortBy", "X Value"); algS->executeAsChildAlg(); // Write DetCal File std::string filename = getProperty("DetCalFilename"); std::fstream outfile; outfile.open(filename.c_str(), std::ios::out); if (detList.size() > 1) { outfile << "#\n"; outfile << "# Mantid Optimized .DetCal file for SNAP with TWO detector " "panels\n"; outfile << "# Old Panel, nominal size and distance at -90 degrees.\n"; outfile << "# New Panel, nominal size and distance at +90 degrees.\n"; outfile << "#\n"; outfile << "# Lengths are in centimeters.\n"; outfile << "# Base and up give directions of unit vectors for a local\n"; outfile << "# x,y coordinate system on the face of the detector.\n"; outfile << "#\n"; outfile << "# " << DateAndTime::getCurrentTime().toFormattedString("%c") << "\n"; outfile << "#\n"; outfile << "6 L1 T0_SHIFT\n"; IComponent_const_sptr source = inst->getSource(); IComponent_const_sptr sample = inst->getSample(); outfile << "7 " << source->getDistance(*sample) * 100 << " 0\n"; outfile << "4 DETNUM NROWS NCOLS WIDTH HEIGHT DEPTH DETD " "CenterX CenterY CenterZ BaseX BaseY BaseZ " "UpX UpY UpZ\n"; } Progress prog(this, 0.0, 1.0, detList.size()); for (int det = 0; det < static_cast<int>(detList.size()); det++) { std::string par[6]; par[0] = detList[det]->getName(); par[1] = inname; par[2] = outname; std::ostringstream strpeakOpt; strpeakOpt << peakOpt; par[3] = strpeakOpt.str(); par[4] = rb_params; // --- Create a GroupingWorkspace for this detector name ------ CPUTimer tim; IAlgorithm_sptr alg2 = AlgorithmFactory::Instance().create("CreateGroupingWorkspace", 1); alg2->initialize(); alg2->setProperty("InputWorkspace", inputW); alg2->setPropertyValue("GroupNames", detList[det]->getName()); std::string groupWSName = "group_" + detList[det]->getName(); alg2->setPropertyValue("OutputWorkspace", groupWSName); alg2->executeAsChildAlg(); par[5] = groupWSName; std::cout << tim << " to CreateGroupingWorkspace\n"; const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex; gsl_multimin_fminimizer *s = nullptr; gsl_vector *ss, *x; gsl_multimin_function minex_func; // finally do the fitting int nopt = 6; int iter = 0; int status = 0; /* Starting point */ x = gsl_vector_alloc(nopt); gsl_vector_set(x, 0, 0.0); gsl_vector_set(x, 1, 0.0); gsl_vector_set(x, 2, 0.0); gsl_vector_set(x, 3, 0.0); gsl_vector_set(x, 4, 0.0); gsl_vector_set(x, 5, 0.0); /* Set initial step sizes to 0.1 */ ss = gsl_vector_alloc(nopt); gsl_vector_set_all(ss, 0.1); /* Initialize method and iterate */ minex_func.n = nopt; minex_func.f = &Mantid::Algorithms::gsl_costFunction; minex_func.params = ∥ s = gsl_multimin_fminimizer_alloc(T, nopt); gsl_multimin_fminimizer_set(s, &minex_func, x, ss); do { iter++; status = gsl_multimin_fminimizer_iterate(s); if (status) break; double size = gsl_multimin_fminimizer_size(s); status = gsl_multimin_test_size(size, 1e-2); } while (status == GSL_CONTINUE && iter < maxIterations && s->fval != -0.000); // Output summary to log file if (s->fval != -0.000) movedetector(gsl_vector_get(s->x, 0), gsl_vector_get(s->x, 1), gsl_vector_get(s->x, 2), gsl_vector_get(s->x, 3), gsl_vector_get(s->x, 4), gsl_vector_get(s->x, 5), par[0], getProperty("InputWorkspace")); else { gsl_vector_set(s->x, 0, 0.0); gsl_vector_set(s->x, 1, 0.0); gsl_vector_set(s->x, 2, 0.0); gsl_vector_set(s->x, 3, 0.0); gsl_vector_set(s->x, 4, 0.0); gsl_vector_set(s->x, 5, 0.0); } std::string reportOfDiffractionEventCalibrateDetectors = gsl_strerror(status); if (s->fval == -0.000) reportOfDiffractionEventCalibrateDetectors = "No events"; g_log.information() << "Detector = " << det << "\n" << "Method used = " << "Simplex" << "\n" << "Iteration = " << iter << "\n" << "Status = " << reportOfDiffractionEventCalibrateDetectors << "\n" << "Minimize PeakLoc-" << peakOpt << " = " << s->fval << "\n"; // Move in cm for small shifts g_log.information() << "Move (X) = " << gsl_vector_get(s->x, 0) * 0.01 << " \n"; g_log.information() << "Move (Y) = " << gsl_vector_get(s->x, 1) * 0.01 << " \n"; g_log.information() << "Move (Z) = " << gsl_vector_get(s->x, 2) * 0.01 << " \n"; g_log.information() << "Rotate (X) = " << gsl_vector_get(s->x, 3) << " \n"; g_log.information() << "Rotate (Y) = " << gsl_vector_get(s->x, 4) << " \n"; g_log.information() << "Rotate (Z) = " << gsl_vector_get(s->x, 5) << " \n"; Kernel::V3D CalCenter = V3D(gsl_vector_get(s->x, 0) * 0.01, gsl_vector_get(s->x, 1) * 0.01, gsl_vector_get(s->x, 2) * 0.01); Kernel::V3D Center = detList[det]->getPos() + CalCenter; int pixmax = detList[det]->xpixels() - 1; int pixmid = (detList[det]->ypixels() - 1) / 2; BoundingBox box; detList[det]->getAtXY(pixmax, pixmid)->getBoundingBox(box); double baseX = box.xMax(); double baseY = box.yMax(); double baseZ = box.zMax(); Kernel::V3D Base = V3D(baseX, baseY, baseZ) + CalCenter; pixmid = (detList[det]->xpixels() - 1) / 2; pixmax = detList[det]->ypixels() - 1; detList[det]->getAtXY(pixmid, pixmax)->getBoundingBox(box); double upX = box.xMax(); double upY = box.yMax(); double upZ = box.zMax(); Kernel::V3D Up = V3D(upX, upY, upZ) + CalCenter; Base -= Center; Up -= Center; // Rotate around x baseX = Base[0]; baseY = Base[1]; baseZ = Base[2]; double deg2rad = M_PI / 180.0; double angle = gsl_vector_get(s->x, 3) * deg2rad; Base = V3D(baseX, baseY * cos(angle) - baseZ * sin(angle), baseY * sin(angle) + baseZ * cos(angle)); upX = Up[0]; upY = Up[1]; upZ = Up[2]; Up = V3D(upX, upY * cos(angle) - upZ * sin(angle), upY * sin(angle) + upZ * cos(angle)); // Rotate around y baseX = Base[0]; baseY = Base[1]; baseZ = Base[2]; angle = gsl_vector_get(s->x, 4) * deg2rad; Base = V3D(baseZ * sin(angle) + baseX * cos(angle), baseY, baseZ * cos(angle) - baseX * sin(angle)); upX = Up[0]; upY = Up[1]; upZ = Up[2]; Up = V3D(upZ * cos(angle) - upX * sin(angle), upY, upZ * sin(angle) + upX * cos(angle)); // Rotate around z baseX = Base[0]; baseY = Base[1]; baseZ = Base[2]; angle = gsl_vector_get(s->x, 5) * deg2rad; Base = V3D(baseX * cos(angle) - baseY * sin(angle), baseX * sin(angle) + baseY * cos(angle), baseZ); upX = Up[0]; upY = Up[1]; upZ = Up[2]; Up = V3D(upX * cos(angle) - upY * sin(angle), upX * sin(angle) + upY * cos(angle), upZ); Base.normalize(); Up.normalize(); Center *= 100.0; // << det+1 << " " outfile << "5 " << detList[det]->getName().substr(4) << " " << detList[det]->xpixels() << " " << detList[det]->ypixels() << " " << 100.0 * detList[det]->xsize() << " " << 100.0 * detList[det]->ysize() << " " << "0.2000" << " " << Center.norm() << " "; Center.write(outfile); outfile << " "; Base.write(outfile); outfile << " "; Up.write(outfile); outfile << "\n"; // clean up dynamically allocated gsl stuff gsl_vector_free(x); gsl_vector_free(ss); gsl_multimin_fminimizer_free(s); // Remove the now-unneeded grouping workspace AnalysisDataService::Instance().remove(groupWSName); prog.report(detList[det]->getName()); } // Closing outfile.close(); }
/** * Create an test instrument with n panels of rectangular detectors, *pixels*pixels in size, * a source and spherical sample shape. * * Banks' lower-left corner is at position (0,0,5*banknum) and they go up to *(pixels*0.008, pixels*0.008, Z) * Pixels are 4 mm wide. * * @param progress :: progress indicator * @param num_banks :: number of rectangular banks to create * @param pixels :: number of pixels in each direction. * @param pixelSpacing :: padding between pixels * @param bankDistanceFromSample :: Distance of first bank from sample (defaults *to 5.0m) * @param sourceSampleDistance :: The distance from the source to the sample * @returns A shared pointer to the generated instrument */ Instrument_sptr CreateSampleWorkspace::createTestInstrumentRectangular( API::Progress &progress, int num_banks, int pixels, double pixelSpacing, const double bankDistanceFromSample, const double sourceSampleDistance) { boost::shared_ptr<Instrument> testInst(new Instrument("basic_rect")); // The instrument is going to be set up with z as the beam axis and y as the // vertical axis. testInst->setReferenceFrame( boost::shared_ptr<ReferenceFrame>(new ReferenceFrame(Y, Z, Left, ""))); const double cylRadius(pixelSpacing / 2); const double cylHeight(0.0002); // One object Object_sptr pixelShape = createCappedCylinder( cylRadius, cylHeight, V3D(0.0, -cylHeight / 2.0, 0.0), V3D(0., 1.0, 0.), "pixel-shape"); for (int banknum = 1; banknum <= num_banks; banknum++) { // Make a new bank std::ostringstream bankname; bankname << "bank" << banknum; RectangularDetector *bank = new RectangularDetector(bankname.str()); bank->initialize(pixelShape, pixels, 0.0, pixelSpacing, pixels, 0.0, pixelSpacing, banknum * pixels * pixels, true, pixels); // Mark them all as detectors for (int x = 0; x < pixels; x++) for (int y = 0; y < pixels; y++) { boost::shared_ptr<Detector> detector = bank->getAtXY(x, y); if (detector) // Mark it as a detector (add to the instrument cache) testInst->markAsDetector(detector.get()); } testInst->add(bank); // Set the bank along the z-axis of the instrument. (beam direction). bank->setPos(V3D(0.0, 0.0, bankDistanceFromSample * banknum)); progress.report(); } // Define a source component ObjComponent *source = new ObjComponent("moderator", Object_sptr(new Object), testInst.get()); source->setPos(V3D(0.0, 0.0, -sourceSampleDistance)); testInst->add(source); testInst->markAsSource(source); // Add chopper ObjComponent *chopper = new ObjComponent( "chopper-position", Object_sptr(new Object), testInst.get()); chopper->setPos(V3D(0.0, 0.0, -0.25 * sourceSampleDistance)); testInst->add(chopper); // Define a sample as a simple sphere Object_sptr sampleSphere = createSphere(0.001, V3D(0.0, 0.0, 0.0), "sample-shape"); ObjComponent *sample = new ObjComponent("sample", sampleSphere, testInst.get()); testInst->setPos(0.0, 0.0, 0.0); testInst->add(sample); testInst->markAsSamplePos(sample); return testInst; }
/** * Cross product */ V3D V2D::cross_prod(const V2D &other) const { return V3D(0.0, 0.0, m_x * other.m_y - m_y * other.m_x); }
/** 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; }
void AnvredCorrection::execEvent() { const int64_t numHists = static_cast<int64_t>(m_inputWS->getNumberHistograms()); std::string unitStr = m_inputWS->getAxis(0)->unit()->unitID(); //Create a new outputworkspace with not much in it DataObjects::EventWorkspace_sptr correctionFactors; correctionFactors = boost::dynamic_pointer_cast<EventWorkspace>( API::WorkspaceFactory::Instance().create("EventWorkspace",numHists,2,1) ); correctionFactors->sortAll(TOF_SORT, NULL); //Copy required stuff from it API::WorkspaceFactory::Instance().initializeFromParent(m_inputWS, correctionFactors, true); bool inPlace = (this->getPropertyValue("InputWorkspace") == this->getPropertyValue("OutputWorkspace")); if (inPlace) g_log.debug("Correcting EventWorkspace in-place."); // If sample not at origin, shift cached positions. const V3D samplePos = m_inputWS->getInstrument()->getSample()->getPos(); const V3D pos = m_inputWS->getInstrument()->getSource()->getPos()-samplePos; double L1 = pos.norm(); Progress prog(this,0.0,1.0,numHists); // Loop over the spectra PARALLEL_FOR2(eventW,correctionFactors) for (int64_t i = 0; i < int64_t(numHists); ++i) { PARALLEL_START_INTERUPT_REGION // Copy over bin boundaries const MantidVec& X = eventW->readX(i); correctionFactors->dataX(i) = X; // Get detector position IDetector_const_sptr det; try { det = eventW->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 ) continue; // This is the scattered beam direction Instrument_const_sptr inst = eventW->getInstrument(); V3D dir = det->getPos() - samplePos; double L2 = dir.norm(); // Two-theta = polar angle = scattering angle = between +Z vector and the scattered beam double scattering = dir.angle( V3D(0.0, 0.0, 1.0) ); EventList el = eventW->getEventList(i); el.switchTo(WEIGHTED_NOTIME); std::vector<WeightedEventNoTime> events = el.getWeightedEventsNoTime(); std::vector<WeightedEventNoTime>::iterator itev; std::vector<WeightedEventNoTime>::iterator itev_end = events.end(); Mantid::Kernel::Units::Wavelength wl; std::vector<double> timeflight; // multiplying an event list by a scalar value for (itev = events.begin(); itev != itev_end; itev++) { timeflight.push_back(itev->tof()); if (unitStr.compare("TOF") == 0) wl.fromTOF(timeflight, timeflight, L1, L2, scattering, 0, 0, 0); double value = this->getEventWeight(timeflight[0], scattering); timeflight.clear(); itev->m_errorSquared = static_cast<float>(itev->m_errorSquared * value*value); itev->m_weight *= static_cast<float>(value); } correctionFactors->getOrAddEventList(i) +=events; std::set<detid_t>& dets = eventW->getEventList(i).getDetectorIDs(); std::set<detid_t>::iterator j; for (j = dets.begin(); j != dets.end(); ++j) correctionFactors->getOrAddEventList(i).addDetectorID(*j); // When focussing in place, you can clear out old memory from the input one! if (inPlace) { eventW->getEventList(i).clear(); Mantid::API::MemoryManager::Instance().releaseFreeMemory(); } prog.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION correctionFactors->doneAddingEventLists(); setProperty("OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(correctionFactors)); // Now do some cleaning-up since destructor may not be called immediately this->cleanup(); }
/** Executes the algorithm. * * @throw std::runtime_error Thrown with Workspace problems */ void RotateInstrumentComponent::exec() { // Get the workspace MatrixWorkspace_sptr WS = getProperty("Workspace"); const std::string ComponentName = getProperty("ComponentName"); const int DetID = getProperty("DetectorID"); const double X = getProperty("X"); const double Y = getProperty("Y"); const double Z = getProperty("Z"); const double angle = getProperty("Angle"); const bool RelativeRotation = getProperty("RelativeRotation"); if (X + Y + Z == 0.0) throw std::invalid_argument("The rotation axis must not be a zero vector"); Instrument_const_sptr inst = WS->getInstrument(); IComponent_const_sptr comp; // Find the component to move if (DetID != -1) { comp = inst->getDetector(DetID); if (comp == 0) { std::ostringstream mess; mess<<"Detector with ID "<<DetID<<" was not found."; g_log.error(mess.str()); throw std::runtime_error(mess.str()); } } else if (!ComponentName.empty()) { comp = inst->getComponentByName(ComponentName); if (comp == 0) { std::ostringstream mess; mess<<"Component with name "<<ComponentName<<" was not found."; g_log.error(mess.str()); throw std::runtime_error(mess.str()); } } else { g_log.error("DetectorID or ComponentName must be given."); throw std::invalid_argument("DetectorID or ComponentName must be given."); } // First set new relative or absolute rotation Quat Rot; if (RelativeRotation) { Quat Rot0 = comp->getRelativeRot(); Rot = Rot0 * Quat(angle,V3D(X,Y,Z)); } else { Rot = Quat(angle,V3D(X,Y,Z)); // Then find the corresponding relative position boost::shared_ptr<const IComponent> parent = comp->getParent(); if (parent) { Quat rot0 = parent->getRelativeRot(); rot0.inverse(); Rot = Rot * rot0; } } //Need to get the address to the base instrument component Geometry::ParameterMap& pmap = WS->instrumentParameters(); // Add a parameter for the new rotation pmap.addQuat(comp.get(), "rot", Rot); return; }
/** Execute the algorithm. */ void FindUBUsingIndexedPeaks::exec() { PeaksWorkspace_sptr ws; ws = boost::dynamic_pointer_cast<PeaksWorkspace>( AnalysisDataService::Instance().retrieve(this->getProperty("PeaksWorkspace")) ); if (!ws) { throw std::runtime_error("Could not read the peaks workspace"); } std::vector<Peak> peaks = ws->getPeaks(); size_t n_peaks = ws->getNumberPeaks(); std::vector<V3D> q_vectors; std::vector<V3D> hkl_vectors; q_vectors.reserve( n_peaks ); hkl_vectors.reserve( n_peaks ); size_t indexed_count = 0; for ( size_t i = 0; i < n_peaks; i++ ) { V3D hkl( peaks[i].getH(), peaks[i].getK(), peaks[i].getL() ); // ##### KEEP if ( IndexingUtils::ValidIndex( hkl, 1.0 ) ) // use tolerance == 1 to // just check for (0,0,0) { q_vectors.push_back( peaks[i].getQSampleFrame() ); V3D miller_ind( round(hkl[0]), round(hkl[1]), round(hkl[2]) ); hkl_vectors.push_back( V3D(miller_ind) ); indexed_count++; } } if ( indexed_count < 3 ) { throw std::runtime_error( "At least three linearly independent indexed peaks are needed."); } Matrix<double> UB(3,3,false); double error = IndexingUtils::Optimize_UB( UB, hkl_vectors, q_vectors ); std::cout << "Error = " << error << std::endl; std::cout << "UB = " << UB << std::endl; if ( ! IndexingUtils::CheckUB( UB ) ) // UB not found correctly { g_log.notice( std::string( "Found Invalid UB...peaks used might not be linearly independent") ); g_log.notice( std::string( "UB NOT SAVED.") ); } else // tell user how many would be indexed { // from the full list of peaks, and q_vectors.clear(); // save the UB in the sample q_vectors.reserve( n_peaks ); for ( size_t i = 0; i < n_peaks; i++ ) { q_vectors.push_back( peaks[i].getQSampleFrame() ); } double tolerance = 0.1; int num_indexed = IndexingUtils::NumberIndexed(UB, q_vectors, tolerance); char logInfo[200]; sprintf( logInfo, std::string("New UB will index %1d Peaks out of %1d with tolerance %5.3f").c_str(), num_indexed, n_peaks, tolerance); g_log.notice( std::string(logInfo) ); OrientedLattice o_lattice; o_lattice.setUB( UB ); double calc_a = o_lattice.a(); double calc_b = o_lattice.b(); double calc_c = o_lattice.c(); double calc_alpha = o_lattice.alpha(); double calc_beta = o_lattice.beta(); double calc_gamma = o_lattice.gamma(); // Show the modified lattice parameters sprintf( logInfo, std::string("Lattice Parameters: %8.3f %8.3f %8.3f %8.3f %8.3f %8.3f").c_str(), calc_a, calc_b, calc_c, calc_alpha, calc_beta, calc_gamma); g_log.notice( std::string(logInfo) ); ws->mutableSample().setOrientedLattice( new OrientedLattice(o_lattice) ); } }