/// Constructor /// @param M :: A matrix to copy. GSLMatrix::GSLMatrix(const Kernel::Matrix<double> &M) { m_matrix = gsl_matrix_alloc(M.numRows(), M.numCols()); for (size_t i = 0; i < size1(); ++i) for (size_t j = 0; j < size2(); ++j) { set(i, j, M[i][j]); } }
std::vector<Kernel::V3D> PeakShapeEllipsoid::getDirectionInSpecificFrame( Kernel::Matrix<double> &invertedGoniometerMatrix) const { std::vector<Kernel::V3D> directionsInFrame; if ((invertedGoniometerMatrix.numCols() != m_directions.size()) || (invertedGoniometerMatrix.numRows() != m_directions.size())) { throw std::invalid_argument("The inverted goniometer matrix is not " "compatible with the direction vector"); } for (const auto &direction : m_directions) { directionsInFrame.push_back(invertedGoniometerMatrix * direction); } return directionsInFrame; }
/** * Checks the normalization workspace against the indices of the original * dimensions. * If not found, the corresponding dimension is integrated * @param otherDimValues Values from non-HKL dimensions * @param skipNormalization [InOut] Sets the flag true if normalization values * are outside of original inputs * @return Affine trasform matrix */ Kernel::Matrix<coord_t> MDNormDirectSC::findIntergratedDimensions( const std::vector<coord_t> &otherDimValues, bool &skipNormalization) { // Get indices of the original dimensions in the output workspace, // and if not found, the corresponding dimension is integrated Kernel::Matrix<coord_t> affineMat = m_normWS->getTransformFromOriginal(0)->makeAffineMatrix(); const size_t nrm1 = affineMat.numRows() - 1; const size_t ncm1 = affineMat.numCols() - 1; for (size_t row = 0; row < nrm1; row++) // affine matrix, ignore last row { const auto dimen = m_normWS->getDimension(row); const auto dimMin(dimen->getMinimum()), dimMax(dimen->getMaximum()); if (affineMat[row][0] == 1.) { m_hIntegrated = false; m_hIdx = row; m_hmin = std::max(m_hmin, dimMin); m_hmax = std::min(m_hmax, dimMax); if (m_hmin > dimMax || m_hmax < dimMin) { skipNormalization = true; } } if (affineMat[row][1] == 1.) { m_kIntegrated = false; m_kIdx = row; m_kmin = std::max(m_kmin, dimMin); m_kmax = std::min(m_kmax, dimMax); if (m_kmin > dimMax || m_kmax < dimMin) { skipNormalization = true; } } if (affineMat[row][2] == 1.) { m_lIntegrated = false; m_lIdx = row; m_lmin = std::max(m_lmin, dimMin); m_lmax = std::min(m_lmax, dimMax); if (m_lmin > dimMax || m_lmax < dimMin) { skipNormalization = true; } } if (affineMat[row][3] == 1.) { m_dEIntegrated = false; m_eIdx = row; m_dEmin = std::max(m_dEmin, dimMin); m_dEmax = std::min(m_dEmax, dimMax); if (m_dEmin > dimMax || m_dEmax < dimMin) { skipNormalization = true; } } for (size_t col = 4; col < ncm1; col++) // affine matrix, ignore last column { if (affineMat[row][col] == 1.) { double val = otherDimValues.at(col - 3); if (val > dimMax || val < dimMin) { skipNormalization = true; } } } } return affineMat; }
/// Constructor /// @param M :: A matrix to copy. GSLMatrix::GSLMatrix(const Kernel::Matrix<double> &M) : m_data(M.getVector()), m_view(gsl_matrix_view_array(m_data.data(), M.numRows(), M.numCols())) {}
/** * This function will create the skew matrix and basis for a non-orthogonal * representation. * * @param ol : The oriented lattice containing B matrix and crystal basis *vectors * @param w : The tranform requested when MDworkspace was created * @param aff : The affine matrix taking care of coordinate transformations */ void vtkDataSetToNonOrthogonalDataSet::createSkewInformation( Geometry::OrientedLattice &ol, Kernel::DblMatrix &w, Kernel::Matrix<coord_t> &aff) { // Get the B matrix Kernel::DblMatrix bMat = ol.getB(); // Apply the W tranform matrix bMat *= w; // Create G* Kernel::DblMatrix gStar = bMat.Tprime() * bMat; Geometry::UnitCell uc(ol); uc.recalculateFromGstar(gStar); m_skewMat = uc.getB(); // Calculate the column normalisation std::vector<double> bNorm; for (std::size_t i = 0; i < m_skewMat.numCols(); i++) { double sum = 0.0; for (std::size_t j = 0; j < m_skewMat.numRows(); j++) { sum += m_skewMat[j][i] * m_skewMat[j][i]; } bNorm.push_back(std::sqrt(sum)); } // Apply column normalisation to skew matrix Kernel::DblMatrix scaleMat(3, 3, true); scaleMat[0][0] /= bNorm[0]; scaleMat[1][1] /= bNorm[1]; scaleMat[2][2] /= bNorm[2]; m_skewMat *= scaleMat; // Setup basis normalisation array // Intel and MSBuild can't handle this // m_basisNorm = {ol.astar(), ol.bstar(), ol.cstar()}; m_basisNorm.push_back(ol.astar()); m_basisNorm.push_back(ol.bstar()); m_basisNorm.push_back(ol.cstar()); // Expand matrix to 4 dimensions if necessary if (4 == m_numDims) { m_basisNorm.push_back(1.0); Kernel::DblMatrix temp(4, 4, true); for (std::size_t i = 0; i < 3; i++) { for (std::size_t j = 0; j < 3; j++) { temp[i][j] = m_skewMat[i][j]; } } m_skewMat = temp; } // Convert affine matrix to similar type as others Kernel::DblMatrix affMat(aff.numRows(), aff.numCols()); for (std::size_t i = 0; i < aff.numRows(); i++) { for (std::size_t j = 0; j < aff.numCols(); j++) { affMat[i][j] = aff[i][j]; } } // Strip affine matrix down to correct dimensions this->stripMatrix(affMat); // Perform similarity transform to get coordinate orientation correct m_skewMat = affMat.Tprime() * (m_skewMat * affMat); m_basisNorm = affMat * m_basisNorm; if (4 == m_numDims) { this->stripMatrix(m_skewMat); } this->findSkewBasis(m_basisX, m_basisNorm[0]); this->findSkewBasis(m_basisY, m_basisNorm[1]); this->findSkewBasis(m_basisZ, m_basisNorm[2]); }
/// Run the algorithm void PredictFractionalPeaks::exec() { PeaksWorkspace_sptr Peaks=getProperty("Peaks"); vector<double> hOffsets = getProperty("HOffset"); vector<double> kOffsets = getProperty("KOffset"); vector<double> lOffsets = getProperty("LOffset"); if ( hOffsets.empty())hOffsets.push_back(0.0); if ( kOffsets.empty())kOffsets.push_back(0.0); if ( lOffsets.empty())lOffsets.push_back(0.0); ; bool includePeaksInRange= getProperty("IncludeAllPeaksInRange"); if( Peaks->getNumberPeaks()<=0) { g_log.error()<<"There are No peaks in the input PeaksWorkspace\n"; return; } API::Sample samp= Peaks->sample(); Geometry::OrientedLattice &ol = samp.getOrientedLattice(); Geometry::Instrument_const_sptr Instr = Peaks->getInstrument(); boost::shared_ptr<IPeaksWorkspace> OutPeaks=WorkspaceFactory::Instance().createPeaks(); OutPeaks->setInstrument(Instr); // AnalysisDataService::Instance().addOrReplace(getPropertyValue("FracPeaks"),OutPeaks); V3D hkl; int peakNum =0; int NPeaks = Peaks->getNumberPeaks(); Kernel::Matrix<double> Gon; Gon.identityMatrix(); double Hmin= getProperty("Hmin"); double Hmax= getProperty("Hmax"); double Kmin= getProperty("Kmin"); double Kmax= getProperty("Kmax"); double Lmin= getProperty("Lmin"); double Lmax= getProperty("Lmax"); int N=NPeaks; if( includePeaksInRange) { N=(int)((Hmax-Hmin+1)*(Kmax-Kmin+1)*(Lmax-Lmin+1)+.5); N=max<int>(100,N); } IPeak& peak0 =Peaks->getPeak(0); int RunNumber = peak0.getRunNumber(); Gon=peak0.getGoniometerMatrix(); Progress prog(this, 0, 1,N); if( includePeaksInRange) { hkl[0]=Hmin; hkl[1]=Kmin; hkl[2]=Lmin; }else { hkl[0]=peak0.getH(); hkl[1]=peak0.getK(); hkl[2] =peak0.getL(); } Kernel::DblMatrix UB= ol.getUB(); vector< vector<int> > AlreadyDonePeaks; bool done = false; int ErrPos = 1;//Used to determine position in code of a throw while( !done) { for( size_t hoffset=0;hoffset<hOffsets.size();hoffset++) for(size_t koffset=0;koffset<kOffsets.size();koffset++) for( size_t loffset=0;loffset<lOffsets.size();loffset++) try { V3D hkl1( hkl ); ErrPos = 0; hkl1[0] += hOffsets[hoffset] ; hkl1[1] += kOffsets[koffset] ; hkl1[2] += lOffsets[loffset] ; Kernel::V3D Qs = UB * hkl1 ; Qs*= 2.0; Qs*=M_PI; Qs=Gon*Qs; if( Qs[2] <= 0 ) continue; ErrPos=1; boost::shared_ptr<IPeak> peak( Peaks->createPeak( Qs, 1 )); peak->setGoniometerMatrix(Gon); if (Qs[2]>0 && peak->findDetector()) { ErrPos=2; vector<int> SavPk; SavPk.push_back(RunNumber); SavPk.push_back((int)floor(1000*hkl1[0]+.5)); SavPk.push_back((int)floor(1000*hkl1[1]+.5)); SavPk.push_back((int)floor(1000*hkl1[2]+.5)); //TODO keep list sorted so searching is faster? vector<vector<int> >::iterator it = find(AlreadyDonePeaks.begin(),AlreadyDonePeaks.end(),SavPk); ErrPos=3; if( it == AlreadyDonePeaks.end()) AlreadyDonePeaks.push_back(SavPk); else continue; ErrPos=4; peak->setHKL(hkl1); peak->setRunNumber(RunNumber); OutPeaks->addPeak(*peak); } }catch(...) { if( ErrPos != 1)// setQLabFrame in createPeak throws exception throw new std::invalid_argument( "Invalid data at this point"); } if( includePeaksInRange) { hkl[0]++; if( hkl[0]>Hmax) { hkl[0]=Hmin; hkl[1]++; if( hkl[1]> Kmax) { hkl[1]=Kmin; hkl[2]++; if( hkl[2]> Lmax) done = true; } } }else { peakNum++; if( peakNum >= NPeaks) done = true; else {// peak0= Peaks->getPeak(peakNum); IPeak& peak1= Peaks->getPeak(peakNum); //??? could not assign to peak0 above. Did not work // the peak that peak0 was associated with did NOT change hkl[0]=peak1.getH(); hkl[1]=peak1.getK(); hkl[2] =peak1.getL(); Gon=peak1.getGoniometerMatrix(); RunNumber = peak1.getRunNumber(); } } prog.report(); } setProperty("FracPeaks",OutPeaks); }
/* Execute the algorithm. */ void ConvertToQ3DdE::exec(){ Timer tim, timtotal; CPUTimer cputim, cputimtotal; // -------- Input workspace MatrixWorkspace_sptr inMatrixWS = getProperty("InputWorkspace"); Workspace2D_sptr inWS2D = boost::dynamic_pointer_cast<Workspace2D>(inMatrixWS); // get the energy axis NumericAxis *pEnAxis = dynamic_cast<NumericAxis *>(inWS2D->getAxis(0)); if(!pEnAxis){ convert_log.error()<<"Can not get proper energy axis from processed workspace\n"; throw(std::invalid_argument("Input workspace is not propwer converted to energy workspace")); } size_t lastInd = inWS2D->getAxis(0)->length()-1; double E_max = inWS2D->getAxis(0)->operator()(lastInd); double E_min = inWS2D->getAxis(0)->operator()(0); //double E_min = inWS2D->readX(0).front(); //double E_max = inWS2D->readX(0).back(); if(E_min>=E_max){ convert_log.error()<<" expecting to process energy form "<<E_min<<" to "<<E_max<<" but Emin>=Emax\n"; throw(std::invalid_argument(" Emin>=Emax")); } //*** Input energy // get and check input energy double Ei = getProperty("EnergyInput"); // check if workspace knows better if(inWS2D->run().hasProperty("Ei")){ double Ei_t = boost::lexical_cast<double>(inWS2D->run().getProperty("Ei")->value()); if(std::fabs(Ei-Ei_t)>double(FLT_EPSILON)){ g_log.information()<<" energy: "<<Ei<<" obtained from the algorithm parameters has been replaced by the energy:"<<Ei_t<<", obtained from the workspace\n"; Ei=Ei_t; setProperty("EnergyInput", Ei); } } if (E_max >Ei){ convert_log.error()<<"Maximal elergy transferred to sample eq "<<E_max<<" and exceeds the input energy "<<Ei<<std::endl; throw(std::invalid_argument("Maximal transferred energy exceeds input energy")); } // the wawe vector of input neutrons; double ki=sqrt(Ei/PhysicalConstants::E_mev_toNeutronWavenumberSq); std::vector<double> QEmin = getProperty("MinQdE_values"); std::vector<double> QEmax = getProperty("MaxQdE_values"); // Try to get the output workspace IMDEventWorkspace_sptr i_out = getProperty("OutputWorkspace"); boost::shared_ptr<MDEvents::MDEventWorkspace<MDE,4> > ws = boost::dynamic_pointer_cast<MDEvents::MDEventWorkspace<MDE,4> >( i_out ); std::string dimensionNames[4] = {"Q_x", "Q_y", "Q_z","DeltaE"}; if (ws){ //check existing worspace limits and agree these with new limits if they were specified; if(QEmin.empty())QEmin.assign(4, FLT_MAX); if(QEmax.empty())QEmax.assign(4,-FLT_MAX); for(int i=0;i<4;i++){ // Check that existing workspace dimensions make sense with the desired one (using the name) if (ws->getDimension(i)->getName() != dimensionNames[i]){ convert_log.error()<<"The existing MDEventWorkspace " + ws->getName() + " has different dimensions than were requested! Either give a different name for the output, or change the OutputDimensions parameter.\n"; throw std::runtime_error("The existing MDEventWorkspace " + ws->getName() + " has different dimensions than were requested! Either give a different name for the output, or change the OutputDimensions parameter."); } // coordinate existing and nwe double ws_min = ws->getDimension(i)->getMinimum(); double ws_max = ws->getDimension(i)->getMaximum(); if(ws_min>QEmin[i])QEmin[i]=ws_min; if(ws_max<QEmax[i])QEmax[i]=ws_max; } // verify that final limits are correct check_max_morethen_min(QEmin,QEmax); }else{ if(QEmin.empty()||QEmax.empty()){ convert_log.error()<<" min and max Q-dE values can not be empty when creating new workspace"; throw(std::invalid_argument(" min-max property is empty")); } if(QEmin.size()!=4||QEmax.size()!=4){ convert_log.error()<<" min and max Q-dE values have to had 4 elements each"; throw(std::invalid_argument(" min-max is not 4Dimensional")); } check_max_morethen_min(QEmin,QEmax); std::string dimensionUnits[4] = {"Amgstroms^-1", "Amgstroms^-1", "Amgstroms^-1","meV"}; ws = create_empty4DEventWS(dimensionNames,dimensionUnits,QEmin,QEmax); } ws->splitBox(); //BoxController_sptr bc = ws->getBoxController(); // if (!bc) // throw std::runtime_error("Output MDEventWorkspace does not have a BoxController!"); // copy experiment info into ExperimentInfo_sptr ExperimentInfo(inWS2D->cloneExperimentInfo()); uint16_t runIndex = ws->addExperimentInfo(ExperimentInfo); // Initalize the matrix to 3x3 identity Kernel::Matrix<double> mat = Kernel::Matrix<double>(3,3, true); // Set the matrix based on UB etc. Kernel::Matrix<double> ub = inWS2D->sample().getOrientedLattice().getUB(); Kernel::Matrix<double> gon =inWS2D->run().getGoniometer().getR(); // As per Busing and Levy 1967, HKL = Goniometer * UB * q_lab_frame mat = gon * ub; std::vector<double> rotMat = mat.get_vector(); const size_t numSpec = inWS2D->getNumberHistograms(); const size_t specSize = inWS2D->blocksize(); // Initialise the progress reporting object Progress progress(this,0.0,1.0,numSpec); // Try to check if one should use preprocessed detector positions or try to calculate the new one bool reuse_preprocecced_detectors = getProperty("UsePreprocessedDetectors"); if(!(reuse_preprocecced_detectors&&det_loc.is_defined()))process_detectors_positions(inWS2D); // allocate the events buffer; // std::vector<MDE> out_events; // out_events.reserve(specSize); // To track when to split up boxes // size_t eventsAdded = 0; // size_t lastNumBoxes = ws->getBoxController()->getTotalNumMDBoxes(); // // Create the thread pool that will run all of these. // ThreadScheduler * ts = new ThreadSchedulerLargestCost(); // ThreadPool tp(ts); // boost::function<void ()> func; // func = boost::bind(&ConvertToQ3DdE::convertEventList<TofEvent>, &*this, static_cast<int>(wi)); // size_t n_added_events(0); size_t SPLIT_LEVEL(1000); // PARALLEL_FOR1(inWS2D) for (int64_t i = 0; i < int64_t(numSpec); ++i) { // PARALLEL_START_INTERUPT_REGION const MantidVec& E_transfer = inWS2D->readX(i); const MantidVec& Signal = inWS2D->readY(i); const MantidVec& Error = inWS2D->readE(i); int32_t det_id = det_loc.det_id[i]; coord_t QE[4]; for (size_t j = 0; j < specSize; ++j) { // drop emtpy events if(Signal[j]<FLT_EPSILON)continue; double E_tr = 0.5*(E_transfer[j]+E_transfer[j+1]); if(E_tr<E_min||E_tr>=E_max)continue; double k_tr = sqrt((Ei-E_tr)/PhysicalConstants::E_mev_toNeutronWavenumberSq); double ex = det_loc.det_dir[i].X(); double ey = det_loc.det_dir[i].Y(); double ez = det_loc.det_dir[i].Z(); double qx = -ex*k_tr; double qy = -ey*k_tr; double qz = ki - ez*k_tr; QE[0] = (coord_t)(rotMat[0]*qx+rotMat[3]*qy+rotMat[6]*qz); if(QE[0]<QEmin[0]||QE[0]>=QEmax[0])continue; QE[1] = (coord_t)(rotMat[1]*qx+rotMat[4]*qy+rotMat[7]*qz); if(QE[1]<QEmin[1]||QE[1]>=QEmax[1])continue; QE[2] = (coord_t)(rotMat[2]*qx+rotMat[5]*qy+rotMat[8]*qz); if(QE[2]<QEmin[2]||QE[2]>=QEmax[2])continue; QE[3] = (coord_t)E_tr; float ErrSq = float(Error[j]*Error[j]); ws->addEvent(MDE(float(Signal[j]),ErrSq,runIndex,det_id,QE)); n_added_events++; } // This splits up all the boxes according to split thresholds and sizes. //Kernel::ThreadScheduler * ts = new ThreadSchedulerFIFO(); //ThreadPool tp(NULL); if(n_added_events>SPLIT_LEVEL){ ws->splitAllIfNeeded(NULL); n_added_events=0; } //tp.joinAll(); progress.report(i); // PARALLEL_END_INTERUPT_REGION } // PARALLEL_CHECK_INTERUPT_REGION if(n_added_events>0){ ws->splitAllIfNeeded(NULL); n_added_events=0; } ws->refreshCache(); progress.report(); // Save the output setProperty("OutputWorkspace", boost::dynamic_pointer_cast<IMDEventWorkspace>(ws)); // // // // ------------------- Cache values that are common for all --------------------------- // // Extract some parameters global to the instrument // in_ws->getInstrument()->getInstrumentParameters(l1,beamline,beamline_norm, samplePos); // beamline_norm = beamline.norm(); // beamDir = beamline / beamline.norm(); // // //To get all the detector ID's // in_ws->getInstrument()->getDetectors(allDetectors); // // size_t totalCost = in_ws->getNumberEvents(); // prog = new Progress(this, 0, 1.0, totalCost); //// if (DODEBUG) prog = new ProgressText(0, 1.0, totalCost, true); //// if (DODEBUG) prog->setNotifyStep(1); // // // Create the thread pool that will run all of these. // ThreadScheduler * ts = new ThreadSchedulerLargestCost(); // ThreadPool tp(ts); // // if (DODEBUG) std::cout << cputim << ": initial setup. There are " << lastNumBoxes << " MDBoxes.\n"; // // for (size_t wi=0; wi < in_ws->getNumberHistograms(); wi++) // { // // Equivalent of: this->convertEventList(wi); // EventList & el = in_ws->getEventList(wi); // // // We want to bind to the right templated function, so we have to know the type of TofEvent contained in the EventList. // boost::function<void ()> func; // switch (el.getEventType()) // { // case TOF: // func = boost::bind(&ConvertToQ3DdE::convertEventList<TofEvent>, &*this, static_cast<int>(wi)); // break; // case WEIGHTED: // func = boost::bind(&ConvertToQ3DdE::convertEventList<WeightedEvent>, &*this, static_cast<int>(wi)); // break; // case WEIGHTED_NOTIME: // func = boost::bind(&ConvertToQ3DdE::convertEventList<WeightedEventNoTime>, &*this, static_cast<int>(wi)); // break; // default: // throw std::runtime_error("EventList had an unexpected data type!"); // } // // // Give this task to the scheduler // double cost = double(el.getNumberEvents()); // ts->push( new FunctionTask( func, cost) ); // // // Keep a running total of how many events we've added // eventsAdded += el.getNumberEvents(); // if (bc->shouldSplitBoxes(eventsAdded, lastNumBoxes)) // { // if (DODEBUG) std::cout << cputim << ": Added tasks worth " << eventsAdded << " events.\n"; // // Do all the adding tasks // tp.joinAll(); // if (DODEBUG) std::cout << cputim << ": Performing the addition of these events.\n"; // // // Now do all the splitting tasks // ws->splitAllIfNeeded(ts); // if (ts->size() > 0) // prog->doReport("Splitting Boxes"); // tp.joinAll(); // // // Count the new # of boxes. // lastNumBoxes = ws->getBoxController()->getTotalNumMDBoxes(); // if (DODEBUG) std::cout << cputim << ": Performing the splitting. There are now " << lastNumBoxes << " boxes.\n"; // eventsAdded = 0; // } // } // // if (DODEBUG) std::cout << cputim << ": We've added tasks worth " << eventsAdded << " events.\n"; // // tp.joinAll(); // if (DODEBUG) std::cout << cputim << ": Performing the FINAL addition of these events.\n"; // // // Do a final splitting of everything // ws->splitAllIfNeeded(ts); // tp.joinAll(); // if (DODEBUG) std::cout << cputim << ": Performing the FINAL splitting of boxes. There are now " << ws->getBoxController()->getTotalNumMDBoxes() <<" boxes\n"; // // // // Recount totals at the end. // cputim.reset(); // ws->refreshCache(); // if (DODEBUG) std::cout << cputim << ": Performing the refreshCache().\n"; // // //TODO: Centroid in parallel, maybe? // ws->getBox()->refreshCentroid(NULL); // if (DODEBUG) std::cout << cputim << ": Performing the refreshCentroid().\n"; // // // if (DODEBUG) // { // std::cout << "Workspace has " << ws->getNPoints() << " events. This took " << cputimtotal << " in total.\n"; // std::vector<std::string> stats = ws->getBoxControllerStats(); // for (size_t i=0; i<stats.size(); ++i) // std::cout << stats[i] << "\n"; // std::cout << std::endl; // } // // }