43 "An input PeaksWorkspace.");
45 auto mustBePositive = std::make_shared<BoundedValidator<double>>();
46 mustBePositive->setLower(0.0);
47 declareProperty(
"ScalePeaks", 1.0, mustBePositive,
"Multiply FSQ and sig(FSQ) by scaleFactor");
48 declareProperty(
"MinDSpacing", 0.0,
"Minimum d-spacing (Angstroms)");
49 declareProperty(
"MinWavelength", 0.0,
"Minimum wavelength (Angstroms)");
50 declareProperty(
"MaxWavelength", 100.0,
"Maximum wavelength (Angstroms)");
52 declareProperty(
"AppendFile",
false,
53 "Append to file if true. Use same corrections as file.\n"
54 "If false, new file (default).");
55 declareProperty(
"ApplyAnvredCorrections",
false,
56 "Apply anvred corrections to peaks if true.\n"
57 "If false, no corrections during save (default).");
58 declareProperty(
"LinearScatteringCoef",
EMPTY_DBL(), mustBePositive,
59 "Linear scattering coefficient in 1/cm if not set with "
61 declareProperty(
"LinearAbsorptionCoef",
EMPTY_DBL(), mustBePositive,
62 "Linear absorption coefficient at 1.8 Angstroms in 1/cm if "
63 "not set with SetSampleMaterial");
64 declareProperty(
"Radius",
EMPTY_DBL(), mustBePositive,
"Radius of the sample in centimeters");
65 declareProperty(
"PowerLambda", 4.0,
"Power of lambda ");
67 " Spectrum data read from a spectrum file.");
69 declareProperty(std::make_unique<FileProperty>(
"Filename",
"",
FileProperty::Save,
".hkl"),
70 "Path to an hkl file to save.");
72 std::vector<std::string> histoTypes{
"Bank",
"RunNumber",
""};
73 declareProperty(
"SortBy", histoTypes[2], std::make_shared<StringListValidator>(histoTypes),
74 "Sort the histograms by bank, run number or both (default).");
75 declareProperty(
"MinIsigI",
EMPTY_DBL(), mustBePositive,
"The minimum I/sig(I) ratio");
76 declareProperty(
"WidthBorder",
EMPTY_INT(),
"Width of border of detectors");
77 declareProperty(
"MinIntensity",
EMPTY_DBL(), mustBePositive,
"The minimum Intensity");
80 "Output PeaksWorkspace");
81 declareProperty(
"HKLDecimalPlaces",
EMPTY_INT(),
82 "Number of decimal places for fractional HKL. Default is integer HKL.");
83 declareProperty(
"DirectionCosines",
false,
84 "Extra columns (22 total) in file if true for direction cosines.\n"
85 "If false, original 14 columns (default).");
86 const std::vector<std::string> exts{
".mat",
".ub",
".txt"};
88 "Path to an ISAW-style UB matrix text file only needed for "
89 "DirectionCosines if workspace does not have lattice.");
101 peaksW =
m_ws->clone();
102 auto inst = peaksW->getInstrument();
103 std::vector<Peak> &peaks = peaksW->getPeaks();
116 if (peaksW->sample().hasOrientedLattice()) {
117 ol = peaksW->sample().getOrientedLattice();
122 std::ifstream in(fileUB.c_str());
124 throw std::runtime_error(
"A file containing the UB matrix must be input into UBFilename.");
130 for (
size_t row = 0; row < 3; row++) {
131 for (
size_t col = 0; col < 3; col++) {
134 throw std::runtime_error(
"The string '" + s +
"' in the file was not understood as a number.");
144 int bankSequence = 0;
150 if (convention ==
"Crystallography")
154 out.open(filename.c_str(), std::ios::out);
158 std::string bankPart =
"?";
161 using bankMap_t = std::map<int, std::vector<size_t>>;
162 using runMap_t = std::map<int, bankMap_t>;
163 std::set<int> uniqueBanks;
164 std::set<int> uniqueRuns;
166 for (
size_t i = 0; i < peaks.size(); ++i) {
171 if (bankName.size() <= 4) {
172 g_log.
information() <<
"Could not interpret bank number of peak " << i <<
"(" << bankName <<
")\n";
177 bankPart = bankName.substr(0, 4);
179 if (bankPart ==
"bank")
180 bankName = bankName.substr(4, bankName.size() - 4);
181 else if (bankPart ==
"WISH")
182 bankName = bankName.substr(9, bankName.size() - 9);
186 if (type.compare(0, 2,
"Ru") == 0)
187 runMap[run][bank].emplace_back(i);
189 runMap[bank][run].emplace_back(i);
191 uniqueBanks.insert(bank);
192 uniqueRuns.insert(run);
195 bool correctPeaks =
getProperty(
"ApplyAnvredCorrections");
196 std::vector<std::vector<double>> spectra;
197 std::vector<std::vector<double>> time;
204 API::Run &run = peaksW->mutableRun();
214 const Material &sampleMaterial = peaksW->sample().getMaterial();
215 const IObject *sampleShape{
nullptr};
224 sphere->setMaterial(
Material(
"SetInSaveHKL", neutron, 1.0));
226 sphere->setMaterial(sampleMaterial);
231 peaksW->mutableSample().setShape(sphere);
232 }
else if (peaksW->sample().getShape().hasValidShape()) {
233 sampleShape = &(peaksW->sample().getShape());
236 if (std::all_of(peaks.cbegin(), peaks.cend(), [](
auto &p) { return p.getAbsorptionWeightedPathLength() == 0; })) {
238 alg->setProperty(
"InputWorkspace", peaksW);
239 alg->setProperty(
"UseSinglePath",
true);
240 alg->executeAsChildAlg();
245 std::vector<double> spec(11);
247 std::ifstream infile;
249 infile.open(spectraFile.c_str());
250 if (infile.is_open()) {
252 for (
int wi = 0; wi < 8; wi++)
254 while (!infile.eof())
257 spectra.resize(a + 1);
259 std::stringstream ss(
STRING);
260 if (
STRING.find(
"Bank") == std::string::npos) {
261 double time0, spectra0;
262 ss >> time0 >> spectra0;
263 time[a].emplace_back(time0);
264 spectra[a].emplace_back(spectra0);
269 ss >> temp >> a0 >> temp >> a;
276 std::set<size_t> banned;
280 runMap_t::iterator runMap_it;
281 for (runMap_it = runMap.begin(); runMap_it != runMap.end(); ++runMap_it) {
284 bankMap_t &bankMap = runMap_it->second;
286 bankMap_t::iterator bankMap_it;
287 for (bankMap_it = bankMap.begin(); bankMap_it != bankMap.end(); ++bankMap_it) {
290 std::vector<size_t> &ids = bankMap_it->second;
293 for (
auto wi : ids) {
316 (p.
getCol() < widthBorder || p.
getRow() < widthBorder || p.
getCol() > (nCols - widthBorder) ||
317 p.
getRow() > (nRows - widthBorder))) {
322 bankName.erase(remove_if(bankName.begin(), bankName.end(), std::not_fn(::isdigit)), bankName.end());
331 if (dsp < dMin || lambda < wlMin || lambda > wlMax) {
336 double transmission{0}, tbar{0};
340 }
else if (sampleShape) {
342 transmission = exp(-tbar * 0.01 * sampleShape->material().attenuationCoefficient(
lambda));
357 out << std::setw(5 + decimalHKL) << std::fixed << std::setprecision(decimalHKL) << -p.
getH()
358 << std::setw(5 + decimalHKL) << std::fixed << std::setprecision(decimalHKL) << -p.
getK()
359 << std::setw(5 + decimalHKL) << std::fixed << std::setprecision(decimalHKL) << -p.
getL();
360 double correc = scaleFactor;
362 double relSigSpect = 0.0;
363 bankSequence =
static_cast<int>(std::distance(uniqueBanks.begin(), uniqueBanks.find(bank)));
364 runSequence =
static_cast<int>(std::distance(uniqueRuns.begin(), uniqueRuns.find(runNumber)));
367 double mu = (9.614 *
lambda) + 0.266;
369 double eff_center = 1.0 - std::exp(-
mu * depth);
372 std::shared_ptr<const IComponent> det0 = inst->getComponentByName(p.
getBankName());
373 if (inst->getName() ==
"CORELLI")
375 std::vector<Geometry::IComponent_const_sptr> children;
376 std::shared_ptr<const Geometry::ICompAssembly> asmb =
377 std::dynamic_pointer_cast<const Geometry::ICompAssembly>(inst->getComponentByName(p.
getBankName()));
378 asmb->getChildren(children,
false);
382 double cosA = det0->getDistance(*sample) / p.
getL2();
383 double pathlength = depth / cosA;
384 double eff_R = 1.0 - exp(-
mu * pathlength);
385 double sp_ratio = eff_center / eff_R;
386 double sinsqt = std::pow(
lambda / (2.0 * dsp), 2);
393 std::vector<double> xdata(1, 1.0);
394 std::vector<double> ydata;
396 double l1 = p.
getL1();
399 unit->toTOF(xdata, ydata, l1, 0, {{UnitParams::l2,
l2}, {UnitParams::twoTheta, theta2}});
400 double one = xdata[0];
401 double spect1 =
spectrumCalc(one, iSpec, time, spectra, bank);
402 relSigSpect = std::sqrt((1.0 / spect) + (1.0 / spect1));
406 throw std::runtime_error(
"Wavelength for normalizing to spectrum is out of range.");
408 correc = scaleFactor * sinsqt * cmonx * sp_ratio / (wl4 * spect * transmission);
410 if (inst->hasParameter(
"detScale" + bankName))
411 correc *=
static_cast<double>(inst->getNumberParameter(
"detScale" + bankName)[0]);
414 instBkg = 0. * 12.28 / cmonx * scaleFactor;
421 std::pow(relSigSpect * correc * p.
getIntensity(), 2) + instBkg);
424 if (ckIntensity > 99999.985)
426 <<
" is too large for format. Decrease ScalePeaks.\n";
427 out << std::setw(8) << std::fixed << std::setprecision(2) << ckIntensity;
429 out << std::setw(8) << std::fixed << std::setprecision(2) << cksigI;
432 out << std::setw(8) << std::fixed << std::setprecision(2) << p.
getIntensity();
434 out << std::setw(8) << std::fixed << std::setprecision(2) << p.
getSigmaIntensity();
436 if (type.compare(0, 2,
"Ba") == 0)
437 out << std::setw(4) << bankSequence + 1;
439 out << std::setw(4) << runSequence + 1;
442 out << std::setw(8) << std::fixed << std::setprecision(5) <<
lambda;
443 out << std::setw(8) << std::fixed << std::setprecision(5) << tbar;
447 auto RU = oriented * U;
451 V3D reverse_incident = inst->getSource()->getPos() - inst->getSample()->getPos();
457 V3D dir_cos_1 = RU * reverse_incident;
458 V3D dir_cos_2 = RU * dir;
460 for (
int k = 0; k < 3; ++k) {
461 out << std::setw(9) << std::fixed << std::setprecision(5) << dir_cos_1[k];
462 out << std::setw(9) << std::fixed << std::setprecision(5) << dir_cos_2[k];
465 out << std::setw(6) << runNumber;
467 out << std::setw(6) << seqNum;
469 out << std::setw(7) << std::fixed << std::setprecision(4) << transmission;
471 out << std::setw(4) << std::right << bank;
473 out << std::setw(9) << std::fixed << std::setprecision(5) << scattering;
475 out << std::setw(8) << std::fixed << std::setprecision(4) << dsp;
476 out << std::setw(7) << std::fixed << std::setprecision(2) << static_cast<double>(p.
getCol());
477 out << std::setw(7) << std::fixed << std::setprecision(2) << static_cast<double>(p.
getRow());
479 out << std::setw(8) << std::fixed << std::setprecision(4) <<
lambda;
481 out << std::setw(7) << std::fixed << std::setprecision(4) << tbar;
483 out << std::setw(7) << runNumber;
485 out << std::setw(7) << wi + 1;
487 out << std::setw(7) << std::fixed << std::setprecision(4) << transmission;
489 out << std::setw(4) << std::right << bank;
491 out << std::setw(9) << std::fixed << std::setprecision(5) << scattering;
493 out << std::setw(9) << std::fixed << std::setprecision(4) << dsp;
501 out << std::setw(4) << 0 << std::setw(4) << 0 << std::setw(4) << 0;
503 out << std::setw(5 + decimalHKL) << std::fixed << std::setprecision(decimalHKL) << 0.0 << std::setw(5 + decimalHKL)
504 << std::fixed << std::setprecision(decimalHKL) << 0.0 << std::setw(5 + decimalHKL) << std::fixed
505 << std::setprecision(decimalHKL) << 0.0;
507 out <<
" 0.00 0.00 0 0.00000 0.00000 0.00000 0.00000 0.00000"
508 " 0.00000 0.00000 0.00000 0 0 0.0000 0 0.00000 "
511 out <<
" 0.00 0.00 0 0.0000 0.0000 0 0 0.0000 "
518 std::vector<int> badPeaks;
519 for (
auto it = banned.crbegin(); it != banned.crend(); ++it) {
520 badPeaks.emplace_back(
static_cast<int>(*it));
522 peaksW->removePeaks(std::move(badPeaks));
525 if (append && Poco::File(filename.c_str()).exists()) {
527 load_alg->setPropertyValue(
"Filename", filename);
528 load_alg->setProperty(
"OutputWorkspace",
"peaks");
529 load_alg->executeAsChildAlg();
532 ws2->setInstrument(inst);
535 plus_alg->setProperty(
"LHSWorkspace", peaksW);
536 plus_alg->setProperty(
"RHSWorkspace", ws2);
537 plus_alg->executeAsChildAlg();
539 peaksW = plus_alg->getProperty(
"OutputWorkspace");
566 if (mur < 0. || mur > 2.5) {
567 std::ostringstream s;
569 throw std::runtime_error(
"muR is not in range of Dwiggins' table :" + s.str());
572 const double theta = twoth *
radtodeg * 0.5;
573 if (theta < 0. || theta > 90.) {
574 std::ostringstream s;
576 throw std::runtime_error(
"theta is not valid it must be in range [0, 90]");
583 if (std::fabs(
mu) < 1e-300)
586 tbar = -std::log(transmission) /
mu;
592 std::vector<std::vector<double>> spectra,
size_t id) {
597 double T =
TOF / 1000.;
599 double c1 = spectra[id][0];
600 double c2 = spectra[id][1];
601 double c3 = spectra[id][2];
602 double c4 = spectra[id][3];
603 double c5 = spectra[id][4];
604 double c6 = spectra[id][5];
605 double c7 = spectra[id][6];
606 double c8 = spectra[id][7];
607 double c9 = spectra[id][8];
608 double c10 = spectra[id][9];
609 double c11 = spectra[id][10];
611 spect = c1 + c2 * exp(-c3 / std::pow(T, 2)) / std::pow(T, 5) + c4 * exp(-c5 * std::pow(T, 2)) +
612 c6 * exp(-c7 * std::pow(T, 3)) + c8 * exp(-c9 * std::pow(T, 4)) + c10 * exp(-c11 * std::pow(T, 5));
615 for (i = 1; i < spectra[id].size(); ++i)
616 if (
TOF < time[
id][i])
618 spect = spectra[id][i - 1] +
619 (
TOF - time[id][i - 1]) / (time[
id][i] - time[
id][i - 1]) * (spectra[id][i] - spectra[id][i - 1]);
625 if (bankName ==
"None")
627 std::shared_ptr<const IComponent> parent =
m_ws->getInstrument()->getComponentByName(bankName);
630 if (parent->type() ==
"RectangularDetector") {
631 std::shared_ptr<const RectangularDetector> RDet = std::dynamic_pointer_cast<const RectangularDetector>(parent);
633 nCols = RDet->xpixels();
634 nRows = RDet->ypixels();
636 if (
m_ws->getInstrument()->getName() ==
"CORELLI")
638 std::vector<Geometry::IComponent_const_sptr> children;
639 std::shared_ptr<const Geometry::ICompAssembly> asmb =
640 std::dynamic_pointer_cast<const Geometry::ICompAssembly>(parent);
641 asmb->getChildren(children,
false);
642 parent = children[0];
644 std::vector<Geometry::IComponent_const_sptr> children;
645 std::shared_ptr<const Geometry::ICompAssembly> asmb =
646 std::dynamic_pointer_cast<const Geometry::ICompAssembly>(parent);
647 asmb->getChildren(children,
false);
648 std::shared_ptr<const Geometry::ICompAssembly> asmb2 =
649 std::dynamic_pointer_cast<const Geometry::ICompAssembly>(children[0]);
650 std::vector<Geometry::IComponent_const_sptr> grandchildren;
651 asmb2->getChildren(grandchildren,
false);
652 nRows =
static_cast<int>(grandchildren.size());
653 nCols =
static_cast<int>(children.size());
#define DECLARE_ALGORITHM(classname)
const std::vector< double > * lambda
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
@ OptionalLoad
to specify a file to read but the file doesn't have to exist
@ Save
to specify a file to write to, the file may or may not exist
bool hasProperty(const std::string &name) const
Does the property exist on the object.
void addProperty(Kernel::Property *prop, bool overwrite=false)
Add data to the object in the form of a property.
HeldType getPropertyValueAsType(const std::string &name) const
Get the value of a property as the given TYPE.
This class stores information regarding an experimental run as a series of log entries.
A property class for workspaces.
static double calc_Astar(const double theta, const double mur)
Save a PeaksWorkspace to a Gsas-style ASCII .hkl file.
void exec() override
Run the algorithm.
void sizeBanks(const std::string &bankName, int &nCols, int &nRows)
DataObjects::PeaksWorkspace_sptr m_ws
double absorbSphere(double radius, double twoth, double wl, double &tbar)
double spectrumCalc(double TOF, int iSpec, std::vector< std::vector< double > > time, std::vector< std::vector< double > > spectra, size_t id)
void setSigmaIntensity(double m_sigmaIntensity) override
Set the error on the integrated peak intensity.
double getL() const override
Get the L index of the peak.
double getIntensity() const override
Return the integrated peak intensity.
double getAbsorptionWeightedPathLength() const override
Gets the absorption weighted path length.
double getSigmaIntensity() const override
Return the error on the integrated peak intensity.
double getK() const override
Get the K index of the peak.
int getPeakNumber() const override
Returns the unique peak number Returns -1 if it could not find it.
int getRunNumber() const override
Return the run number this peak was measured at.
double getH() const override
Get the H index of the peak.
void setIntensity(double m_intensity) override
Set the integrated peak intensity.
Mantid::Kernel::Matrix< double > getGoniometerMatrix() const override
Get the goniometer rotation matrix at which this peak was measured.
double getMonitorCount() const override
Return the monitor count stored in this peak.
Structure describing a single-crystal peak.
int getCol() const override
For RectangularDetectors only, returns the column (x) of the pixel of the detector or -1 if not found...
double getDSpacing() const override
Calculate the d-spacing of the peak, in 1/Angstroms
std::string getBankName() const
Find the name of the bank that is the parent of the detector.
int getRow() const override
For RectangularDetectors only, returns the row (y) of the pixel of the detector or -1 if not found.
double getL1() const override
Return the L1 flight path length (source to sample), in meters.
double getWavelength() const override
Calculate the neutron wavelength (in angstroms) at the peak (Note for inelastic scattering - it is th...
double getTOF() const override
Calculate the time of flight (in microseconds) of the neutrons for this peak, using the geometry of t...
virtual Mantid::Kernel::V3D getDetPos() const
Return the detector position vector.
double getL2() const override
Return the L2 flight path length (sample to detector), in meters.
int getDetectorID() const
Get the ID of the detector at the center of the peak
double getScattering() const override
Calculate the scattering angle of the peak
IObject : Interface for geometry objects.
Class to implement UB matrix.
void setUB(const Kernel::DblMatrix &newUB)
Sets the UB matrix and recalculates lattice parameters.
const Kernel::DblMatrix & getU() const
Get the U matrix.
static std::shared_ptr< CSGObject > createSphere(const Kernel::V3D ¢re, double radius)
Create a Sphere.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
A material is defined as being composed of a given element, defined as a PhysicalConstants::NeutronAt...
double numberDensity() const
Get the number density.
double absorbXSection(const double lambda=PhysicalConstants::NeutronAtom::ReferenceLambda) const
Get the absorption cross section at a given wavelength in barns.
double totalScatterXSection() const
Return the total scattering cross section for a given wavelength in barns.
Matrix< T > & Transpose()
Transpose the matrix.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
double normalize()
Make a normalized vector (return norm value)
std::shared_ptr< PeaksWorkspace > PeaksWorkspace_sptr
Typedef for a shared pointer to a peaks workspace.
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
Holds support functions for strings.
MANTID_KERNEL_DLL void readToEndOfLine(std::istream &in, bool ConsumeEOL)
Eat everything from the stream until the next EOL.
int convert(const std::string &A, T &out)
Convert a string into a number.
MANTID_KERNEL_DLL std::string getWord(std::istream &in, bool consumeEOL)
Returns the next word in the stream.
long round(double x)
Custom rounding method for a double->long because none is portable in C++ (!)
std::shared_ptr< Unit > Unit_sptr
Shared pointer to the Unit base class.
A namespace containing physical constants that are required by algorithms and unit routines.
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
@ Input
An input workspace.
@ Output
An output workspace.
Structure to store neutronic scattering information for the various elements.
static const double ReferenceLambda
The reference wavelength value for absorption cross sections.