/** Build meaningful dimension names for different conversion modes * @param TargWSDescription the class-container to keep the dimension names and dimension unints * @param FrameID -- the ID describing the target transformation frame (lab, sample, hkl) * @param ScaleID -- the scale ID which define how the dimensions are scaled */ void MDWSTransform::setQ3DDimensionsNames( MDWSDescription &TargWSDescription, CnvrtToMD::TargetFrame FrameID, CnvrtToMD::CoordScaling ScaleID) const { std::vector<Kernel::V3D> dimDirections; // set default dimension names: std::vector<std::string> dimNames = TargWSDescription.getDimNames(); // define B-matrix and Lattice parameters to one in case if no OrientedLattice // is there Kernel::DblMatrix Bm(3, 3, true); std::vector<double> LatPar(3, 1); if (TargWSDescription.hasLattice()) { // redefine B-matrix and Lattice // parameters from real oriented lattice // if there is one auto spLatt = TargWSDescription.getLattice(); Bm = spLatt->getB(); for (int i = 0; i < 3; i++) LatPar[i] = spLatt->a(i); } if (FrameID == CnvrtToMD::AutoSelect) FrameID = findTargetFrame(TargWSDescription); switch (FrameID) { case (CnvrtToMD::LabFrame): { dimNames[0] = "Q_lab_x"; dimNames[1] = "Q_lab_y"; dimNames[2] = "Q_lab_z"; TargWSDescription.setCoordinateSystem(Mantid::Kernel::QLab); TargWSDescription.setFrame(Geometry::QLab::QLabName); break; } case (CnvrtToMD::SampleFrame): { dimNames[0] = "Q_sample_x"; dimNames[1] = "Q_sample_y"; dimNames[2] = "Q_sample_z"; TargWSDescription.setCoordinateSystem(Mantid::Kernel::QSample); TargWSDescription.setFrame(Geometry::QSample::QSampleName); break; } case (CnvrtToMD::HKLFrame): { dimNames[0] = "H"; dimNames[1] = "K"; dimNames[2] = "L"; Kernel::MDUnit_uptr mdUnit(new Kernel::InverseAngstromsUnit); TargWSDescription.setCoordinateSystem(Mantid::Kernel::HKL); TargWSDescription.setFrame(Geometry::HKL::HKLName); break; } default: throw(std::invalid_argument(" Unknown or undefined Target Frame ID")); } dimDirections.resize(3); dimDirections[0] = m_UProj; dimDirections[1] = m_VProj; dimDirections[2] = m_WProj; if (ScaleID == OrthogonalHKLScale) { std::vector<Kernel::V3D> uv(2); uv[0] = m_UProj; uv[1] = m_VProj; dimDirections = Kernel::V3D::makeVectorsOrthogonal(uv); } // axis names: if ((FrameID == CnvrtToMD::LabFrame) || (FrameID == CnvrtToMD::SampleFrame)) for (int i = 0; i < 3; i++) TargWSDescription.setDimName(i, dimNames[i]); else for (int i = 0; i < 3; i++) TargWSDescription.setDimName( i, MDAlgorithms::makeAxisName(dimDirections[i], dimNames)); if (ScaleID == NoScaling) { for (int i = 0; i < 3; i++) TargWSDescription.setDimUnit(i, "A^-1"); } if (ScaleID == SingleScale) { double dMax(-1.e+32); for (int i = 0; i < 3; i++) dMax = (dMax > LatPar[i]) ? (dMax) : (LatPar[i]); for (int i = 0; i < 3; i++) TargWSDescription.setDimUnit( i, "in " + MDAlgorithms::sprintfd(2 * M_PI / dMax, 1.e-3) + " A^-1"); } if ((ScaleID == OrthogonalHKLScale) || (ScaleID == HKLScale)) { // get the length along each of the axes std::vector<double> len; Kernel::V3D x; x = Bm * dimDirections[0]; len.push_back(2 * M_PI * x.norm()); x = Bm * dimDirections[1]; len.push_back(2 * M_PI * x.norm()); x = Bm * dimDirections[2]; len.push_back(2 * M_PI * x.norm()); for (int i = 0; i < 3; i++) TargWSDescription.setDimUnit( i, "in " + MDAlgorithms::sprintfd(len[i], 1.e-3) + " A^-1"); } }
/** Method builds transformation Q=R*U*B*W*h where W-transf is W or WB or W*Unit*Lattice_param depending on inputs */ Kernel::DblMatrix MDWSTransform::buildQTrahsf(MDWSDescription &TargWSDescription, CnvrtToMD::CoordScaling ScaleID, bool UnitUB) const { // implements strategy if (!(TargWSDescription.hasLattice() || UnitUB)) { throw(std::invalid_argument("this function should be called only on " "workspace with defined oriented lattice")); } // if u,v us default, Wmat is unit transformation Kernel::DblMatrix Wmat(3, 3, true); // derive rotation from u0,v0 u0||ki to u,v if (!m_isUVdefault) { Wmat[0][0] = m_UProj[0]; Wmat[1][0] = m_UProj[1]; Wmat[2][0] = m_UProj[2]; Wmat[0][1] = m_VProj[0]; Wmat[1][1] = m_VProj[1]; Wmat[2][1] = m_VProj[2]; Wmat[0][2] = m_WProj[0]; Wmat[1][2] = m_WProj[1]; Wmat[2][2] = m_WProj[2]; } if (ScaleID == OrthogonalHKLScale) { std::vector<Kernel::V3D> dim_directions; std::vector<Kernel::V3D> uv(2); uv[0] = m_UProj; uv[1] = m_VProj; dim_directions = Kernel::V3D::makeVectorsOrthogonal(uv); for (size_t i = 0; i < 3; ++i) for (size_t j = 0; j < 3; ++j) Wmat[i][j] = dim_directions[j][i]; } // Now define lab frame to target frame transformation Kernel::DblMatrix Scale(3, 3, true); Kernel::DblMatrix Transf(3, 3, true); boost::shared_ptr<Geometry::OrientedLattice> spLatt; if (UnitUB) spLatt = boost::shared_ptr<Geometry::OrientedLattice>( new Geometry::OrientedLattice(1, 1, 1)); else spLatt = TargWSDescription.getLattice(); switch (ScaleID) { case NoScaling: //< momentums in A^-1 { Transf = spLatt->getU(); break; } case SingleScale: //< momentums divided by 2*Pi/Lattice -- equivalent to // d-spacing in some sense { double dMax(-1.e+32); for (int i = 0; i < 3; i++) dMax = (dMax > spLatt->a(i)) ? (dMax) : (spLatt->a(i)); for (int i = 0; i < 3; i++) Scale[i][i] = (2 * M_PI) / dMax; Transf = spLatt->getU(); break; } case OrthogonalHKLScale: //< each momentum component divided by appropriate // lattice parameter; equivalent to hkl for orthogonal // axis { if (spLatt) { for (int i = 0; i < 3; i++) { Scale[i][i] = (2 * M_PI) / spLatt->a(i); } Transf = spLatt->getU(); } break; } case HKLScale: //< non-orthogonal system for non-orthogonal lattice { if (spLatt) Scale = spLatt->getUB() * (2 * M_PI); break; } default: throw(std::invalid_argument("unrecognized conversion mode")); } TargWSDescription.addProperty("W_MATRIX", Wmat.getVector(), true); return Transf * Scale * Wmat; }