/** * Updates the map from run number to GoniometerMatrix * * @param Peaks The PeaksWorkspace whose peaks contain the run numbers * along with the corresponding GoniometerMatrix * * @param OptRuns A '/' separated "list" of run numbers to include in the * map. This string must also start and end with a '/' * * @param Res The resultant map. */ void PeakHKLErrors::getRun2MatMap( PeaksWorkspace_sptr &Peaks, const std::string &OptRuns, std::map<int, Mantid::Kernel::Matrix<double>> &Res) const { for (int i = 0; i < Peaks->getNumberPeaks(); ++i) { Geometry::IPeak &peak_old = Peaks->getPeak(i); int runNum = peak_old.getRunNumber(); std::string runNumStr = std::to_string(runNum); size_t N = OptRuns.find("/" + runNumStr + "/"); if (N < OptRuns.size()) { double chi = getParameter("chi" + boost::lexical_cast<std::string>(runNumStr)); double phi = getParameter("phi" + boost::lexical_cast<std::string>(runNumStr)); double omega = getParameter("omega" + boost::lexical_cast<std::string>(runNumStr)); Mantid::Geometry::Goniometer uniGonio; uniGonio.makeUniversalGoniometer(); uniGonio.setRotationAngle("phi", phi); uniGonio.setRotationAngle("chi", chi); uniGonio.setRotationAngle("omega", omega); Res[runNum] = uniGonio.getR(); } } }
/// Fills possibleHKLs with all HKLs from the supplied PeaksWorkspace. void PredictPeaks::fillPossibleHKLsUsingPeaksWorkspace( const PeaksWorkspace_sptr &peaksWorkspace, std::vector<V3D> &possibleHKLs) const { possibleHKLs.clear(); possibleHKLs.reserve(peaksWorkspace->getNumberPeaks()); bool roundHKL = getProperty("RoundHKL"); /* Q is at the end multiplied with the factor determined in the * constructor (-1 for crystallography, 1 otherwise). So to avoid * "flippling HKLs" when it's not required, the HKLs of the input * workspace are also multiplied by the factor that is appropriate * for the convention stored in the workspace. */ double peaks_q_convention_factor = get_factor_for_q_convention(peaksWorkspace->getConvention()); for (int i = 0; i < static_cast<int>(peaksWorkspace->getNumberPeaks()); ++i) { IPeak &p = peaksWorkspace->getPeak(i); // Get HKL from that peak V3D hkl = p.getHKL() * peaks_q_convention_factor; if (roundHKL) hkl.round(); possibleHKLs.push_back(hkl); } // for each hkl in the workspace }
/// Returns a PeaksWorkspace which is either the input workspace or a clone. PeaksWorkspace_sptr SortHKL::getOutputPeaksWorkspace( const PeaksWorkspace_sptr &inputPeaksWorkspace) const { PeaksWorkspace_sptr outputPeaksWorkspace = getProperty("OutputWorkspace"); if (outputPeaksWorkspace != inputPeaksWorkspace) { outputPeaksWorkspace.reset(inputPeaksWorkspace->clone().release()); } return outputPeaksWorkspace; }
/** 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)); }
/** @param inname Name of workspace containing peaks @param params optimized cell parameters @param out residuals from optimization */ void OptimizeLatticeForCellType::optLattice(std::string inname, std::vector<double> ¶ms, double *out) { PeaksWorkspace_sptr ws = boost::dynamic_pointer_cast<PeaksWorkspace>( AnalysisDataService::Instance().retrieve(inname)); const std::vector<Peak> &peaks = ws->getPeaks(); size_t n_peaks = ws->getNumberPeaks(); std::vector<V3D> q_vector; std::vector<V3D> hkl_vector; for (size_t i = 0; i < params.size(); i++) params[i] = std::abs(params[i]); for (size_t i = 0; i < n_peaks; i++) { q_vector.push_back(peaks[i].getQSampleFrame()); hkl_vector.push_back(peaks[i].getHKL()); } Mantid::API::IAlgorithm_sptr alg = createChildAlgorithm("CalculateUMatrix"); alg->setPropertyValue("PeaksWorkspace", inname); alg->setProperty("a", params[0]); alg->setProperty("b", params[1]); alg->setProperty("c", params[2]); alg->setProperty("alpha", params[3]); alg->setProperty("beta", params[4]); alg->setProperty("gamma", params[5]); alg->executeAsChildAlg(); ws = alg->getProperty("PeaksWorkspace"); OrientedLattice latt = ws->mutableSample().getOrientedLattice(); DblMatrix UB = latt.getUB(); DblMatrix A = aMatrix(params); DblMatrix Bc = A; Bc.Invert(); DblMatrix U1_B1 = UB * A; OrientedLattice o_lattice; o_lattice.setUB(U1_B1); DblMatrix U1 = o_lattice.getU(); DblMatrix U1_Bc = U1 * Bc; for (size_t i = 0; i < hkl_vector.size(); i++) { V3D error = U1_Bc * hkl_vector[i] - q_vector[i] / (2.0 * M_PI); out[i] = error.norm2(); } return; }
/** Count the peaks from a .peaks file and compare with the workspace * @param outWS :: the workspace in which to place the information * @param filename :: path to the .peaks file */ void LoadIsawPeaks::checkNumberPeaks( PeaksWorkspace_sptr outWS, std::string filename ) { // Open the file std::ifstream in( filename.c_str() ); std::string first; int NumberPeaks = 0; while (getline(in,first)) { if (first[0] == '3')NumberPeaks++; } if(NumberPeaks != outWS->getNumberPeaks()) { g_log.error()<<"Number of peaks in file is " << NumberPeaks << " but only read " <<outWS->getNumberPeaks() << std::endl; throw std::length_error("Wrong number of peaks read"); } }
/// Fills possibleHKLs with all HKLs from the supplied PeaksWorkspace. void PredictPeaks::fillPossibleHKLsUsingPeaksWorkspace( const PeaksWorkspace_sptr &peaksWorkspace, std::vector<V3D> &possibleHKLs) const { possibleHKLs.clear(); possibleHKLs.reserve(peaksWorkspace->getNumberPeaks()); bool roundHKL = getProperty("RoundHKL"); for (int i = 0; i < static_cast<int>(peaksWorkspace->getNumberPeaks()); ++i) { IPeak &p = peaksWorkspace->getPeak(i); // Get HKL from that peak V3D hkl = p.getHKL(); if (roundHKL) hkl.round(); possibleHKLs.push_back(hkl); } // for each hkl in the workspace }
/** * Checks that a PeaksWorkspace has only one run. * * @param Peaks The PeaksWorkspace * @param GoniometerMatrix the goniometer matrix for the run */ bool GoniometerAnglesFromPhiRotation::CheckForOneRun( const PeaksWorkspace_sptr &Peaks, Kernel::Matrix<double> &GoniometerMatrix) const { int RunNumber = -1; for (int peak = 0; peak < Peaks->getNumberPeaks(); peak++) { int thisRunNum = Peaks->getPeak(peak).getRunNumber(); GoniometerMatrix = Peaks->getPeak(peak).getGoniometerMatrix(); if (RunNumber < 0) RunNumber = thisRunNum; else if (thisRunNum != RunNumber) return false; } return true; }
/** * Creates a new parameterized instrument for which the parameter values can be *changed * * @param Peaks - a PeaksWorkspace used to get the original instrument. The *instrument from the 0th peak is * the one that is used. * * NOTE: All the peaks in the PeaksWorkspace must use the same instrument. */ boost::shared_ptr<Geometry::Instrument> PeakHKLErrors::getNewInstrument(PeaksWorkspace_sptr Peaks) const { Geometry::Instrument_const_sptr instSave = Peaks->getPeak(0).getInstrument(); auto pmap = boost::make_shared<Geometry::ParameterMap>(); if (!instSave) { g_log.error(" Peaks workspace does not have an instrument"); throw std::invalid_argument(" Not all peaks have an instrument"); } if (!hasParameterMap) { pmapSv = instSave->getParameterMap(); hasParameterMap = true; if (!instSave->isParametrized()) { boost::shared_ptr<Geometry::Instrument> instClone(instSave->clone()); auto Pinsta = boost::make_shared<Geometry::Instrument>(instSave, pmap); instChange = Pinsta; IComponent_const_sptr sample = instChange->getSample(); sampPos = sample->getRelativePos(); } else // catch(... ) { auto P1 = boost::make_shared<Geometry::Instrument>( instSave->baseInstrument(), instSave->makeLegacyParameterMap()); instChange = P1; IComponent_const_sptr sample = instChange->getSample(); sampPos = sample->getRelativePos(); } } if (!instChange) { g_log.error("Cannot 'clone' instrument"); throw std::logic_error("Cannot clone instrument"); } //------------------"clone" orig instruments pmap ------------------- cLone(pmap, instSave, pmapSv); V3D sampOffsets(getParameter("SampleXOffset"), getParameter("SampleYOffset"), getParameter("SampleZOffset")); IComponent_const_sptr sample = instChange->getSample(); pmap->addPositionCoordinate(sample.get(), std::string("x"), sampPos.X() + sampOffsets.X()); pmap->addPositionCoordinate(sample.get(), std::string("y"), sampPos.Y() + sampOffsets.Y()); pmap->addPositionCoordinate(sample.get(), std::string("z"), sampPos.Z() + sampOffsets.Z()); return instChange; }
/** @param ws Name of workspace containing peaks @param bankName Name of bank containing peak @param col Column number containing peak @param row Row number containing peak @param Edge Number of edge points for each bank @return True if peak is on edge */ bool OptimizeLatticeForCellType::edgePixel(PeaksWorkspace_sptr ws, std::string bankName, int col, int row, int Edge) { if (bankName.compare("None") == 0) return false; Geometry::Instrument_const_sptr Iptr = ws->getInstrument(); boost::shared_ptr<const IComponent> parent = Iptr->getComponentByName(bankName); if (parent->type().compare("RectangularDetector") == 0) { boost::shared_ptr<const RectangularDetector> RDet = boost::dynamic_pointer_cast<const RectangularDetector>(parent); return col < Edge || col >= (RDet->xpixels() - Edge) || row < Edge || row >= (RDet->ypixels() - Edge); } else { std::vector<Geometry::IComponent_const_sptr> children; boost::shared_ptr<const Geometry::ICompAssembly> asmb = boost::dynamic_pointer_cast<const Geometry::ICompAssembly>(parent); asmb->getChildren(children, false); int startI = 1; if (children[0]->getName() == "sixteenpack") { startI = 0; parent = children[0]; children.clear(); boost::shared_ptr<const Geometry::ICompAssembly> asmb = boost::dynamic_pointer_cast<const Geometry::ICompAssembly>(parent); asmb->getChildren(children, false); } boost::shared_ptr<const Geometry::ICompAssembly> asmb2 = boost::dynamic_pointer_cast<const Geometry::ICompAssembly>(children[0]); std::vector<Geometry::IComponent_const_sptr> grandchildren; asmb2->getChildren(grandchildren, false); int NROWS = static_cast<int>(grandchildren.size()); int NCOLS = static_cast<int>(children.size()); // Wish pixels and tubes start at 1 not 0 return col - startI < Edge || col - startI >= (NCOLS - Edge) || row - startI < Edge || row - startI >= (NROWS - Edge); } return false; }
void PeakHKLErrors::functionDeriv1D(Jacobian *out, const double *xValues, const size_t nData) { PeaksWorkspace_sptr Peaks = AnalysisDataService::Instance().retrieveWS<PeaksWorkspace>( PeakWorkspaceName); boost::shared_ptr<Geometry::Instrument> instNew = getNewInstrument(Peaks); const DblMatrix &UB = Peaks->sample().getOrientedLattice().getUB(); DblMatrix UBinv(UB); UBinv.Invert(); UBinv /= 2 * M_PI; double GonRotx = getParameter("GonRotx"); double GonRoty = getParameter("GonRoty"); double GonRotz = getParameter("GonRotz"); Matrix<double> InvGonRotxMat = RotationMatrixAboutRegAxis(GonRotx, 'x'); Matrix<double> InvGonRotyMat = RotationMatrixAboutRegAxis(GonRoty, 'y'); Matrix<double> InvGonRotzMat = RotationMatrixAboutRegAxis(GonRotz, 'z'); Matrix<double> GonRot = InvGonRotxMat * InvGonRotyMat * InvGonRotzMat; InvGonRotxMat.Invert(); InvGonRotyMat.Invert(); InvGonRotzMat.Invert(); std::map<int, Kernel::Matrix<double>> RunNums2GonMatrix; getRun2MatMap(Peaks, OptRuns, RunNums2GonMatrix); g_log.debug() << "----------------------------Derivative------------------------\n"; V3D samplePosition = instNew->getSample()->getPos(); IPeak &ppeak = Peaks->getPeak(0); double L0 = ppeak.getL1(); double velocity = (L0 + ppeak.getL2()) / ppeak.getTOF(); double K = 2 * M_PI / ppeak.getWavelength() / velocity; // 2pi/lambda = K* velocity V3D beamDir = instNew->getBeamDirection(); size_t paramNums[] = {parameterIndex(std::string("SampleXOffset")), parameterIndex(std::string("SampleYOffset")), parameterIndex(std::string("SampleZOffset"))}; for (size_t i = 0; i < nData; i += 3) { int peakNum = boost::math::iround(xValues[i]); IPeak &peak_old = Peaks->getPeak(peakNum); Peak peak = createNewPeak(peak_old, instNew, 0, peak_old.getL1()); int runNum = peak_old.getRunNumber(); std::string runNumStr = std::to_string(runNum); for (int kk = 0; kk < static_cast<int>(nParams()); kk++) { out->set(i, kk, 0.0); out->set(i + 1, kk, 0.0); out->set(i + 2, kk, 0.0); } double chi, phi, omega; size_t chiParamNum, phiParamNum, omegaParamNum; size_t N = OptRuns.find("/" + runNumStr); if (N < OptRuns.size()) { chi = getParameter("chi" + (runNumStr)); phi = getParameter("phi" + (runNumStr)); omega = getParameter("omega" + (runNumStr)); peak.setGoniometerMatrix(GonRot * RunNums2GonMatrix[runNum]); chiParamNum = parameterIndex("chi" + (runNumStr)); phiParamNum = parameterIndex("phi" + (runNumStr)); omegaParamNum = parameterIndex("omega" + (runNumStr)); } else { Geometry::Goniometer Gon(peak.getGoniometerMatrix()); std::vector<double> phichiOmega = Gon.getEulerAngles("YZY"); chi = phichiOmega[1]; phi = phichiOmega[2]; omega = phichiOmega[0]; // peak.setGoniometerMatrix( GonRot*Gon.getR()); chiParamNum = phiParamNum = omegaParamNum = nParams() + 10; peak.setGoniometerMatrix(GonRot * peak.getGoniometerMatrix()); } V3D sampOffsets(getParameter("SampleXOffset"), getParameter("SampleYOffset"), getParameter("SampleZOffset")); peak.setSamplePos(peak.getSamplePos() + sampOffsets); // NOTE:Use getQLabFrame except for below. // For parameters the getGoniometerMatrix should remove GonRot, for derivs // wrt GonRot*, wrt chi*,phi*,etc. // Deriv wrt chi phi and omega if (phiParamNum < nParams()) { Matrix<double> chiMatrix = RotationMatrixAboutRegAxis(chi, 'z'); Matrix<double> phiMatrix = RotationMatrixAboutRegAxis(phi, 'y'); Matrix<double> omegaMatrix = RotationMatrixAboutRegAxis(omega, 'y'); Matrix<double> dchiMatrix = DerivRotationMatrixAboutRegAxis(chi, 'z'); Matrix<double> dphiMatrix = DerivRotationMatrixAboutRegAxis(phi, 'y'); Matrix<double> domegaMatrix = DerivRotationMatrixAboutRegAxis(omega, 'y'); Matrix<double> InvG = omegaMatrix * chiMatrix * phiMatrix; InvG.Invert(); // Calculate Derivatives wrt chi(phi,omega) in degrees Matrix<double> R = omegaMatrix * chiMatrix * dphiMatrix; Matrix<double> InvR = InvG * R * InvG * -1; V3D lab = peak.getQLabFrame(); V3D Dhkl0 = UBinv * InvR * lab; R = omegaMatrix * dchiMatrix * phiMatrix; InvR = InvG * R * InvG * -1; V3D Dhkl1 = UBinv * InvR * peak.getQLabFrame(); R = domegaMatrix * chiMatrix * phiMatrix; InvR = InvG * R * InvG * -1; V3D Dhkl2 = UBinv * InvR * peak.getQLabFrame(); // R.transpose should be R inverse out->set(i, chiParamNum, Dhkl1[0]); out->set(i + 1, chiParamNum, Dhkl1[1]); out->set(i + 2, chiParamNum, Dhkl1[2]); out->set(i, phiParamNum, Dhkl0[0]); out->set(i + 1, phiParamNum, Dhkl0[1]); out->set(i + 2, phiParamNum, Dhkl0[2]); out->set(i, omegaParamNum, Dhkl2[0]); out->set(i + 1, omegaParamNum, Dhkl2[1]); out->set(i + 2, omegaParamNum, Dhkl2[2]); } // if optimize for chi phi and omega on this peak //------------------------Goniometer Rotation Derivatives //----------------------- Matrix<double> InvGonRot(GonRot); InvGonRot.Invert(); Matrix<double> InvGon = InvGonRot * peak.getGoniometerMatrix(); InvGon.Invert(); V3D DGonx = (UBinv * InvGon * InvGonRotzMat * InvGonRotyMat * DerivRotationMatrixAboutRegAxis( -GonRotx, 'x') * // - gives inverse of GonRot peak.getQLabFrame()) * -1; V3D DGony = (UBinv * InvGon * InvGonRotzMat * DerivRotationMatrixAboutRegAxis(-GonRoty, 'y') * InvGonRotxMat * peak.getQLabFrame()) * -1; V3D DGonz = (UBinv * InvGon * DerivRotationMatrixAboutRegAxis(-GonRotz, 'z') * InvGonRotyMat * InvGonRotxMat * peak.getQLabFrame()) * -1; size_t paramnum = parameterIndex("GonRotx"); out->set(i, paramnum, DGonx[0]); out->set(i + 1, paramnum, DGonx[1]); out->set(i + 2, paramnum, DGonx[2]); out->set(i, parameterIndex("GonRoty"), DGony[0]); out->set(i + 1, parameterIndex("GonRoty"), DGony[1]); out->set(i + 2, parameterIndex("GonRoty"), DGony[2]); out->set(i, parameterIndex("GonRotz"), DGonz[0]); out->set(i + 1, parameterIndex("GonRotz"), DGonz[1]); out->set(i + 2, parameterIndex("GonRotz"), DGonz[2]); //-------------------- Sample Orientation derivatives //---------------------------------- // Qlab = -KV + k|V|*beamdir // D = pos-sampPos //|V|= vmag=(L0 + D )/tof // t1= tof - L0/|V| {time from sample to pixel} // V = D/t1 V3D D = peak.getDetPos() - samplePosition; double vmag = (L0 + D.norm()) / peak.getTOF(); double t1 = peak.getTOF() - L0 / vmag; // Derivs wrt sample x, y, z // Ddsx =( - 1, 0, 0), d|D|^2/dsx -> 2|D|d|D|/dsx =d(tranp(D)* D)/dsx =2 // Ddsx* tranp(D) //|D| also called Dmag V3D Dmagdsxsysz(D); Dmagdsxsysz *= (-1 / D.norm()); V3D vmagdsxsysz = Dmagdsxsysz / peak.getTOF(); V3D t1dsxsysz = vmagdsxsysz * (L0 / vmag / vmag); Matrix<double> Gon = peak.getGoniometerMatrix(); Gon.Invert(); // x=0 is deriv wrt SampleXoffset, x=1 is deriv wrt SampleYoffset, etc. for (int x = 0; x < 3; x++) { V3D pp; pp[x] = 1; V3D dQlab1 = pp / -t1 - D * (t1dsxsysz[x] / t1 / t1); V3D dQlab2 = beamDir * vmagdsxsysz[x]; V3D dQlab = dQlab2 - dQlab1; dQlab *= K; V3D dQSamp = Gon * dQlab; V3D dhkl = UBinv * dQSamp; out->set(i, paramNums[x], dhkl[0]); out->set(i + 1, paramNums[x], dhkl[1]); out->set(i + 2, paramNums[x], dhkl[2]); } } }
/** 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)); }
int PeakIntegration::fitneighbours(int ipeak, std::string det_name, int x0, int y0, int idet, double qspan, PeaksWorkspace_sptr &Peaks, const detid2index_map &pixel_to_wi) { UNUSED_ARG(ipeak); UNUSED_ARG(det_name); UNUSED_ARG(x0); UNUSED_ARG(y0); Geometry::IPeak &peak = Peaks->getPeak(ipeak); // Number of slices int TOFmax = 0; IAlgorithm_sptr slice_alg = createChildAlgorithm("IntegratePeakTimeSlices"); slice_alg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", inputW); std::ostringstream tab_str; tab_str << "LogTable" << ipeak; slice_alg->setPropertyValue("OutputWorkspace", tab_str.str()); slice_alg->setProperty<PeaksWorkspace_sptr>("Peaks", Peaks); slice_alg->setProperty("PeakIndex", ipeak); slice_alg->setProperty("PeakQspan", qspan); int nPixels = std::max<int>(0, getProperty("NBadEdgePixels")); slice_alg->setProperty("NBadEdgePixels", nPixels); slice_alg->executeAsChildAlg(); Mantid::API::MemoryManager::Instance().releaseFreeMemory(); MantidVec &Xout = outputW->dataX(idet); MantidVec &Yout = outputW->dataY(idet); MantidVec &Eout = outputW->dataE(idet); TableWorkspace_sptr logtable = slice_alg->getProperty("OutputWorkspace"); peak.setIntensity(slice_alg->getProperty("Intensity")); peak.setSigmaIntensity(slice_alg->getProperty("SigmaIntensity")); TOFmax = static_cast<int>(logtable->rowCount()); for (int iTOF = 0; iTOF < TOFmax; iTOF++) { Xout[iTOF] = logtable->getRef<double>(std::string("Time"), iTOF); if (m_IC) // Ikeda-Carpenter fit { Yout[iTOF] = logtable->getRef<double>(std::string("TotIntensity"), iTOF); Eout[iTOF] = logtable->getRef<double>(std::string("TotIntensityError"), iTOF); } else { Yout[iTOF] = logtable->getRef<double>(std::string("ISAWIntensity"), iTOF); Eout[iTOF] = logtable->getRef<double>(std::string("ISAWIntensityError"), iTOF); } } outputW->getSpectrum(idet)->clearDetectorIDs(); // Find the pixel ID at that XY position on the rectangular detector int pixelID = peak.getDetectorID(); // det->getAtXY(x0,y0)->getID(); // Find the corresponding workspace index, if any auto wiEntry = pixel_to_wi.find(pixelID); if (wiEntry != pixel_to_wi.end()) { size_t wi = wiEntry->second; // Set detectorIDs outputW->getSpectrum(idet) ->addDetectorIDs(inputW->getSpectrum(wi)->getDetectorIDs()); } return TOFmax - 1; }
/** @param inname Name of Filename containing peaks @param cell_type cell type to optimize @param params optimized cell parameters @return chisq of optimization */ double OptimizeLatticeForCellType::optLatticeSum(std::string inname, std::string cell_type, std::vector<double> ¶ms) { std::vector<double> lattice_parameters; lattice_parameters.assign(6, 0); if (cell_type == ReducedCell::CUBIC()) { lattice_parameters[0] = params[0]; lattice_parameters[1] = params[0]; lattice_parameters[2] = params[0]; lattice_parameters[3] = 90; lattice_parameters[4] = 90; lattice_parameters[5] = 90; } else if (cell_type == ReducedCell::TETRAGONAL()) { lattice_parameters[0] = params[0]; lattice_parameters[1] = params[0]; lattice_parameters[2] = params[1]; lattice_parameters[3] = 90; lattice_parameters[4] = 90; lattice_parameters[5] = 90; } else if (cell_type == ReducedCell::ORTHORHOMBIC()) { lattice_parameters[0] = params[0]; lattice_parameters[1] = params[1]; lattice_parameters[2] = params[2]; lattice_parameters[3] = 90; lattice_parameters[4] = 90; lattice_parameters[5] = 90; } else if (cell_type == ReducedCell::RHOMBOHEDRAL()) { lattice_parameters[0] = params[0]; lattice_parameters[1] = params[0]; lattice_parameters[2] = params[0]; lattice_parameters[3] = params[1]; lattice_parameters[4] = params[1]; lattice_parameters[5] = params[1]; } else if (cell_type == ReducedCell::HEXAGONAL()) { lattice_parameters[0] = params[0]; lattice_parameters[1] = params[0]; lattice_parameters[2] = params[1]; lattice_parameters[3] = 90; lattice_parameters[4] = 90; lattice_parameters[5] = 120; } else if (cell_type == "Monoclinic ( a unique )") { lattice_parameters[0] = params[0]; lattice_parameters[1] = params[1]; lattice_parameters[2] = params[2]; lattice_parameters[3] = params[3]; lattice_parameters[4] = 90; lattice_parameters[5] = 90; } else if (cell_type == ReducedCell::MONOCLINIC() || cell_type == "Monoclinic ( b unique )") { lattice_parameters[0] = params[0]; lattice_parameters[1] = params[1]; lattice_parameters[2] = params[2]; lattice_parameters[3] = 90; lattice_parameters[4] = params[3]; lattice_parameters[5] = 90; } else if (cell_type == "Monoclinic ( c unique )") { lattice_parameters[0] = params[0]; lattice_parameters[1] = params[1]; lattice_parameters[2] = params[2]; lattice_parameters[3] = 90; lattice_parameters[4] = 90; lattice_parameters[5] = params[3]; } else if (cell_type == ReducedCell::TRICLINIC()) { lattice_parameters[0] = params[0]; lattice_parameters[1] = params[1]; lattice_parameters[2] = params[2]; lattice_parameters[3] = params[3]; lattice_parameters[4] = params[4]; lattice_parameters[5] = params[5]; } PeaksWorkspace_sptr ws = boost::dynamic_pointer_cast<PeaksWorkspace>( AnalysisDataService::Instance().retrieve(inname)); size_t n_peaks = ws->getNumberPeaks(); double *out = new double[n_peaks]; optLattice(inname, lattice_parameters, out); double ChiSqTot = 0; for (size_t i = 0; i < n_peaks; i++) ChiSqTot += out[i]; delete[] out; return ChiSqTot; }
/** Append the peaks from a .peaks file into the workspace * @param outWS :: the workspace in which to place the information * @param filename :: path to the .peaks file */ void LoadIsawPeaks::appendFile( PeaksWorkspace_sptr outWS, std::string filename ) { // Open the file std::ifstream in( filename.c_str() ); // Read the header, load the instrument double T0; std::string s = readHeader( outWS, in , T0); // set T0 in the run parameters API::Run & m_run = outWS->mutableRun(); m_run.addProperty<double>("T0", T0, true); if( !in.good() || s.length() < 1 ) throw std::runtime_error( "End of Peaks file before peaks" ); if( s.compare( std::string( "0" ) ) != 0 ) throw std::logic_error( "No header for Peak segments" ); readToEndOfLine( in , true ); s = getWord( in , false ); int run, bankNum; double chi , phi , omega , monCount; // Build the universal goniometer that will build the rotation matrix. Mantid::Geometry::Goniometer uniGonio; uniGonio.makeUniversalGoniometer(); // TODO: Can we find the number of peaks to get better progress reporting? Progress prog(this, 0.0, 1.0, 100); while( in.good() ) { // Read the header if necessary s = readPeakBlockHeader( s , in , run , bankNum , chi , phi , omega , monCount ); // Build the Rotation matrix using phi,chi,omega uniGonio.setRotationAngle("phi", phi); uniGonio.setRotationAngle("chi", chi); uniGonio.setRotationAngle("omega", omega); //Put goniometer into peaks workspace outWS->mutableRun().setGoniometer(uniGonio, false); std::ostringstream oss; std::string bankString = "bank"; if (outWS->getInstrument()->getName() == "WISH") bankString = "WISHpanel0"; oss << bankString << bankNum; std::string bankName = oss.str(); int seqNum = -1; try { // Read the peak Peak peak = readPeak(outWS, s, in, seqNum, bankName); // Get the calculated goniometer matrix Matrix<double> gonMat = uniGonio.getR(); peak.setGoniometerMatrix(gonMat); peak.setRunNumber(run); peak.setMonitorCount( monCount ); double tof = peak.getTOF(); Kernel::Units::Wavelength wl; wl.initialize(peak.getL1(), peak.getL2(), peak.getScattering(), 0, peak.getInitialEnergy(), 0.0); peak.setWavelength(wl.singleFromTOF( tof)); // Add the peak to workspace outWS->addPeak(peak); } catch (std::runtime_error & e) { g_log.warning() << "Error reading peak SEQN " << seqNum << " : " << e.what() << std::endl; } prog.report(); } }
/** Read one peak in a line of an ISAW peaks file. * * @param outWS :: workspace to add peaks to * @param lastStr [in,out] :: last word (the one at the start of the line) * @param in :: input stream * @param seqNum [out] :: the sequence number of the peak * @param bankName :: the bank number from the ISAW file. * @return the Peak the Peak object created */ Mantid::DataObjects::Peak readPeak( PeaksWorkspace_sptr outWS, std::string & lastStr, std::ifstream& in, int & seqNum, std::string bankName) { double h ; double k ; double l ; double col ; double row ; double wl ; double IPK ; double Inti ; double SigI ; seqNum = -1; std::string s = lastStr; if( s.length() < 1 && in.good() )//blank line { readToEndOfLine( in , true ); s = getWord( in , false );; } if( s.length() < 1 ) throw std::runtime_error("Empty peak line encountered."); if( s.compare( "2" ) == 0 ) { readToEndOfLine( in , true ); for( s = getWord( in , false ) ; s.length() < 1 && in.good() ; s = getWord( in , true ) ) { s = getWord( in , false ); } } if( s.length() < 1 ) throw std::runtime_error("Empty peak line encountered."); if( s.compare( "3" ) != 0 ) throw std::runtime_error("Empty peak line encountered."); seqNum = atoi( getWord( in , false ).c_str() ); h = strtod( getWord( in , false ).c_str() , 0 ) ; k = strtod( getWord( in , false ).c_str() , 0 ) ; l = strtod( getWord( in , false ).c_str() , 0 ) ; col = strtod( getWord( in , false ).c_str() , 0 ) ; row = strtod( getWord( in , false ).c_str() , 0 ) ; strtod( getWord( in , false ).c_str() , 0 ) ; //chan strtod( getWord( in , false ).c_str() , 0 ) ; //L2 strtod( getWord( in , false ).c_str() , 0 ) ; //ScatAng strtod( getWord( in , false ).c_str() , 0 ) ; //Az wl = strtod( getWord( in , false ).c_str() , 0 ) ; strtod( getWord( in , false ).c_str() , 0 ) ; //D IPK = strtod( getWord( in , false ).c_str() , 0 ) ; Inti = strtod( getWord( in , false ).c_str() , 0 ) ; SigI = strtod( getWord( in , false ).c_str() , 0 ) ; atoi( getWord( in , false ).c_str() ) ; // iReflag // Finish the line and get the first word of next line readToEndOfLine( in , true ); lastStr = getWord( in , false ); // Find the detector ID from row/col Instrument_const_sptr inst = outWS->getInstrument(); if (!inst) throw std::runtime_error("No instrument in PeaksWorkspace!"); LoadIsawPeaks u; int pixelID = u.findPixelID(inst, bankName, static_cast<int>(col), static_cast<int>(row)); //Create the peak object Peak peak(outWS->getInstrument(), pixelID, wl); // HKL's are flipped by -1 because of the internal Q convention peak.setHKL(-h,-k,-l); peak.setIntensity(Inti); peak.setSigmaIntensity(SigI); peak.setBinCount(IPK); // Return the peak return peak; }
/** Reads the header of a .peaks file * @param outWS :: the workspace in which to place the information * @param in :: stream of the input file * @param T0 :: Time offset * @return the first word on the next line */ std::string LoadIsawPeaks::readHeader( PeaksWorkspace_sptr outWS, std::ifstream& in, double &T0 ) { std::string tag; std::string r = getWord( in , false ); if( r.length() < 1 ) throw std::logic_error( std::string( "No first line of Peaks file" ) ); if( r.compare( std::string( "Version:" ) ) != 0 ) throw std::logic_error( std::string( "No Version: on first line of Peaks file" ) ); std::string C_version = getWord( in , false ); if( C_version.length() < 1 ) throw std::logic_error( std::string( "No Version for Peaks file" ) ); getWord( in , false ); //tag // cppcheck-suppress unreadVariable std::string C_Facility = getWord( in , false ); getWord( in , false ); //tag std::string C_Instrument = getWord( in , false ); if( C_Instrument.length() < 1 ) throw std::logic_error( std::string( "No Instrument for Peaks file" ) ); // Date: use the current date/time if not found Kernel::DateAndTime C_experimentDate; std::string date; tag = getWord( in , false ); if(tag.empty()) date = Kernel::DateAndTime::getCurrentTime().toISO8601String(); else if(tag == "Date:") date = getWord( in , false ); readToEndOfLine( in , true ); // Now we load the instrument using the name and date MatrixWorkspace_sptr tempWS = WorkspaceFactory::Instance().create("Workspace2D", 1, 1, 1); tempWS->mutableRun().addProperty<std::string>("run_start", date); IAlgorithm_sptr loadInst= createChildAlgorithm("LoadInstrument"); loadInst->setPropertyValue("InstrumentName", C_Instrument); loadInst->setProperty<MatrixWorkspace_sptr> ("Workspace", tempWS); loadInst->executeAsChildAlg(); // Populate the instrument parameters in this workspace - this works around a bug tempWS->populateInstrumentParameters(); Geometry::Instrument_const_sptr instr_old = tempWS->getInstrument() ; boost::shared_ptr< ParameterMap > map(new ParameterMap()); Geometry::Instrument_const_sptr instr ( new Geometry::Instrument(instr_old->baseInstrument(), map )); //std::string s; std::string s = ApplyCalibInfo(in, "", instr_old, instr, T0); outWS->setInstrument( instr); // Now skip all lines on L1, detector banks, etc. until we get to a block of peaks. They start with 0. // readToEndOfLine( in , true ); // readToEndOfLine( in , true ); // s = getWord(in, false); while (s != "0" && in.good()) { readToEndOfLine( in , true ); s = getWord(in, false); } return s; }
/** Executes the algorithm * * @throw runtime_error Thrown if algorithm cannot execute */ void IndexSXPeaks::exec() { using namespace Mantid::DataObjects; std::vector<int> peakindices = getProperty("PeakIndices"); PeaksWorkspace_sptr ws = boost::dynamic_pointer_cast<PeaksWorkspace>( AnalysisDataService::Instance().retrieve(this->getProperty("PeaksWorkspace")) ); // Need a least two peaks std::size_t npeaks=peakindices.size(); if (npeaks > size_t(ws->getNumberPeaks())) { throw std::runtime_error("Cannot have more peaks indices than actual peaks"); } if (npeaks == 1 || ws->getNumberPeaks() < 2) { throw std::runtime_error("At least 2 peaks are required for this algorithm to work"); } if (npeaks == 0) { //If the user provides no peaks we default to use all the available peaks. npeaks = ws->getNumberPeaks(); peakindices.reserve(npeaks); for(int i = 1; i <= int(npeaks); i++) //create indexes corresponding to all peak indexes { peakindices.push_back(i); } g_log.information("No peak indexes provided. Algorithm will use all peaks in the workspace for the calculation."); } //Get the effective unit cell double a = getProperty("a"); double b = getProperty("b"); double c = getProperty("c"); double alpha = getProperty("alpha"); double beta = getProperty("beta"); double gamma = getProperty("gamma"); std::vector<int> extents = getProperty("SearchExtents"); if(extents.size() != 6) { std::stringstream stream; stream << "Expected 6 elements for the extents. Got: " << extents.size(); throw std::runtime_error(stream.str()); } // Create the Unit-Cell. Mantid::Geometry::UnitCell unitcell(a, b, c, alpha, beta, gamma); std::vector<PeakCandidate> peaks; for (std::size_t i=0;i<npeaks;i++) { int row=peakindices[i]-1; if(row < 0) { throw std::runtime_error("Cannot have a peak index < 0."); } IPeak& peak = ws->getPeak(row); V3D Qs = peak.getQSampleFrame() / (2.0 * M_PI); peaks.push_back(PeakCandidate(Qs[0], Qs[1], Qs[2])); } //Sanity check the generated peaks. validateNotColinear(peaks); //Generate HKL possibilities for each peak. double dtol= getProperty("dTolerance"); Progress prog(this,0.0,1.0,4); for (int h=extents[0]; h<extents[1]; h++) { for (int k=extents[2]; k<extents[3]; k++) { for (int l=extents[4]; l<extents[5]; l++) { double dspacing=unitcell.d(h,k,l); //Create a fictional d spacing for (std::size_t p=0;p<npeaks;p++) { double dSpacingPeaks = peaks[p].getdSpacing(); if (std::abs(dspacing-dSpacingPeaks)<dtol) peaks[p].addHKL(h,k,l); // If the peak position and the fictional d spacing are within tolerance, add it } } } } prog.report(); //1st Progress report. cullHKLs(peaks, unitcell); prog.report(); //2nd progress report. peaks[0].setFirst(); //On the first peak, now only the first candidate hkl is considered, others are erased, //This means the design space of possible peak-hkl alignments has been reduced, will improve future refinements. cullHKLs(peaks, unitcell); prog.report(); //3rd progress report. peaks[1].setFirst(); cullHKLs(peaks, unitcell); prog.report(); //4th progress report. //Now we can index the input/output peaks workspace //If there are peak indexes uses those to find actual peaks in the workspace and overrite HKL for (std::size_t i=0;i<npeaks;i++) { int row = 0; try { row=peakindices[i]-1; IPeak& peak = ws->getPeak(row); const V3D hkl = peaks[i].getHKL(); peak.setHKL(hkl); std::stringstream stream; stream << "Peak Index: " << row << " HKL: " << hkl; g_log.information(stream.str()); } catch(std::logic_error&) { std::stringstream msg; msg << "Peak Index: " << row + 1 << " cannot be assigned a single HKL set."; g_log.warning(msg.str()); continue; } } }
/** Execute the algorithm. */ void SelectCellWithForm::exec() { PeaksWorkspace_sptr ws = this->getProperty("PeaksWorkspace"); if (!ws) { throw std::runtime_error("Could not read the peaks workspace"); } OrientedLattice o_lattice = ws->mutableSample().getOrientedLattice(); Matrix<double> UB = o_lattice.getUB(); bool allowPermutations = this->getProperty("AllowPermutations"); if ( ! IndexingUtils::CheckUB( UB ) ) { throw std::runtime_error( "ERROR: The stored UB is not a valid orientation matrix"); } int form_num = this->getProperty("FormNumber"); bool apply = this->getProperty("Apply"); double tolerance = this->getProperty("Tolerance"); ConventionalCell info = ScalarUtils::GetCellForForm( UB, form_num, allowPermutations ); DblMatrix newUB = info.GetNewUB(); std::string message = info.GetDescription() + " Lat Par:" + IndexingUtils::GetLatticeParameterString( newUB ); g_log.notice( std::string(message) ); Kernel::Matrix<double>T(UB); T.Invert(); T = newUB * T; g_log.notice() << "Transformation Matrix = " << T.str() << std::endl; if ( apply ) { //----------------------------------- Try to optimize(LSQ) to find lattice errors ------------------------ // UB matrix may NOT have been found by unconstrained least squares optimization //---------------------------------------------- o_lattice.setUB( newUB ); std::vector<double> sigabc(6); DetermineErrors(sigabc,newUB,ws, tolerance); o_lattice.setError( sigabc[0],sigabc[1],sigabc[2],sigabc[3],sigabc[4],sigabc[5]); ws->mutableSample().setOrientedLattice( &o_lattice ); std::vector<Peak> &peaks = ws->getPeaks(); size_t n_peaks = ws->getNumberPeaks(); int num_indexed = 0; double average_error = 0.0; std::vector<V3D> miller_indices; std::vector<V3D> q_vectors; for ( size_t i = 0; i < n_peaks; i++ ) { q_vectors.push_back( peaks[i].getQSampleFrame() ); } num_indexed = IndexingUtils::CalculateMillerIndices( newUB, q_vectors, tolerance, miller_indices, average_error ); for ( size_t i = 0; i < n_peaks; i++ ) { peaks[i].setHKL( miller_indices[i] ); } // Tell the user what happened. g_log.notice() << "Re-indexed the peaks with the new UB. " << std::endl; g_log.notice() << "Now, " << num_indexed << " are indexed with average error " << average_error << std::endl; // Save output properties this->setProperty("NumIndexed", num_indexed); this->setProperty("AverageError", average_error); } }
/** * Calculates the h,k, and l offsets from an integer for (some of )the peaks, *given the parameter values. * * @param out For each peak there are 3 consecutive elements in this array. The *first is for the h offset from an * integer, the second is the k offset and the 3rd is the l offset * @param xValues xValues give the index in the PeaksWorkspace for the peak. *For each peak considered there are * three consecutive entries all with the same index * @param nData The size of the xValues and out arrays */ void PeakHKLErrors::function1D(double *out, const double *xValues, const size_t nData) const { PeaksWorkspace_sptr Peaks = AnalysisDataService::Instance().retrieveWS<PeaksWorkspace>( PeakWorkspaceName); boost::shared_ptr<Geometry::Instrument> instNew = getNewInstrument(Peaks); if (!Peaks) throw std::invalid_argument("Peaks not stored under the name " + PeakWorkspaceName); std::map<int, Mantid::Kernel::Matrix<double>> RunNum2GonMatrixMap; getRun2MatMap(Peaks, OptRuns, RunNum2GonMatrixMap); const DblMatrix &UBx = Peaks->sample().getOrientedLattice().getUB(); DblMatrix UBinv(UBx); UBinv.Invert(); UBinv /= (2 * M_PI); double GonRotx = getParameter("GonRotx"); double GonRoty = getParameter("GonRoty"); double GonRotz = getParameter("GonRotz"); Matrix<double> GonRot = RotationMatrixAboutRegAxis(GonRotx, 'x') * RotationMatrixAboutRegAxis(GonRoty, 'y') * RotationMatrixAboutRegAxis(GonRotz, 'z'); double ChiSqTot = 0.0; for (size_t i = 0; i < nData; i += 3) { int peakNum = boost::math::iround(xValues[i]); IPeak &peak_old = Peaks->getPeak(peakNum); int runNum = peak_old.getRunNumber(); std::string runNumStr = std::to_string(runNum); Peak peak = createNewPeak(peak_old, instNew, 0, peak_old.getL1()); size_t N = OptRuns.find("/" + runNumStr + "/"); if (N < OptRuns.size()) { peak.setGoniometerMatrix(GonRot * RunNum2GonMatrixMap[runNum]); } else { peak.setGoniometerMatrix(GonRot * peak.getGoniometerMatrix()); } V3D sampOffsets(getParameter("SampleXOffset"), getParameter("SampleYOffset"), getParameter("SampleZOffset")); peak.setSamplePos(peak.getSamplePos() + sampOffsets); V3D hkl = UBinv * peak.getQSampleFrame(); for (int k = 0; k < 3; k++) { double d1 = hkl[k] - floor(hkl[k]); if (d1 > .5) d1 = d1 - 1; if (d1 < -.5) d1 = d1 + 1; out[i + k] = d1; ChiSqTot += d1 * d1; } } g_log.debug() << "------------------------Function---------------------------" "--------------------\n"; for (size_t p = 0; p < nParams(); p++) { g_log.debug() << parameterName(p) << "(" << getParameter(p) << "),"; if ((p + 1) % 6 == 0) g_log.debug() << '\n'; } g_log.debug() << '\n'; g_log.debug() << "Off constraints="; for (size_t p = 0; p < nParams(); p++) { IConstraint *constr = getConstraint(p); if (constr) if ((constr->check() > 0)) g_log.debug() << "(" << parameterName(p) << "=" << constr->check() << ");"; } g_log.debug() << '\n'; g_log.debug() << " Chi**2 = " << ChiSqTot << " nData = " << nData << '\n'; }
/** Read one peak in a line of an ISAW peaks file. * * @param outWS :: workspace to add peaks to * @param lastStr [in,out] :: last word (the one at the start of the line) * @param in :: input stream * @param seqNum [out] :: the sequence number of the peak * @param bankName :: the bank number from the ISAW file. * @return the Peak the Peak object created */ Mantid::DataObjects::Peak readPeak( PeaksWorkspace_sptr outWS, std::string & lastStr, std::ifstream& in, int & seqNum, std::string bankName) { double h ; double k ; double l ; double col ; double row ; double wl ; double IPK ; double Inti ; double SigI ; seqNum = -1; std::string s = lastStr; if( s.length() < 1 && in.good() )//blank line { readToEndOfLine( in , true ); s = getWord( in , false );; } if( s.length() < 1 ) throw std::runtime_error("Empty peak line encountered."); if( s.compare( "2" ) == 0 ) { readToEndOfLine( in , true ); for( s = getWord( in , false ) ; s.length() < 1 && in.good() ; s = getWord( in , true ) ) { s = getWord( in , false ); } } if( s.length() < 1 ) throw std::runtime_error("Empty peak line encountered."); if( s.compare( "3" ) != 0 ) throw std::runtime_error("Empty peak line encountered."); seqNum = atoi( getWord( in , false ).c_str() ); h = strtod( getWord( in , false ).c_str() , 0 ) ; k = strtod( getWord( in , false ).c_str() , 0 ) ; l = strtod( getWord( in , false ).c_str() , 0 ) ; col = strtod( getWord( in , false ).c_str() , 0 ) ; row = strtod( getWord( in , false ).c_str() , 0 ) ; strtod( getWord( in , false ).c_str() , 0 ) ; //chan strtod( getWord( in , false ).c_str() , 0 ) ; //L2 strtod( getWord( in , false ).c_str() , 0 ) ; //ScatAng strtod( getWord( in , false ).c_str() , 0 ) ; //Az wl = strtod( getWord( in , false ).c_str() , 0 ) ; strtod( getWord( in , false ).c_str() , 0 ) ; //D IPK = strtod( getWord( in , false ).c_str() , 0 ) ; Inti = strtod( getWord( in , false ).c_str() , 0 ) ; SigI = strtod( getWord( in , false ).c_str() , 0 ) ; atoi( getWord( in , false ).c_str() ) ; // iReflag // Finish the line and get the first word of next line readToEndOfLine( in , true ); lastStr = getWord( in , false ); // Find the detector ID from row/col Instrument_const_sptr inst = outWS->getInstrument(); if (!inst) throw std::runtime_error("No instrument in PeaksWorkspace!"); IComponent_const_sptr bank = inst->getComponentByName(bankName); if (!bank) throw std::runtime_error("Bank named " + bankName + " not found!"); RectangularDetector_const_sptr rect = boost::dynamic_pointer_cast<const RectangularDetector>(bank); if (!rect) throw std::runtime_error("Bank named " + bankName + " is not a RectangularDetector!"); IDetector_sptr det = rect->getAtXY(int(col), int(row)); if (!det) throw std::runtime_error("Detector not found on " + bankName + "!"); //Create the peak object Peak peak(outWS->getInstrument(), det->getID(), wl); // HKL's are flipped by -1 because of the internal Q convention peak.setHKL(-h,-k,-l); peak.setIntensity(Inti); peak.setSigmaIntensity(SigI); peak.setBinCount(IPK); // Return the peak return peak; }
/** 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(); // } }
/** 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) ); } }