/** Initialize unit conversion helper * This method is interface to internal initialize method, which actually takes all parameters UnitConversion helper needs from * targetWSDescr class * @param targetWSDescr -- the class which contains all information about target workspace including energy transfer mode, number of dimensions, input workspace etc. * @param unitsTo -- the ID of the units conversion helper would help to convert to * @param forceViaTOF -- force to perform unit conversion via TOF even if quick conversion exist (by default, false) * */ void UnitsConversionHelper::initialize(const MDWSDescription &targetWSDescr, const std::string &unitsTo, bool forceViaTOF) { // obtain input workspace units API::MatrixWorkspace_const_sptr inWS2D = targetWSDescr.getInWS(); if (!inWS2D) throw(std::runtime_error("UnitsConversionHelper::initialize Should not be " "able to call this function when workpsace is " "undefined")); API::NumericAxis *pAxis = dynamic_cast<API::NumericAxis *>(inWS2D->getAxis(0)); if (!pAxis) throw(std::invalid_argument( "Cannot retrieve numeric X axis from the input workspace: " + inWS2D->name())); std::string unitsFrom = inWS2D->getAxis(0)->unit()->unitID(); // get detectors positions and other data needed for units conversion: if (!(targetWSDescr.m_PreprDetTable)) throw std::runtime_error("MDWSDescription does not have a detector table"); int Emode = (int)targetWSDescr.getEMode(); this->initialize(unitsFrom, unitsTo, targetWSDescr.m_PreprDetTable, Emode, forceViaTOF); }
/** Method analyzes the state of UB matrix and goniometer attached to the *workspace and decides, which target * coordinate system these variables identify. *Crystal Frame decided in case if there is UB matrix is present and is not *unit matrix *Lab frame -- if goniometer is Unit and UB is unit matrix or not present *Sample frame -- otherwise */ CnvrtToMD::TargetFrame MDWSTransform::findTargetFrame(MDWSDescription &TargWSDescription) const { bool hasGoniometer = TargWSDescription.hasGoniometer(); bool hasLattice = TargWSDescription.hasLattice(); if (!hasGoniometer) { return LabFrame; } else { if (hasLattice) return HKLFrame; else return SampleFrame; } }
void MDTransfNoQ::initialize(const MDWSDescription &ConvParams) { // get pointer to the positions of the detectors std::vector<Kernel::V3D> const &DetDir = ConvParams.m_PreprDetTable->getColVector<Kernel::V3D>("DetDirections"); m_Det = &DetDir[0]; // // get min and max values defined by the algorithm. ConvParams.getMinMax(m_DimMin, m_DimMax); m_NMatrixDim = getNMatrixDimensions(Kernel::DeltaEMode::Undefined, ConvParams.getInWS()); m_AddDimCoordinates = ConvParams.getAddCoord(); API::NumericAxis *pXAx; this->getAxes(ConvParams.getInWS(), pXAx, m_YAxis); }
/** function creates empty MD event workspace with given parameters (workspace *factory) and stores internal pointer to this workspace for further usage. * IT ASLO SETS UP W-TRANSFORMATON. TODO: reconcile w-transformation with MD *geometry. * *@param WSD the class which describes an MD workspace * *@returns shared pointer to the created workspace */ API::IMDEventWorkspace_sptr MDEventWSWrapper::createEmptyMDWS(const MDWSDescription &WSD) { if (WSD.nDimensions() < 1 || WSD.nDimensions() > MAX_N_DIM) { std::string ERR = " Number of requested MD dimensions: " + boost::lexical_cast<std::string>(WSD.nDimensions()) + " exceeds maximal number of MD dimensions: " + boost::lexical_cast<std::string>((int)MAX_N_DIM) + " instantiated during compilation\n"; throw(std::invalid_argument(ERR)); } m_NDimensions = (int)WSD.nDimensions(); // call the particular function, which creates the workspace with n_dimensions (this->*(wsCreator[m_NDimensions]))(WSD); // set up the matrix, which convert momentums from Q in orthogonal crystal // coordinate system and units of Angstrom^-1 to hkl or orthogonal hkl or // whatever m_Workspace->setWTransf(WSD.m_Wtransf); return m_Workspace; }
/** Method verifies if the information available on the source workspace is *sufficient to build appropriate frame *@param TargWSDescription -- the class which contains the information about the *target workspace *@param CoordFrameID -- the ID of the target frame requested * * method throws invalid argument if the information on the workspace is *insufficient to define the frame requested */ void MDWSTransform::checkTargetFrame( const MDWSDescription &TargWSDescription, const CnvrtToMD::TargetFrame CoordFrameID) const { switch (CoordFrameID) { case (LabFrame): // nothing needed for lab frame return; case (SampleFrame): if (!TargWSDescription.hasGoniometer()) throw std::invalid_argument( " Sample frame needs goniometer to be defined on the workspace "); return; case (HKLFrame): // ubMatrix has to be present if (!TargWSDescription.hasLattice()) throw std::invalid_argument( " HKL frame needs UB matrix defined on the workspace "); if (!TargWSDescription.hasGoniometer()) g_Log.warning() << " HKL frame does not have goniometer defined on the " "workspace. Assuming unit goniometer matrix\n"; return; default: throw std::runtime_error( " Unexpected argument in MDWSTransform::checkTargetFrame"); } }
/** method to build the Q-coordinates transformation. * * @param TargWSDescription -- the class which describes target MD workspace. In Q3D case this description is modified by the method with default Q-axis labels and Q-axis units * @param FrameRequested -- the string which describes the target transformation frame in Q3D case. If the string value is '''Auto''' * the frame is selected depending on the presence of UB matrix and goniometer settings, namely it can be: * a) the laboratory -- (no UB matrix, goniometer angles set to 0) b) Q (sample frame)''': the goniometer rotation of the sample is taken out, to give Q in the frame of the sample. See [[SetGoniometer]] to specify the goniometer used in the experiment. c) Crystal or crystal Cartesian (C)- Busing, Levi 1967 coordinate system -- depending on Q-scale requested * one of the target frames above can be requested explicitly. In this case the method throws invalid argument if necessary parameters (UB matrix) is not attached to the workspace * @param QScaleRequested -- Q-transformation needed * * @return the linear representation for the transformation matrix, which translate momentums from laboratory to the requested * coordinate system. */ std::vector<double> MDWSTransform::getTransfMatrix(MDWSDescription &TargWSDescription, const std::string &FrameRequested, const std::string &QScaleRequested) const { CoordScaling ScaleID = getQScaling(QScaleRequested); TargetFrame FrameID = getTargetFrame(FrameRequested); std::vector<double> transf = getTransfMatrix(TargWSDescription, FrameID, ScaleID); if (TargWSDescription.isQ3DMode()) { this->setQ3DDimensionsNames(TargWSDescription, FrameID, ScaleID); } return transf; }
/** method sets up all internal variables necessary to convert from Event Workspace to MDEvent workspace @param WSD -- the class describing the target MD workspace, sorurce Event workspace and the transformations, necessary to perform on these workspaces @param inWSWrapper -- the class wrapping the target MD workspace @param ignoreZeros -- if zero value signals should be rejected */ size_t ConvToMDEventsWS::initialize(const MDWSDescription &WSD, boost::shared_ptr<MDEventWSWrapper> inWSWrapper, bool ignoreZeros) { size_t numSpec = ConvToMDBase::initialize(WSD, inWSWrapper, ignoreZeros); m_EventWS = boost::dynamic_pointer_cast<const DataObjects::EventWorkspace>(m_InWS2D); if (!m_EventWS) throw(std::logic_error( " ConvertToMDEventWS should work with defined event workspace")); // Record any special coordinate system known to the description. m_coordinateSystem = WSD.getCoordinateSystem(); return numSpec; }
/** * Create new MD workspace and set up its box controller using algorithm's box * controllers properties * @param targWSDescr :: Description of workspace to create * @param filebackend :: true if the workspace will have a file back end * @param filename :: file to use for file back end of workspace * @return :: Shared pointer for the created workspace */ API::IMDEventWorkspace_sptr ConvertToMD::createNewMDWorkspace(const MDWSDescription &targWSDescr, const bool filebackend, const std::string &filename) { // create new md workspace and set internal shared pointer of m_OutWSWrapper // to this workspace API::IMDEventWorkspace_sptr spws = m_OutWSWrapper->createEmptyMDWS(targWSDescr); if (!spws) { g_log.error() << "can not create target event workspace with :" << targWSDescr.nDimensions() << " dimensions\n"; throw(std::invalid_argument("can not create target workspace")); } // Build up the box controller Mantid::API::BoxController_sptr bc = m_OutWSWrapper->pWorkspace()->getBoxController(); // Build up the box controller, using the properties in // BoxControllerSettingsAlgorithm this->setBoxController(bc, m_InWS2D->getInstrument()); if (filebackend) { setupFileBackend(filename, m_OutWSWrapper->pWorkspace()); } // Check if the user want sto force a top level split or not bool topLevelSplittingChecked = this->getProperty("TopLevelSplitting"); if (topLevelSplittingChecked) { // Perform initial split with the forced settings setupTopLevelSplitting(bc); } // split boxes; spws->splitBox(); // Do we split more due to MinRecursionDepth? int minDepth = this->getProperty("MinRecursionDepth"); int maxDepth = this->getProperty("MaxRecursionDepth"); if (minDepth > maxDepth) throw std::invalid_argument( "MinRecursionDepth must be >= MaxRecursionDepth "); spws->setMinRecursionDepth(size_t(minDepth)); return spws; }
void UnitsConversionHelper::initialize(const MDWSDescription &TWSD, const std::string &units_to) { // obtain input workspace units API::MatrixWorkspace_const_sptr inWS2D = TWSD.getInWS(); if(!inWS2D.get()){ throw(std::logic_error("UnitsConversionHelper::initialize Should not be able to call this function when workpsace is undefined")); } API::NumericAxis *pAxis = dynamic_cast<API::NumericAxis *>(inWS2D->getAxis(0)); if(!pAxis){ std::string ERR = "can not retrieve numeric X axis from the input workspace: "+inWS2D->name(); throw(std::invalid_argument(ERR)); } pSourceWSUnit = inWS2D->getAxis(0)->unit(); if(!pSourceWSUnit){ throw(std::logic_error(" can not retrieve source workspace units from the source workspace's numeric axis")); } // Check how input workspace units relate to the units requested UnitCnvrsn = analyzeUnitsConversion(pSourceWSUnit->unitID(),units_to); // get units class, requested by ChildAlgorithm pTargetUnit = Kernel::UnitFactory::Instance().create(units_to); if(!pTargetUnit){ throw(std::logic_error(" can not retrieve target unit from the units factory")); } // get detectors positions and other data needed for units conversion: pTwoTheta = &(TWSD.getDetectors()->getTwoTheta()); pL2 = &(TWSD.getDetectors()->getL2()); L1 = TWSD.getDetectors()->getL1(); // get efix efix = TWSD.getEi(); emode = (int)TWSD.getEMode(); }
void MDEventWSWrapper::createEmptyEventWS(const MDWSDescription &description) { boost::shared_ptr<DataObjects::MDEventWorkspace<DataObjects::MDEvent<nd>, nd>> ws = boost::shared_ptr< DataObjects::MDEventWorkspace<DataObjects::MDEvent<nd>, nd>>( new DataObjects::MDEventWorkspace<DataObjects::MDEvent<nd>, nd>()); auto numBins = description.getNBins(); size_t nBins(10); // HACK. this means we have 10 bins artificially. This can't // be right. // Give all the dimensions for (size_t d = 0; d < nd; d++) { if (!numBins.empty()) nBins = numBins[d]; Geometry::MDHistoDimension *dim = NULL; if (d < 3 && description.isQ3DMode()) { // We should have frame and scale information that we can use correctly // for our Q dimensions. auto mdFrame = description.getFrame(d); dim = new Geometry::MDHistoDimension( description.getDimNames()[d], description.getDimIDs()[d], *mdFrame, Mantid::coord_t(description.getDimMin()[d]), Mantid::coord_t(description.getDimMax()[d]), nBins); } else { Mantid::Geometry::GeneralFrame frame(description.getDimNames()[d], description.getDimUnits()[d]); dim = new Geometry::MDHistoDimension( description.getDimNames()[d], description.getDimIDs()[d], frame, Mantid::coord_t(description.getDimMin()[d]), Mantid::coord_t(description.getDimMax()[d]), nBins); } ws->addDimension(Geometry::MDHistoDimension_sptr(dim)); } ws->initialize(); m_Workspace = ws; }
/** 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; }
/** The matrix to convert neutron momentums into the target coordinate system */ std::vector<double> MDWSTransform::getTransfMatrix(MDWSDescription &TargWSDescription, CnvrtToMD::TargetFrame FrameID, CoordScaling &ScaleID) const { Kernel::Matrix<double> mat(3, 3, true); bool powderMode = TargWSDescription.isPowder(); bool has_lattice(true); if (!TargWSDescription.hasLattice()) has_lattice = false; if (!(powderMode || has_lattice)) { std::string inWsName = TargWSDescription.getWSName(); // notice about 3D case without lattice g_Log.notice() << "Can not obtain transformation matrix from the input workspace: " << inWsName << " as no oriented lattice has been defined. \n" "Will use unit transformation matrix.\n"; } // set the frame ID to the values, requested by properties CnvrtToMD::TargetFrame CoordFrameID(FrameID); if (FrameID == AutoSelect || powderMode) // if this value is auto-select, find // appropriate frame from workspace // properties CoordFrameID = findTargetFrame(TargWSDescription); else // if not, and specific target frame requested, verify if everything is // available on the workspace for this frame checkTargetFrame( TargWSDescription, CoordFrameID); // throw, if the information is not available switch (CoordFrameID) { case (CnvrtToMD::LabFrame): { ScaleID = NoScaling; TargWSDescription.m_Wtransf = buildQTrahsf(TargWSDescription, ScaleID, true); // ignore goniometer mat = TargWSDescription.m_Wtransf; break; } case (CnvrtToMD::SampleFrame): { ScaleID = NoScaling; TargWSDescription.m_Wtransf = buildQTrahsf(TargWSDescription, ScaleID, true); // Obtain the transformation matrix to Cartesian related to Crystal mat = TargWSDescription.getGoniometerMatr() * TargWSDescription.m_Wtransf; break; } case (CnvrtToMD::HKLFrame): { TargWSDescription.m_Wtransf = buildQTrahsf(TargWSDescription, ScaleID, false); // Obtain the transformation matrix to Cartesian related to Crystal if (TargWSDescription.hasGoniometer()) mat = TargWSDescription.getGoniometerMatr() * TargWSDescription.m_Wtransf; else mat = TargWSDescription.m_Wtransf; break; } default: throw(std::invalid_argument(" Unknown or undefined Target Frame ID")); } // // and this is the transformation matrix to notional mat.Invert(); std::vector<double> rotMat = mat.getVector(); g_Log.debug() << " *********** Q-transformation matrix ***********************\n"; g_Log.debug() << "*** *qx ! *qy ! *qz !\n"; g_Log.debug() << "q1= " << rotMat[0] << " ! " << rotMat[1] << " ! " << rotMat[2] << " !\n"; g_Log.debug() << "q2= " << rotMat[3] << " ! " << rotMat[4] << " ! " << rotMat[5] << " !\n"; g_Log.debug() << "q3= " << rotMat[6] << " ! " << rotMat[7] << " ! " << rotMat[8] << " !\n"; g_Log.debug() << " *********** *********************** ***********************\n"; return rotMat; }
/** function initalizes all variables necessary for converting workspace * variables into MD variables in ModQ (elastic/inelastic) cases */ void MDTransfQ3D::initialize(const MDWSDescription &ConvParams) { m_pEfixedArray = NULL; m_pDetMasks = NULL; //********** Generic part of initialization, common for elastic and inelastic // modes: // get transformation matrix (needed for CrystalAsPoder mode) m_RotMat = ConvParams.getTransfMatrix(); if (!ConvParams.m_PreprDetTable) throw(std::runtime_error("The detectors have not been preprocessed but " "they have to before running initialize")); // get pointer to the positions of the preprocessed detectors std::vector<Kernel::V3D> const &DetDir = ConvParams.m_PreprDetTable->getColVector<Kernel::V3D>("DetDirections"); m_DetDirecton = &DetDir[0]; // // get min and max values defined by the algorithm. ConvParams.getMinMax(m_DimMin, m_DimMax); // get additional coordinates which are m_AddDimCoordinates = ConvParams.getAddCoord(); //************ specific part of the initialization, dependent on emode: m_Emode = ConvParams.getEMode(); m_NMatrixDim = getNMatrixDimensions(m_Emode); if (m_Emode == Kernel::DeltaEMode::Direct || m_Emode == Kernel::DeltaEMode::Indirect) { // energy needed in inelastic case m_Ei = ConvParams.m_PreprDetTable->getLogs()->getPropertyValueAsType<double>( "Ei"); // the wave vector of incident neutrons; m_Ki = sqrt(m_Ei / PhysicalConstants::E_mev_toNeutronWavenumberSq); m_pEfixedArray = NULL; if (m_Emode == (int)Kernel::DeltaEMode::Indirect) m_pEfixedArray = ConvParams.m_PreprDetTable->getColDataArray<float>("eFixed"); } else { if (m_Emode != Kernel::DeltaEMode::Elastic) throw(std::runtime_error("MDTransfQ3D::initialize::Unknown or " "unsupported energy conversion mode")); // check if we need to calculate Lorentz corrections and if we do, prepare // values for their precalculation: m_isLorentzCorrected = ConvParams.isLorentsCorrections(); if (m_isLorentzCorrected) { auto &TwoTheta = ConvParams.m_PreprDetTable->getColVector<double>("TwoTheta"); SinThetaSq.resize(TwoTheta.size()); for (size_t i = 0; i < TwoTheta.size(); i++) { double sth = sin(0.5 * TwoTheta[i]); SinThetaSq[i] = sth * sth; } m_SinThetaSqArray = &SinThetaSq[0]; if (!m_SinThetaSqArray) throw(std::runtime_error("MDTransfQ3D::initialize::Uninitilized " "Sin(Theta)^2 array for calculating Lorentz " "corrections")); } } // use detectors masks untill signals are masked by 0 instead of NaN m_pDetMasks = ConvParams.m_PreprDetTable->getColDataArray<int>("detMask"); }
/** function initializes all variables necessary for converting workspace * variables into MD variables in ModQ (elastic/inelastic) cases */ void MDTransfModQ::initialize(const MDWSDescription &ConvParams) { //********** Generic part of initialization, common for elastic and inelastic // modes: // pHost = &Conv; // get transformation matrix (needed for CrystalAsPoder mode) m_RotMat = ConvParams.getTransfMatrix(); m_pEfixedArray = nullptr; if (!ConvParams.m_PreprDetTable) throw(std::runtime_error("The detectors have not been preprocessed but " "they have to before running initialize")); // get pointer to the positions of the detectors std::vector<Kernel::V3D> const &DetDir = ConvParams.m_PreprDetTable->getColVector<Kernel::V3D>("DetDirections"); m_DetDirecton = &DetDir[0]; // // get min and max values defined by the algorithm. ConvParams.getMinMax(m_DimMin, m_DimMax); // m_DimMin/max here are momentums and they are verified on momentum squared // base if (m_DimMin[0] < 0) m_DimMin[0] = 0; if (m_DimMax[0] < 0) m_DimMax[0] = 0; // m_DimMin here is a momentum and it is verified on momentum squared base m_DimMin[0] *= m_DimMin[0]; m_DimMax[0] *= m_DimMax[0]; if (std::fabs(m_DimMin[0] - m_DimMax[0]) < FLT_EPSILON || m_DimMax[0] < m_DimMin[0]) { std::string ERR = "ModQ coordinate transformation: Min Q^2 value: " + boost::lexical_cast<std::string>(m_DimMin[0]) + " is more or equal then Max Q^2 value: " + boost::lexical_cast<std::string>(m_DimMax[0]); throw(std::invalid_argument(ERR)); } m_AddDimCoordinates = ConvParams.getAddCoord(); //************ specific part of the initialization, dependent on emode: m_Emode = ConvParams.getEMode(); m_NMatrixDim = getNMatrixDimensions(m_Emode); if (m_Emode == Kernel::DeltaEMode::Direct || m_Emode == Kernel::DeltaEMode::Indirect) { // energy needed in inelastic case volatile double Ei = ConvParams.m_PreprDetTable->getLogs()->getPropertyValueAsType<double>( "Ei"); m_Ei = Ei; if (Ei != m_Ei) // Ei is NaN, try Efixed, but the value should be overridden later { try { m_Ei = ConvParams.m_PreprDetTable->getLogs() ->getPropertyValueAsType<double>("eFixed"); } catch (...) { } } // the wave vector of incident neutrons; m_Ki = sqrt(m_Ei / PhysicalConstants::E_mev_toNeutronWavenumberSq); m_pEfixedArray = nullptr; if (m_Emode == static_cast<int>(Kernel::DeltaEMode::Indirect)) m_pEfixedArray = ConvParams.m_PreprDetTable->getColDataArray<float>("eFixed"); } else if (m_Emode != Kernel::DeltaEMode::Elastic) throw(std::invalid_argument( "MDTransfModQ::initialize::Unknown energy conversion mode")); m_pDetMasks = ConvParams.m_PreprDetTable->getColDataArray<int>("detMask"); }