void LoadIsawUB::readModulatedUB(std::ifstream &in, DblMatrix &ub) { int ModDim = 0; Kernel::DblMatrix modub(3, 3); Kernel::DblMatrix ModVecErr(3, 3); int maxorder = 0; bool crossterm = false; std::string s; double val; s = getWord(in, true); if (!convert(s, val)) { readToEndOfLine(in, true); for (size_t row = 0; row < 3; row++) { for (size_t col = 0; col < 3; col++) { s = getWord(in, true); if (!convert(s, val)) throw std::runtime_error( "The string '" + s + "' in the file was not understood as a number."); modub[row][col] = val; } readToEndOfLine(in, true); if (modub[row][0] != 0.0 || modub[row][1] != 0.0 || modub[row][2] != 0.0) ModDim++; } } readToEndOfLine(in, true); double latVals[6]; for (double &latVal : latVals) { s = getWord(in, true); if (!convert(s, val)) throw std::runtime_error("The string '" + s + "' in the file was not understood as a number."); latVal = val; } if (ModDim > 0) { readToEndOfLine(in, true); readToEndOfLine(in, true); for (int i = 0; i < ModDim; i++) { readToEndOfLine(in, true); for (int j = 0; j < 4; j++) s = getWord(in, true); for (int j = 0; j < 3; j++) { s = getWord(in, true); if (!convert(s, val)) throw std::runtime_error( "The string '" + s + "' in the file was not understood as a number."); ModVecErr[i][j] = val; } readToEndOfLine(in, true); } readToEndOfLine(in, true); for (int j = 0; j < 3; j++) s = getWord(in, true); if (!convert(s, val)) throw std::runtime_error("The string '" + s + "' in the file was not understood as a number."); maxorder = static_cast<int>(val); readToEndOfLine(in, true); for (int j = 0; j < 3; j++) s = getWord(in, true); bool valBool; if (!convert(s, valBool)) throw std::runtime_error("The string '" + s + "' in the file was not understood as a number."); crossterm = valBool; } // Adjust the UB by transposing ub = ub.Transpose(); modub = modub.Transpose(); /* The method in OrientedLattice gets both the lattice parameters and the U * matrix from the UB matrix. * This is compatible (same results) with the ISAW lattice parameters */ OrientedLattice *latt = new OrientedLattice(); latt->setUB(ub); latt->setError(latVals[0], latVals[1], latVals[2], latVals[3], latVals[4], latVals[5]); latt->setModUB(modub); for (int i = 0; i < ModDim; i++) latt->setModerr(i, ModVecErr[i][0], ModVecErr[i][1], ModVecErr[i][2]); latt->setMaxOrder(maxorder); latt->setCrossTerm(crossterm); DblMatrix U = latt->getU(); // Swap rows around to accound for IPNS convention DblMatrix U2 = U; // Swap rows around for (size_t r = 0; r < 3; r++) { U2[2][r] = U[0][r]; U2[1][r] = U[2][r]; U2[0][r] = U[1][r]; } U = U2; const bool checkU = getProperty("CheckUMatrix"); latt->setU(U, !checkU); // In and Out workspace. Workspace_sptr ws1 = getProperty("InputWorkspace"); ExperimentInfo_sptr ws; MultipleExperimentInfos_sptr MDWS = boost::dynamic_pointer_cast<MultipleExperimentInfos>(ws1); if (MDWS != nullptr) { ws = MDWS->getExperimentInfo(0); } else { ws = boost::dynamic_pointer_cast<ExperimentInfo>(ws1); } if (!ws) throw std::invalid_argument("Must specify either a MatrixWorkspace or a " "PeaksWorkspace or a MDWorkspace."); // Save it into the workspace ws->mutableSample().setOrientedLattice(latt); // Save it to every experiment info in MD workspaces if ((MDWS != nullptr) && (MDWS->getNumExperimentInfo() > 1)) { for (uint16_t i = 1; i < MDWS->getNumExperimentInfo(); i++) { ws = MDWS->getExperimentInfo(i); ws->mutableSample().setOrientedLattice(latt); } } delete latt; this->setProperty("InputWorkspace", ws1); }
/** Execute the algorithm. */ void IntegrateEllipsoids::exec() { // get the input workspace MatrixWorkspace_sptr wksp = getProperty("InputWorkspace"); EventWorkspace_sptr eventWS = boost::dynamic_pointer_cast<EventWorkspace>(wksp); Workspace2D_sptr histoWS = boost::dynamic_pointer_cast<Workspace2D>(wksp); if (!eventWS && !histoWS) { throw std::runtime_error("IntegrateEllipsoids needs either a " "EventWorkspace or Workspace2D as input."); } // error out if there are not events if (eventWS && eventWS->getNumberEvents() <= 0) { throw std::runtime_error( "IntegrateEllipsoids does not work for empty event lists"); } PeaksWorkspace_sptr in_peak_ws = getProperty("PeaksWorkspace"); if (!in_peak_ws) { throw std::runtime_error("Could not read the peaks workspace"); } double radius_m = getProperty("RegionRadius"); double radius_s = getProperty("SatelliteRegionRadius"); int numSigmas = getProperty("NumSigmas"); double cutoffIsigI = getProperty("CutoffIsigI"); bool specify_size = getProperty("SpecifySize"); double peak_radius = getProperty("PeakSize"); double sate_peak_radius = getProperty("SatellitePeakSize"); double back_inner_radius = getProperty("BackgroundInnerSize"); double sate_back_inner_radius = getProperty("SatelliteBackgroundInnerSize"); double back_outer_radius = getProperty("BackgroundOuterSize"); double sate_back_outer_radius = getProperty("SatelliteBackgroundOuterSize"); bool hkl_integ = getProperty("IntegrateInHKL"); bool integrateEdge = getProperty("IntegrateIfOnEdge"); bool adaptiveQBackground = getProperty("AdaptiveQBackground"); double adaptiveQMultiplier = getProperty("AdaptiveQMultiplier"); double adaptiveQBackgroundMultiplier = 0.0; bool useOnePercentBackgroundCorrection = getProperty("UseOnePercentBackgroundCorrection"); if (adaptiveQBackground) adaptiveQBackgroundMultiplier = adaptiveQMultiplier; if (!integrateEdge) { // This only fails in the unit tests which say that MaskBTP is not // registered try { runMaskDetectors(in_peak_ws, "Tube", "edges"); runMaskDetectors(in_peak_ws, "Pixel", "edges"); } catch (...) { g_log.error("Can't execute MaskBTP algorithm for this instrument to set " "edge for IntegrateIfOnEdge option"); } calculateE1(in_peak_ws->detectorInfo()); // fill E1Vec for use in detectorQ } Mantid::DataObjects::PeaksWorkspace_sptr peak_ws = getProperty("OutputWorkspace"); if (peak_ws != in_peak_ws) peak_ws = in_peak_ws->clone(); // get UBinv and the list of // peak Q's for the integrator std::vector<Peak> &peaks = peak_ws->getPeaks(); size_t n_peaks = peak_ws->getNumberPeaks(); size_t indexed_count = 0; std::vector<V3D> peak_q_list; std::vector<std::pair<double, V3D>> qList; std::vector<V3D> hkl_vectors; std::vector<V3D> mnp_vectors; int ModDim = 0; for (size_t i = 0; i < n_peaks; i++) // Note: we skip un-indexed peaks { V3D hkl(peaks[i].getIntHKL()); V3D mnp(peaks[i].getIntMNP()); if (mnp[0] != 0 && ModDim == 0) ModDim = 1; if (mnp[1] != 0 && ModDim == 1) ModDim = 2; if (mnp[2] != 0 && ModDim == 2) ModDim = 3; // use tolerance == 1 to just check for (0,0,0,0,0,0) if (Geometry::IndexingUtils::ValidIndex(hkl, 1.0)) { peak_q_list.emplace_back(peaks[i].getQLabFrame()); qList.emplace_back(1., V3D(peaks[i].getQLabFrame())); hkl_vectors.push_back(hkl); mnp_vectors.push_back(mnp); indexed_count++; } } if (indexed_count < 3) throw std::runtime_error( "At least three linearly independent indexed peaks are needed."); // Get UB using indexed peaks and // lab-Q vectors Matrix<double> UB(3, 3, false); Matrix<double> modUB(3, 3, false); Matrix<double> modHKL(3, 3, false); Geometry::IndexingUtils::Optimize_6dUB(UB, modUB, hkl_vectors, mnp_vectors, ModDim, peak_q_list); int maxOrder = 0; bool CT = false; if (peak_ws->sample().hasOrientedLattice()) { OrientedLattice lattice = peak_ws->mutableSample().getOrientedLattice(); lattice.setUB(UB); lattice.setModUB(modUB); modHKL = lattice.getModHKL(); maxOrder = lattice.getMaxOrder(); CT = lattice.getCrossTerm(); } Matrix<double> UBinv(UB); UBinv.Invert(); UBinv *= (1.0 / (2.0 * M_PI)); std::vector<double> PeakRadiusVector(n_peaks, peak_radius); std::vector<double> BackgroundInnerRadiusVector(n_peaks, back_inner_radius); std::vector<double> BackgroundOuterRadiusVector(n_peaks, back_outer_radius); if (specify_size) { if (back_outer_radius > radius_m) throw std::runtime_error( "BackgroundOuterSize must be less than or equal to the RegionRadius"); if (back_inner_radius >= back_outer_radius) throw std::runtime_error( "BackgroundInnerSize must be less BackgroundOuterSize"); if (peak_radius > back_inner_radius) throw std::runtime_error( "PeakSize must be less than or equal to the BackgroundInnerSize"); } // make the integrator Integrate3DEvents integrator(qList, hkl_vectors, mnp_vectors, UBinv, modHKL, radius_m, radius_s, maxOrder, CT, useOnePercentBackgroundCorrection); // get the events and add // them to the inegrator // set up a descripter of where we are going this->initTargetWSDescr(wksp); // set up the progress bar const size_t numSpectra = wksp->getNumberHistograms(); Progress prog(this, 0.5, 1.0, numSpectra); if (eventWS) { // process as EventWorkspace qListFromEventWS(integrator, prog, eventWS, UBinv, hkl_integ); } else { // process as Workspace2D qListFromHistoWS(integrator, prog, histoWS, UBinv, hkl_integ); } double inti; double sigi; std::vector<double> principalaxis1, principalaxis2, principalaxis3; std::vector<double> sateprincipalaxis1, sateprincipalaxis2, sateprincipalaxis3; for (size_t i = 0; i < n_peaks; i++) { const V3D hkl(peaks[i].getIntHKL()); const V3D mnp(peaks[i].getIntMNP()); if (Geometry::IndexingUtils::ValidIndex(hkl, 1.0) || Geometry::IndexingUtils::ValidIndex(mnp, 1.0)) { const V3D peak_q = peaks[i].getQLabFrame(); // modulus of Q const double lenQpeak = adaptiveQMultiplier != 0.0 ? peak_q.norm() : 0.0; double adaptiveRadius = adaptiveQMultiplier * lenQpeak + peak_radius; if (mnp != V3D(0, 0, 0)) adaptiveRadius = adaptiveQMultiplier * lenQpeak + sate_peak_radius; if (adaptiveRadius <= 0.0) { g_log.error() << "Error: Radius for integration sphere of peak " << i << " is negative = " << adaptiveRadius << '\n'; peaks[i].setIntensity(0.0); peaks[i].setSigmaIntensity(0.0); PeakRadiusVector[i] = 0.0; BackgroundInnerRadiusVector[i] = 0.0; BackgroundOuterRadiusVector[i] = 0.0; continue; } double adaptiveBack_inner_radius; double adaptiveBack_outer_radius; if (mnp == V3D(0, 0, 0)) { adaptiveBack_inner_radius = adaptiveQBackgroundMultiplier * lenQpeak + back_inner_radius; adaptiveBack_outer_radius = adaptiveQBackgroundMultiplier * lenQpeak + back_outer_radius; } else { adaptiveBack_inner_radius = adaptiveQBackgroundMultiplier * lenQpeak + sate_back_inner_radius; adaptiveBack_outer_radius = adaptiveQBackgroundMultiplier * lenQpeak + sate_back_outer_radius; } PeakRadiusVector[i] = adaptiveRadius; BackgroundInnerRadiusVector[i] = adaptiveBack_inner_radius; BackgroundOuterRadiusVector[i] = adaptiveBack_outer_radius; std::vector<double> axes_radii; Mantid::Geometry::PeakShape_const_sptr shape = integrator.ellipseIntegrateModEvents( E1Vec, peak_q, hkl, mnp, specify_size, adaptiveRadius, adaptiveBack_inner_radius, adaptiveBack_outer_radius, axes_radii, inti, sigi); peaks[i].setIntensity(inti); peaks[i].setSigmaIntensity(sigi); peaks[i].setPeakShape(shape); if (axes_radii.size() == 3) { if (inti / sigi > cutoffIsigI || cutoffIsigI == EMPTY_DBL()) { if (mnp == V3D(0, 0, 0)) { principalaxis1.push_back(axes_radii[0]); principalaxis2.push_back(axes_radii[1]); principalaxis3.push_back(axes_radii[2]); } else { sateprincipalaxis1.push_back(axes_radii[0]); sateprincipalaxis2.push_back(axes_radii[1]); sateprincipalaxis3.push_back(axes_radii[2]); } } } } else { peaks[i].setIntensity(0.0); peaks[i].setSigmaIntensity(0.0); } } if (principalaxis1.size() > 1) { Statistics stats1 = getStatistics(principalaxis1); g_log.notice() << "principalaxis1: " << " mean " << stats1.mean << " standard_deviation " << stats1.standard_deviation << " minimum " << stats1.minimum << " maximum " << stats1.maximum << " median " << stats1.median << "\n"; Statistics stats2 = getStatistics(principalaxis2); g_log.notice() << "principalaxis2: " << " mean " << stats2.mean << " standard_deviation " << stats2.standard_deviation << " minimum " << stats2.minimum << " maximum " << stats2.maximum << " median " << stats2.median << "\n"; Statistics stats3 = getStatistics(principalaxis3); g_log.notice() << "principalaxis3: " << " mean " << stats3.mean << " standard_deviation " << stats3.standard_deviation << " minimum " << stats3.minimum << " maximum " << stats3.maximum << " median " << stats3.median << "\n"; if (sateprincipalaxis1.size() > 1) { Statistics satestats1 = getStatistics(sateprincipalaxis1); g_log.notice() << "sateprincipalaxis1: " << " mean " << satestats1.mean << " standard_deviation " << satestats1.standard_deviation << " minimum " << satestats1.minimum << " maximum " << satestats1.maximum << " median " << satestats1.median << "\n"; Statistics satestats2 = getStatistics(sateprincipalaxis2); g_log.notice() << "sateprincipalaxis2: " << " mean " << satestats2.mean << " standard_deviation " << satestats2.standard_deviation << " minimum " << satestats2.minimum << " maximum " << satestats2.maximum << " median " << satestats2.median << "\n"; Statistics satestats3 = getStatistics(sateprincipalaxis3); g_log.notice() << "sateprincipalaxis3: " << " mean " << satestats3.mean << " standard_deviation " << satestats3.standard_deviation << " minimum " << satestats3.minimum << " maximum " << satestats3.maximum << " median " << satestats3.median << "\n"; } constexpr size_t histogramNumber = 3; Workspace_sptr wsProfile = WorkspaceFactory::Instance().create( "Workspace2D", histogramNumber, principalaxis1.size(), principalaxis1.size()); Workspace2D_sptr wsProfile2D = boost::dynamic_pointer_cast<Workspace2D>(wsProfile); AnalysisDataService::Instance().addOrReplace("EllipsoidAxes", wsProfile2D); // set output workspace Points points(principalaxis1.size(), LinearGenerator(0, 1)); wsProfile2D->setHistogram(0, points, Counts(std::move(principalaxis1))); wsProfile2D->setHistogram(1, points, Counts(std::move(principalaxis2))); wsProfile2D->setHistogram(2, points, Counts(std::move(principalaxis3))); if (cutoffIsigI != EMPTY_DBL()) { principalaxis1.clear(); principalaxis2.clear(); principalaxis3.clear(); sateprincipalaxis1.clear(); sateprincipalaxis2.clear(); sateprincipalaxis3.clear(); specify_size = true; peak_radius = std::max(std::max(stats1.mean, stats2.mean), stats3.mean) + numSigmas * std::max(std::max(stats1.standard_deviation, stats2.standard_deviation), stats3.standard_deviation); back_inner_radius = peak_radius; back_outer_radius = peak_radius * 1.25992105; // A factor of 2 ^ (1/3) // will make the background // shell volume equal to the peak region volume. for (size_t i = 0; i < n_peaks; i++) { V3D hkl(peaks[i].getIntHKL()); V3D mnp(peaks[i].getIntMNP()); if (Geometry::IndexingUtils::ValidIndex(hkl, 1.0) || Geometry::IndexingUtils::ValidIndex(mnp, 1.0)) { const V3D peak_q = peaks[i].getQLabFrame(); std::vector<double> axes_radii; integrator.ellipseIntegrateModEvents( E1Vec, peak_q, hkl, mnp, specify_size, peak_radius, back_inner_radius, back_outer_radius, axes_radii, inti, sigi); peaks[i].setIntensity(inti); peaks[i].setSigmaIntensity(sigi); if (axes_radii.size() == 3) { if (mnp == V3D(0, 0, 0)) { principalaxis1.push_back(axes_radii[0]); principalaxis2.push_back(axes_radii[1]); principalaxis3.push_back(axes_radii[2]); } else { sateprincipalaxis1.push_back(axes_radii[0]); sateprincipalaxis2.push_back(axes_radii[1]); sateprincipalaxis3.push_back(axes_radii[2]); } } } else { peaks[i].setIntensity(0.0); peaks[i].setSigmaIntensity(0.0); } } if (principalaxis1.size() > 1) { Workspace_sptr wsProfile2 = WorkspaceFactory::Instance().create( "Workspace2D", histogramNumber, principalaxis1.size(), principalaxis1.size()); Workspace2D_sptr wsProfile2D2 = boost::dynamic_pointer_cast<Workspace2D>(wsProfile2); AnalysisDataService::Instance().addOrReplace("EllipsoidAxes_2ndPass", wsProfile2D2); Points profilePoints(principalaxis1.size(), LinearGenerator(0, 1)); wsProfile2D->setHistogram(0, profilePoints, Counts(std::move(principalaxis1))); wsProfile2D->setHistogram(1, profilePoints, Counts(std::move(principalaxis2))); wsProfile2D->setHistogram(2, profilePoints, Counts(std::move(principalaxis3))); } } } // This flag is used by the PeaksWorkspace to evaluate whether it has been // integrated. peak_ws->mutableRun().addProperty("PeaksIntegrated", 1, true); // These flags are specific to the algorithm. peak_ws->mutableRun().addProperty("PeakRadius", PeakRadiusVector, true); peak_ws->mutableRun().addProperty("BackgroundInnerRadius", BackgroundInnerRadiusVector, true); peak_ws->mutableRun().addProperty("BackgroundOuterRadius", BackgroundOuterRadiusVector, true); setProperty("OutputWorkspace", peak_ws); }