Mantid
Loading...
Searching...
No Matches
SaveHKL.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
9#include "MantidAPI/Run.h"
10#include "MantidAPI/Sample.h"
19#include "MantidKernel/Unit.h"
21#include "MantidKernel/Utils.h"
22#include <cmath>
23#include <filesystem>
24#include <fstream>
25
26using namespace Mantid::Geometry;
27using namespace Mantid::DataObjects;
28using namespace Mantid::Kernel;
29using namespace Mantid::Kernel::Strings;
30using namespace Mantid::API;
31using namespace Mantid::PhysicalConstants;
32
33namespace Mantid::Crystal {
34
35// Register the algorithm into the AlgorithmFactory
36DECLARE_ALGORITHM(SaveHKL)
37
38
40void SaveHKL::init() {
41 declareProperty(std::make_unique<WorkspaceProperty<PeaksWorkspace>>("InputWorkspace", "", Direction::Input),
42 "An input PeaksWorkspace.");
43
44 auto mustBePositive = std::make_shared<BoundedValidator<double>>();
45 mustBePositive->setLower(0.0);
46 declareProperty("ScalePeaks", 1.0, mustBePositive, "Multiply FSQ and sig(FSQ) by scaleFactor");
47 declareProperty("MinDSpacing", 0.0, "Minimum d-spacing (Angstroms)");
48 declareProperty("MinWavelength", 0.0, "Minimum wavelength (Angstroms)");
49 declareProperty("MaxWavelength", 100.0, "Maximum wavelength (Angstroms)");
50
51 declareProperty("AppendFile", false,
52 "Append to file if true. Use same corrections as file.\n"
53 "If false, new file (default).");
54 declareProperty("ApplyAnvredCorrections", false,
55 "Apply anvred corrections to peaks if true.\n"
56 "If false, no corrections during save (default).");
57 declareProperty("LinearScatteringCoef", EMPTY_DBL(), mustBePositive,
58 "Linear scattering coefficient in 1/cm if not set with "
59 "SetSampleMaterial");
60 declareProperty("LinearAbsorptionCoef", EMPTY_DBL(), mustBePositive,
61 "Linear absorption coefficient at 1.8 Angstroms in 1/cm if "
62 "not set with SetSampleMaterial");
63 declareProperty("Radius", EMPTY_DBL(), mustBePositive, "Radius of the sample in centimeters");
64 declareProperty("PowerLambda", 4.0, "Power of lambda ");
65 declareProperty(std::make_unique<FileProperty>("SpectraFile", "", API::FileProperty::OptionalLoad, ".dat"),
66 " Spectrum data read from a spectrum file.");
67
68 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Save, ".hkl"),
69 "Path to an hkl file to save.");
70
71 std::vector<std::string> histoTypes{"Bank", "RunNumber", ""};
72 declareProperty("SortBy", histoTypes[2], std::make_shared<StringListValidator>(histoTypes),
73 "Sort the histograms by bank, run number or both (default).");
74 declareProperty("MinIsigI", EMPTY_DBL(), mustBePositive, "The minimum I/sig(I) ratio");
75 declareProperty("WidthBorder", EMPTY_INT(), "Width of border of detectors");
76 declareProperty("MinIntensity", EMPTY_DBL(), mustBePositive, "The minimum Intensity");
77 declareProperty(
78 std::make_unique<WorkspaceProperty<PeaksWorkspace>>("OutputWorkspace", "SaveHKLOutput", Direction::Output),
79 "Output PeaksWorkspace");
80 declareProperty("HKLDecimalPlaces", EMPTY_INT(),
81 "Number of decimal places for fractional HKL. Default is integer HKL.");
82 declareProperty("DirectionCosines", false,
83 "Extra columns (22 total) in file if true for direction cosines.\n"
84 "If false, original 14 columns (default).");
85 const std::vector<std::string> exts{".mat", ".ub", ".txt"};
86 declareProperty(std::make_unique<FileProperty>("UBFilename", "", FileProperty::OptionalLoad, exts),
87 "Path to an ISAW-style UB matrix text file only needed for "
88 "DirectionCosines if workspace does not have lattice.");
89}
90
94
95 std::string filename = getPropertyValue("Filename");
96 m_ws = getProperty("InputWorkspace");
97
98 PeaksWorkspace_sptr peaksW = getProperty("OutputWorkspace");
99 if (peaksW != m_ws)
100 peaksW = m_ws->clone();
101 auto inst = peaksW->getInstrument();
102 std::vector<Peak> &peaks = peaksW->getPeaks();
103 double scaleFactor = getProperty("ScalePeaks");
104 double dMin = getProperty("MinDSpacing");
105 double wlMin = getProperty("MinWavelength");
106 double wlMax = getProperty("MaxWavelength");
107 std::string type = getProperty("SortBy");
108 double minIsigI = getProperty("MinIsigI");
109 double minIntensity = getProperty("MinIntensity");
110 int widthBorder = getProperty("WidthBorder");
111 int decimalHKL = getProperty("HKLDecimalPlaces");
112 bool cosines = getProperty("DirectionCosines");
114 if (cosines) {
115 if (peaksW->sample().hasOrientedLattice()) {
116 ol = peaksW->sample().getOrientedLattice();
117 } else {
118 // Find OrientedLattice
119 std::string fileUB = getProperty("UBFilename");
120 // Open the file
121 std::ifstream in(fileUB.c_str());
122 if (!in)
123 throw std::runtime_error("A file containing the UB matrix must be input into UBFilename.");
124
125 auto UB_alg = createChildAlgorithm("LoadIsawUB", -1, -1, false);
126 UB_alg->setProperty("PeaksWorkspace", peaksW);
127 UB_alg->setProperty("Filename", fileUB);
128 UB_alg->executeAsChildAlg();
129 }
130 }
131
132 // Sequence and run number
133 int bankSequence = 0;
134 int runSequence = 0;
135 // HKL is flipped by -1 due to different q convention in ISAW vs mantid.
136 // Default for kf-ki has -q
137 double qSign = -1.0;
138 std::string convention = ConfigService::Instance().getString("Q.convention");
139 if (convention == "Crystallography") {
140 qSign = 1.0;
141 }
142
143 std::fstream out;
144 out.open(filename.c_str(), std::ios::out);
145
146 // We cannot assume the peaks have bank type detector modules, so we have a
147 // string to check this
148 std::string bankPart = "?";
149 // We must sort the peaks first by run, then bank #, and save the list of
150 // workspace indices of it
151 using bankMap_t = std::map<int, std::vector<size_t>>;
152 using runMap_t = std::map<int, bankMap_t>;
153 std::set<int> uniqueBanks;
154 std::set<int> uniqueRuns;
155 runMap_t runMap;
156 for (size_t i = 0; i < peaks.size(); ++i) {
157 Peak const &p = peaks[i];
158 int run = p.getRunNumber();
159 int bank = 0;
160 std::string bankName = p.getBankName();
161 if (bankName.size() <= 4) {
162 g_log.information() << "Could not interpret bank number of peak " << i << "(" << bankName << ")\n";
163 continue;
164 }
165 // Save the "bank" part once to check whether it really is a bank
166 if (bankPart == "?")
167 bankPart = bankName.substr(0, 4);
168 // Take out the "bank" part of the bank name and convert to an int
169 if (bankPart == "bank")
170 bankName = bankName.substr(4, bankName.size() - 4);
171 else if (bankPart == "WISH")
172 bankName = bankName.substr(9, bankName.size() - 9);
173 Strings::convert(bankName, bank);
174
175 // Save in the map
176 if (type.compare(0, 2, "Ru") == 0)
177 runMap[run][bank].emplace_back(i);
178 else
179 runMap[bank][run].emplace_back(i);
180 // Track unique bank numbers
181 uniqueBanks.insert(bank);
182 uniqueRuns.insert(run);
183 }
184
185 bool correctPeaks = getProperty("ApplyAnvredCorrections");
186 std::vector<std::vector<double>> spectra;
187 std::vector<std::vector<double>> time;
188 int iSpec = 0;
189
190 m_smu = getProperty("LinearScatteringCoef"); // in 1/cm
191 m_amu = getProperty("LinearAbsorptionCoef"); // in 1/cm
192 m_power_th = getProperty("PowerLambda"); // in cm
193
194 API::Run &run = peaksW->mutableRun();
195
196 double radius = getProperty("Radius"); // in cm
197 if (radius != EMPTY_DBL()) {
198 run.addProperty<double>("Radius", radius, true);
199 } else {
200 if (run.hasProperty("Radius"))
201 radius = run.getPropertyValueAsType<double>("Radius");
202 }
203
204 const Material &sampleMaterial = peaksW->sample().getMaterial();
205 const IObject *sampleShape{nullptr};
206 // special case of sphere else assume the sample shape and material have been
207 // set already
208 if (radius != EMPTY_DBL()) {
209 // create sphere shape
210 auto sphere = ShapeFactory::createSphere(V3D(), radius * 0.01);
211 if (m_smu != EMPTY_DBL() && m_amu != EMPTY_DBL()) {
212 // Save input in Sample with wrong atomic number and name
213 NeutronAtom neutron(0, 0, 0.0, 0.0, m_smu, 0.0, m_smu, m_amu);
214 sphere->setMaterial(Material("SetInSaveHKL", neutron, 1.0));
215 } else {
216 sphere->setMaterial(sampleMaterial);
217 const double rho = sampleMaterial.numberDensity();
218 m_smu = sampleMaterial.totalScatterXSection() * rho;
220 }
221 peaksW->mutableSample().setShape(sphere);
222 } else if (peaksW->sample().getShape().hasValidShape()) {
223 sampleShape = &(peaksW->sample().getShape());
224 // if AddAbsorptionWeightedPathLengths has already been run on the workspace
225 // then keep those tbar values
226 if (std::all_of(peaks.cbegin(), peaks.cend(), [](auto &p) { return p.getAbsorptionWeightedPathLength() == 0; })) {
227 auto alg = createChildAlgorithm("AddAbsorptionWeightedPathLengths");
228 alg->setProperty("InputWorkspace", peaksW);
229 alg->setProperty("UseSinglePath", true);
230 alg->executeAsChildAlg();
231 }
232 }
233
234 if (correctPeaks) {
235 std::ifstream infile;
236 std::string spectraFile = getPropertyValue("SpectraFile");
237 infile.open(spectraFile.c_str());
238 if (infile.is_open()) {
239 std::string ignoreLine;
240 size_t a = 1;
241 for (int wi = 0; wi < 8; wi++)
242 getline(infile, ignoreLine);
243 while (!infile.eof()) {
244 time.resize(a + 1);
245 spectra.resize(a + 1);
246 std::string line;
247 getline(infile, line);
248 std::stringstream ss(line);
249 if (line.find("Bank") == std::string::npos) {
250 double time0, spectra0;
251 ss >> time0 >> spectra0;
252 time[a].emplace_back(time0);
253 spectra[a].emplace_back(spectra0);
254
255 } else {
256 std::string temp;
257 size_t a0 = 1;
258 ss >> temp >> a0 >> temp >> a;
259 }
260 }
261 infile.close();
262 }
263 }
264 // =================== Save all Peaks ======================================
265 std::set<size_t> banned;
266 // Go through each peak at this run / bank
267 int maxOrder = 0;
268 if (peaksW->sample().hasOrientedLattice()) {
269 maxOrder = peaksW->sample().getOrientedLattice().getMaxOrder();
270 }
271 // Go in order of run numbers
272 runMap_t::iterator runMap_it;
273 for (runMap_it = runMap.begin(); runMap_it != runMap.end(); ++runMap_it) {
274 // Start of a new run
275 // int run = runMap_it->first;
276 bankMap_t &bankMap = runMap_it->second;
277
278 bankMap_t::iterator bankMap_it;
279 for (bankMap_it = bankMap.begin(); bankMap_it != bankMap.end(); ++bankMap_it) {
280 // Start of a new bank.
281 // int bank = bankMap_it->first;
282 std::vector<size_t> &ids = bankMap_it->second;
283
284 // Go through each peak at this run / bank
285 for (auto wi : ids) {
286
287 Peak &p = peaks[wi];
288 if (p.getIntensity() == 0.0 || !(std::isfinite(p.getIntensity())) || !(std::isfinite(p.getSigmaIntensity()))) {
289 banned.insert(wi);
290 continue;
291 }
292 if (minIsigI != EMPTY_DBL() && p.getIntensity() < std::abs(minIsigI * p.getSigmaIntensity())) {
293 banned.insert(wi);
294 continue;
295 }
296 if (minIntensity != EMPTY_DBL() && p.getIntensity() < minIntensity) {
297 banned.insert(wi);
298 continue;
299 }
300 const int runNumber = p.getRunNumber();
301 int seqNum = p.getPeakNumber();
302 int bank = 0;
303 std::string bankName = p.getBankName();
304 int nCols, nRows;
305 sizeBanks(bankName, nCols, nRows);
306 // peaks with detectorID=-1 are from LoadHKL
307 if (widthBorder != EMPTY_INT() && p.getDetectorID() != -1 &&
308 (p.getCol() < widthBorder || p.getRow() < widthBorder || p.getCol() > (nCols - widthBorder) ||
309 p.getRow() > (nRows - widthBorder))) {
310 banned.insert(wi);
311 continue;
312 }
313 // Take out the "bank" part of the bank name and convert to an int
314 bankName.erase(remove_if(bankName.begin(), bankName.end(), std::not_fn(::isdigit)), bankName.end());
315 Strings::convert(bankName, bank);
316
317 // Two-theta = polar angle = scattering angle = between +Z vector and
318 // the
319 // scattered beam
320 double scattering = p.getScattering();
321 double lambda = p.getWavelength();
322 double dsp = p.getDSpacing();
323 if (dsp < dMin || lambda < wlMin || lambda > wlMax) {
324 banned.insert(wi);
325 continue;
326 }
327
328 double transmission{0}, tbar{0};
329 if (radius != EMPTY_DBL()) {
330 // keep original method if radius is provided
331 transmission = absorbSphere(radius, scattering, lambda, tbar);
332 } else if (sampleShape) {
334 transmission = exp(-tbar * 0.01 * sampleShape->material().attenuationCoefficient(lambda));
335 }
336
337 // Anvred write from Art Schultz/
338 if (p.getH() == 0 && p.getK() == 0 && p.getL() == 0) {
339 banned.insert(wi);
340 continue;
341 }
342 if (decimalHKL == EMPTY_INT()) {
343 V3D HKL = (maxOrder == 0) ? p.getHKL() : p.getIntHKL();
344 out << std::setw(4) << Utils::round(qSign * HKL[0]) << std::setw(4) << Utils::round(qSign * HKL[1])
345 << std::setw(4) << Utils::round(qSign * HKL[2]);
346 if (maxOrder > 0) {
347 V3D MNP = p.getIntMNP();
348 out << std::setw(4) << Utils::round(qSign * MNP[0]) << std::setw(4) << Utils::round(qSign * MNP[1])
349 << std::setw(4) << Utils::round(qSign * MNP[2]);
350 }
351 } else {
352 out << std::setw(5 + decimalHKL) << std::fixed << std::setprecision(decimalHKL) << qSign * p.getH()
353 << std::setw(5 + decimalHKL) << std::fixed << std::setprecision(decimalHKL) << qSign * p.getK()
354 << std::setw(5 + decimalHKL) << std::fixed << std::setprecision(decimalHKL) << qSign * p.getL();
355 }
356 double correc = scaleFactor;
357 double instBkg = 0;
358 double relSigSpect = 0.0;
359 bankSequence = static_cast<int>(std::distance(uniqueBanks.begin(), uniqueBanks.find(bank)));
360 runSequence = static_cast<int>(std::distance(uniqueRuns.begin(), uniqueRuns.find(runNumber)));
361 if (correctPeaks) {
362 // correct for the slant path throught the scintillator glass
363 double mu = (9.614 * lambda) + 0.266; // mu for GS20 glass
364 double depth = 0.2;
365 double eff_center = 1.0 - std::exp(-mu * depth); // efficiency at center of detector
366
367 // Distance to center of detector
368 std::shared_ptr<const IComponent> det0 = inst->getComponentByName(p.getBankName());
369 if (inst->getName() == "CORELLI") // for Corelli with sixteenpack under bank
370 {
371 std::vector<Geometry::IComponent_const_sptr> children;
372 std::shared_ptr<const Geometry::ICompAssembly> asmb =
373 std::dynamic_pointer_cast<const Geometry::ICompAssembly>(inst->getComponentByName(p.getBankName()));
374 asmb->getChildren(children, false);
375 det0 = children[0];
376 }
377 IComponent_const_sptr sample = inst->getSample();
378 double cosA = det0->getDistance(*sample) / p.getL2();
379 double pathlength = depth / cosA;
380 double eff_R = 1.0 - exp(-mu * pathlength); // efficiency at point R
381 double sp_ratio = eff_center / eff_R; // slant path efficiency ratio
382 double sinsqt = std::pow(lambda / (2.0 * dsp), 2);
383 double wl4 = std::pow(lambda, m_power_th);
384 double cmonx = 1.0;
385 if (p.getMonitorCount() > 0) {
386 cmonx = 100e6 / p.getMonitorCount();
387 }
388 double spect = spectrumCalc(p.getTOF(), iSpec, time, spectra, bank);
389 // Find spectra at wavelength of 1 for normalization
390 std::vector<double> xdata(1, 1.0); // wl = 1
391 std::vector<double> ydata;
392 double theta2 = p.getScattering();
393 double l1 = p.getL1();
394 double l2 = p.getL2();
395 Mantid::Kernel::Unit_sptr unit = UnitFactory::Instance().create("Wavelength");
396 unit->toTOF(xdata, ydata, l1, 0, {{UnitParams::l2, l2}, {UnitParams::twoTheta, theta2}});
397 double one = xdata[0];
398 double spect1 = spectrumCalc(one, iSpec, time, spectra, bank);
399 relSigSpect = std::sqrt((1.0 / spect) + (1.0 / spect1));
400 if (spect1 != 0.0) {
401 spect /= spect1;
402 } else {
403 throw std::runtime_error("Wavelength for normalizing to spectrum is out of range.");
404 }
405 correc = scaleFactor * sinsqt * cmonx * sp_ratio / (wl4 * spect * transmission);
406
407 if (inst->hasParameter("detScale" + bankName)) {
408 correc *= static_cast<double>(inst->getNumberParameter("detScale" + bankName)[0]);
409 }
410
411 // instrument background constant for sigma
412 instBkg = 0. * 12.28 / cmonx * scaleFactor;
413 }
414
415 // SHELX can read data without the space between the l and intensity
416 if (p.getDetectorID() != -1) {
417 double ckIntensity = correc * p.getIntensity();
418 double cksigI = std::sqrt(std::pow(correc * p.getSigmaIntensity(), 2) +
419 std::pow(relSigSpect * correc * p.getIntensity(), 2) + instBkg);
420 p.setIntensity(ckIntensity);
421 p.setSigmaIntensity(cksigI);
422 if (ckIntensity > 99999.985)
423 g_log.warning() << "Scaled intensity, " << ckIntensity
424 << " is too large for format. Decrease ScalePeaks.\n";
425 out << std::setw(8) << std::fixed << std::setprecision(2) << ckIntensity;
426
427 out << std::setw(8) << std::fixed << std::setprecision(2) << cksigI;
428 } else {
429 // This is data from LoadHKL which is already corrected
430 out << std::setw(8) << std::fixed << std::setprecision(2) << p.getIntensity();
431
432 out << std::setw(8) << std::fixed << std::setprecision(2) << p.getSigmaIntensity();
433 }
434 if (type.compare(0, 2, "Ba") == 0)
435 out << std::setw(4) << bankSequence + 1;
436 else
437 out << std::setw(4) << runSequence + 1;
438
439 out << std::setw(8) << std::fixed << std::setprecision(5) << lambda;
440 out << std::setw(8) << std::fixed << std::setprecision(5) << tbar;
441
442 if (cosines) {
443 // This is the reverse incident beam
444 V3D reverse_incident_dir = p.getSourceDirectionSampleFrame();
445 V3D reverse_incident_cos = ol.cosFromDir(reverse_incident_dir);
446
447 // This is the scattered beam direction
448 V3D scattered_dir = p.getDetectorDirectionSampleFrame();
449 V3D scattered_cos = ol.cosFromDir(scattered_dir);
450
451 for (int k = 0; k < 3; ++k) {
452 out << std::setw(9) << std::fixed << std::setprecision(5) << reverse_incident_cos[k];
453 out << std::setw(9) << std::fixed << std::setprecision(5) << scattered_cos[k];
454 }
455 }
456
457 out << std::setw(6) << runNumber;
458
459 if (cosines) {
460 out << std::setw(7) << seqNum;
461 } else {
462 out << std::setw(7) << wi + 1;
463 }
464
465 out << std::setw(7) << std::fixed << std::setprecision(4) << transmission;
466
467 out << std::setw(4) << std::right << bank;
468
469 out << std::setw(9) << std::fixed << std::setprecision(5) << scattering; // two-theta scattering
470
471 out << std::setw(8) << std::fixed << std::setprecision(4) << dsp;
472
473 if (cosines) {
474 out << std::setw(7) << std::fixed << std::setprecision(2) << static_cast<double>(p.getCol());
475 out << std::setw(7) << std::fixed << std::setprecision(2) << static_cast<double>(p.getRow());
476 }
477
478 out << '\n';
479 }
480 }
481 }
482 if (decimalHKL == EMPTY_INT()) {
483 out << std::setw(4) << 0 << std::setw(4) << 0 << std::setw(4) << 0;
484 if (maxOrder > 0) {
485 out << std::setw(4) << 0 << std::setw(4) << 0 << std::setw(4) << 0;
486 }
487 } else {
488 //
489 out << std::setw(5 + decimalHKL) << std::fixed << std::setprecision(decimalHKL) << 0.0 << std::setw(5 + decimalHKL)
490 << std::fixed << std::setprecision(decimalHKL) << 0.0 << std::setw(5 + decimalHKL) << std::fixed
491 << std::setprecision(decimalHKL) << 0.0;
492 }
493 if (cosines) {
494 out << " 0.00 0.00 0 0.00000 0.00000"
495 " 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000"
496 " 0 0 0.0000 0 0.00000 0.0000 0.00 0.00";
497 } else {
498 out << " 0.00 0.00 0 0.00000 0.00000"
499 " 0 0 0.0000 0 0.00000 0.0000";
500 }
501 out << '\n';
502 out.flush();
503 out.close();
504 // delete banned peaks
505 std::vector<int> badPeaks;
506 for (auto it = banned.crbegin(); it != banned.crend(); ++it) {
507 badPeaks.emplace_back(static_cast<int>(*it));
508 }
509 peaksW->removePeaks(std::move(badPeaks));
510
511 bool append = getProperty("AppendFile");
512 if (append && std::filesystem::exists(filename)) {
513 auto load_alg = createChildAlgorithm("LoadHKL");
514 load_alg->setPropertyValue("Filename", filename);
515 load_alg->setProperty("OutputWorkspace", "peaks");
516 load_alg->executeAsChildAlg();
517 // Get back the result
518 DataObjects::PeaksWorkspace_sptr ws2 = load_alg->getProperty("OutputWorkspace");
519 ws2->setInstrument(inst);
520
521 auto plus_alg = createChildAlgorithm("CombinePeaksWorkspaces");
522 plus_alg->setProperty("LHSWorkspace", peaksW);
523 plus_alg->setProperty("RHSWorkspace", ws2);
524 plus_alg->executeAsChildAlg();
525 // Get back the result
526 peaksW = plus_alg->getProperty("OutputWorkspace");
527 }
528
529 setProperty("OutputWorkspace", peaksW);
530} // namespace Crystal
531
548double SaveHKL::absorbSphere(double radius, double twoth, double wl, double &tbar) {
549
550 const double mu = m_smu + (m_amu / 1.8f) * wl; // linear absorption coef
551 const double mur = mu * radius;
552
553 if (mur < 0. || mur > 2.5) {
554 std::ostringstream s;
555 s << mur;
556 throw std::runtime_error("muR is not in range of Dwiggins' table :" + s.str());
557 }
558
559 const double theta = twoth * radtodeg * 0.5;
560 if (theta < 0. || theta > 90.) {
561 std::ostringstream s;
562 s << theta;
563 throw std::runtime_error("theta is not valid it must be in range [0, 90]");
564 }
565
566 const double transmission = 1.f / AnvredCorrection::calc_Astar(theta, mur);
567
568 // calculate tbar as defined by coppens.
569 // transmission = exp(-mu*tbar)
570 if (std::fabs(mu) < 1e-300)
571 tbar = 0.0;
572 else
573 tbar = -std::log(transmission) / mu;
574
575 return transmission;
576}
577
578double SaveHKL::spectrumCalc(double TOF, int iSpec, const std::vector<std::vector<double>> &time,
579 const std::vector<std::vector<double>> &spectra, size_t id) {
580 double spect = 0;
581 if (iSpec == 1) {
582 //"Calculate the spectrum using spectral coefficients for the GSAS Type 2
583 // incident spectrum."
584 double T = TOF / 1000.; // time-of-flight in milliseconds
585
586 double c1 = spectra[id][0];
587 double c2 = spectra[id][1];
588 double c3 = spectra[id][2];
589 double c4 = spectra[id][3];
590 double c5 = spectra[id][4];
591 double c6 = spectra[id][5];
592 double c7 = spectra[id][6];
593 double c8 = spectra[id][7];
594 double c9 = spectra[id][8];
595 double c10 = spectra[id][9];
596 double c11 = spectra[id][10];
597
598 spect = c1 + c2 * exp(-c3 / std::pow(T, 2)) / std::pow(T, 5) + c4 * exp(-c5 * std::pow(T, 2)) +
599 c6 * exp(-c7 * std::pow(T, 3)) + c8 * exp(-c9 * std::pow(T, 4)) + c10 * exp(-c11 * std::pow(T, 5));
600 } else {
601 size_t i = 1;
602 for (i = 1; i < spectra[id].size(); ++i)
603 if (TOF < time[id][i])
604 break;
605 spect = spectra[id][i - 1] +
606 (TOF - time[id][i - 1]) / (time[id][i] - time[id][i - 1]) * (spectra[id][i] - spectra[id][i - 1]);
607 }
608
609 return spect;
610}
611void SaveHKL::sizeBanks(const std::string &bankName, int &nCols, int &nRows) {
612 if (bankName == "None")
613 return;
614 std::shared_ptr<const IComponent> parent = m_ws->getInstrument()->getComponentByName(bankName);
615 if (!parent)
616 return;
617 if (parent->type() == "RectangularDetector") {
618 std::shared_ptr<const RectangularDetector> RDet = std::dynamic_pointer_cast<const RectangularDetector>(parent);
619
620 nCols = RDet->xpixels();
621 nRows = RDet->ypixels();
622 } else {
623 if (m_ws->getInstrument()->getName() == "CORELLI") // for Corelli with sixteenpack under bank
624 {
625 std::vector<Geometry::IComponent_const_sptr> children;
626 std::shared_ptr<const Geometry::ICompAssembly> asmb =
627 std::dynamic_pointer_cast<const Geometry::ICompAssembly>(parent);
628 asmb->getChildren(children, false);
629 parent = children[0];
630 }
631 std::vector<Geometry::IComponent_const_sptr> children;
632 std::shared_ptr<const Geometry::ICompAssembly> asmb =
633 std::dynamic_pointer_cast<const Geometry::ICompAssembly>(parent);
634 asmb->getChildren(children, false);
635 std::shared_ptr<const Geometry::ICompAssembly> asmb2 =
636 std::dynamic_pointer_cast<const Geometry::ICompAssembly>(children[0]);
637 std::vector<Geometry::IComponent_const_sptr> grandchildren;
638 asmb2->getChildren(grandchildren, false);
639 nRows = static_cast<int>(grandchildren.size());
640 nCols = static_cast<int>(children.size());
641 }
642}
643
644} // namespace Mantid::Crystal
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
const std::vector< double > * lambda
const int maxOrder
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.
Kernel::Logger & g_log
Definition Algorithm.h:422
@ 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.
Definition LogManager.h:91
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.
Definition Run.h:35
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.
Definition SaveHKL.h:22
void exec() override
Run the algorithm.
Definition SaveHKL.cpp:93
void sizeBanks(const std::string &bankName, int &nCols, int &nRows)
Definition SaveHKL.cpp:611
DataObjects::PeaksWorkspace_sptr m_ws
Definition SaveHKL.h:46
double spectrumCalc(double TOF, int iSpec, const std::vector< std::vector< double > > &time, const std::vector< std::vector< double > > &spectra, size_t id)
Definition SaveHKL.cpp:578
double absorbSphere(double radius, double twoth, double wl, double &tbar)
Definition SaveHKL.cpp:548
Mantid::Kernel::V3D getIntMNP() const override
Return the int MNP vector.
Definition BasePeak.cpp:115
void setSigmaIntensity(double m_sigmaIntensity) override
Set the error on the integrated peak intensity.
Definition BasePeak.cpp:205
double getL() const override
Get the L index of the peak.
Definition BasePeak.cpp:99
double getIntensity() const override
Return the integrated peak intensity.
Definition BasePeak.cpp:184
double getAbsorptionWeightedPathLength() const override
Gets the absorption weighted path length.
Definition BasePeak.cpp:347
double getSigmaIntensity() const override
Return the error on the integrated peak intensity.
Definition BasePeak.cpp:187
double getK() const override
Get the K index of the peak.
Definition BasePeak.cpp:96
int getPeakNumber() const override
Returns the unique peak number Returns -1 if it could not find it.
Definition BasePeak.cpp:233
int getRunNumber() const override
Return the run number this peak was measured at.
Definition BasePeak.cpp:77
double getH() const override
Get the H index of the peak.
Definition BasePeak.cpp:93
void setIntensity(double m_intensity) override
Set the integrated peak intensity.
Definition BasePeak.cpp:197
Mantid::Kernel::V3D getHKL() const override
Return the HKL vector.
Definition BasePeak.cpp:102
double getMonitorCount() const override
Return the monitor count stored in this peak.
Definition BasePeak.cpp:85
Mantid::Kernel::V3D getIntHKL() const override
Return the int HKL vector.
Definition BasePeak.cpp:112
Structure describing a single-crystal peak.
Definition Peak.h:34
int getCol() const override
For RectangularDetectors only, returns the column (x) of the pixel of the detector or -1 if not found...
Definition Peak.cpp:335
Mantid::Kernel::V3D getSourceDirectionSampleFrame() const override
Calculate the reverse incident beam direction in the sample frame
Definition Peak.cpp:418
double getDSpacing() const override
Calculate the d-spacing of the peak, in 1/Angstroms
Definition Peak.cpp:426
int getRow() const override
For RectangularDetectors only, returns the row (y) of the pixel of the detector or -1 if not found.
Definition Peak.cpp:326
double getL1() const override
Return the L1 flight path length (source to sample), in meters.
Definition Peak.cpp:724
int getDetectorID() const override
Get the ID of the detector at the center of the peak
Definition Peak.cpp:265
Mantid::Kernel::V3D getDetectorDirectionSampleFrame() const override
Calculate the scattered beam direction in the sample frame
Definition Peak.cpp:410
double getWavelength() const override
Calculate the neutron wavelength (in angstroms) at the peak (Note for inelastic scattering - it is th...
Definition Peak.cpp:358
double getTOF() const override
Calculate the time of flight (in microseconds) of the neutrons for this peak, using the geometry of t...
Definition Peak.cpp:373
double getL2() const override
Return the L2 flight path length (sample to detector), in meters.
Definition Peak.cpp:728
const std::string & getBankName() const
Find the name of the bank that is the parent of the detector.
Definition Peak.cpp:347
double getScattering() const override
Calculate the scattering angle of the peak
Definition Peak.cpp:391
HKL : HKL MDFrame.
Definition HKL.h:20
IObject : Interface for geometry objects.
Definition IObject.h:42
Class to implement UB matrix.
Kernel::V3D cosFromDir(const Kernel::V3D &dir) const
Calculate the direction cosine corresponding to a given direction.
static std::shared_ptr< CSGObject > createSphere(const Kernel::V3D &centre, 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.
Definition Logger.cpp:117
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
A material is defined as being composed of a given element, defined as a PhysicalConstants::NeutronAt...
Definition Material.h:50
double numberDensity() const
Get the number density.
Definition Material.cpp:189
double absorbXSection(const double lambda=PhysicalConstants::NeutronAtom::ReferenceLambda) const
Get the absorption cross section at a given wavelength in barns.
Definition Material.cpp:260
double totalScatterXSection() const
Return the total scattering cross section for a given wavelength in barns.
Definition Material.cpp:252
Class for 3D vectors.
Definition V3D.h:34
const double radtodeg
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.
Definition IComponent.h:167
Holds support functions for strings.
int convert(const std::string &A, T &out)
Convert a string into a number.
Definition Strings.cpp:696
long round(double x)
Custom rounding method for a double->long because none is portable in C++ (!)
Definition Utils.h:37
std::shared_ptr< Unit > Unit_sptr
Shared pointer to the Unit base class.
Definition Unit.h:194
A namespace containing physical constants that are required by algorithms and unit routines.
Definition Atom.h:14
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
Definition EmptyValues.h:24
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition EmptyValues.h:42
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54
Structure to store neutronic scattering information for the various elements.
Definition NeutronAtom.h:22
static const double ReferenceLambda
The reference wavelength value for absorption cross sections.
Definition NeutronAtom.h:25