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 <fstream>
23
24#include <Poco/File.h>
25#include <cmath>
26
27using namespace Mantid::Geometry;
28using namespace Mantid::DataObjects;
29using namespace Mantid::Kernel;
30using namespace Mantid::Kernel::Strings;
31using namespace Mantid::API;
32using namespace Mantid::PhysicalConstants;
33
34namespace Mantid::Crystal {
35
36// Register the algorithm into the AlgorithmFactory
37DECLARE_ALGORITHM(SaveHKL)
38
39
41void SaveHKL::init() {
42 declareProperty(std::make_unique<WorkspaceProperty<PeaksWorkspace>>("InputWorkspace", "", Direction::Input),
43 "An input PeaksWorkspace.");
44
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)");
51
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 "
60 "SetSampleMaterial");
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 ");
66 declareProperty(std::make_unique<FileProperty>("SpectraFile", "", API::FileProperty::OptionalLoad, ".dat"),
67 " Spectrum data read from a spectrum file.");
68
69 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Save, ".hkl"),
70 "Path to an hkl file to save.");
71
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");
78 declareProperty(
79 std::make_unique<WorkspaceProperty<PeaksWorkspace>>("OutputWorkspace", "SaveHKLOutput", Direction::Output),
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"};
87 declareProperty(std::make_unique<FileProperty>("UBFilename", "", FileProperty::OptionalLoad, exts),
88 "Path to an ISAW-style UB matrix text file only needed for "
89 "DirectionCosines if workspace does not have lattice.");
90}
91
95
96 std::string filename = getPropertyValue("Filename");
97 m_ws = getProperty("InputWorkspace");
98
99 PeaksWorkspace_sptr peaksW = getProperty("OutputWorkspace");
100 if (peaksW != m_ws)
101 peaksW = m_ws->clone();
102 auto inst = peaksW->getInstrument();
103 std::vector<Peak> &peaks = peaksW->getPeaks();
104 double scaleFactor = getProperty("ScalePeaks");
105 double dMin = getProperty("MinDSpacing");
106 double wlMin = getProperty("MinWavelength");
107 double wlMax = getProperty("MaxWavelength");
108 std::string type = getProperty("SortBy");
109 double minIsigI = getProperty("MinIsigI");
110 double minIntensity = getProperty("MinIntensity");
111 int widthBorder = getProperty("WidthBorder");
112 int decimalHKL = getProperty("HKLDecimalPlaces");
113 bool cosines = getProperty("DirectionCosines");
115 if (cosines) {
116 if (peaksW->sample().hasOrientedLattice()) {
117 ol = peaksW->sample().getOrientedLattice();
118 } else {
119 // Find OrientedLattice
120 std::string fileUB = getProperty("UBFilename");
121 // Open the file
122 std::ifstream in(fileUB.c_str());
123 if (!in)
124 throw std::runtime_error("A file containing the UB matrix must be input into UBFilename.");
125 std::string s;
126 double val;
127
128 // Read the ISAW UB matrix
130 for (size_t row = 0; row < 3; row++) {
131 for (size_t col = 0; col < 3; col++) {
132 s = getWord(in, true);
133 if (!convert(s, val))
134 throw std::runtime_error("The string '" + s + "' in the file was not understood as a number.");
135 UB[row][col] = val;
136 }
137 readToEndOfLine(in, true);
138 }
139 ol.setUB(UB);
140 }
141 }
142
143 // Sequence and run number
144 int bankSequence = 0;
145 int runSequence = 0;
146 // HKL is flipped by -1 due to different q convention in ISAW vs mantid.
147 // Default for kf-ki has -q
148 double qSign = -1.0;
149 std::string convention = ConfigService::Instance().getString("Q.convention");
150 if (convention == "Crystallography")
151 qSign = 1.0;
152
153 std::fstream out;
154 out.open(filename.c_str(), std::ios::out);
155
156 // We cannot assume the peaks have bank type detector modules, so we have a
157 // string to check this
158 std::string bankPart = "?";
159 // We must sort the peaks first by run, then bank #, and save the list of
160 // workspace indices of it
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;
165 runMap_t runMap;
166 for (size_t i = 0; i < peaks.size(); ++i) {
167 Peak &p = peaks[i];
168 int run = p.getRunNumber();
169 int bank = 0;
170 std::string bankName = p.getBankName();
171 if (bankName.size() <= 4) {
172 g_log.information() << "Could not interpret bank number of peak " << i << "(" << bankName << ")\n";
173 continue;
174 }
175 // Save the "bank" part once to check whether it really is a bank
176 if (bankPart == "?")
177 bankPart = bankName.substr(0, 4);
178 // Take out the "bank" part of the bank name and convert to an int
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);
183 Strings::convert(bankName, bank);
184
185 // Save in the map
186 if (type.compare(0, 2, "Ru") == 0)
187 runMap[run][bank].emplace_back(i);
188 else
189 runMap[bank][run].emplace_back(i);
190 // Track unique bank numbers
191 uniqueBanks.insert(bank);
192 uniqueRuns.insert(run);
193 }
194
195 bool correctPeaks = getProperty("ApplyAnvredCorrections");
196 std::vector<std::vector<double>> spectra;
197 std::vector<std::vector<double>> time;
198 int iSpec = 0;
199
200 m_smu = getProperty("LinearScatteringCoef"); // in 1/cm
201 m_amu = getProperty("LinearAbsorptionCoef"); // in 1/cm
202 m_power_th = getProperty("PowerLambda"); // in cm
203
204 API::Run &run = peaksW->mutableRun();
205
206 double radius = getProperty("Radius"); // in cm
207 if (radius != EMPTY_DBL()) {
208 run.addProperty<double>("Radius", radius, true);
209 } else {
210 if (run.hasProperty("Radius"))
211 radius = run.getPropertyValueAsType<double>("Radius");
212 }
213
214 const Material &sampleMaterial = peaksW->sample().getMaterial();
215 const IObject *sampleShape{nullptr};
216 // special case of sphere else assume the sample shape and material have been
217 // set already
218 if (radius != EMPTY_DBL()) {
219 // create sphere shape
220 auto sphere = ShapeFactory::createSphere(V3D(), radius * 0.01);
221 if (m_smu != EMPTY_DBL() && m_amu != EMPTY_DBL()) {
222 // Save input in Sample with wrong atomic number and name
223 NeutronAtom neutron(0, 0, 0.0, 0.0, m_smu, 0.0, m_smu, m_amu);
224 sphere->setMaterial(Material("SetInSaveHKL", neutron, 1.0));
225 } else {
226 sphere->setMaterial(sampleMaterial);
227 const double rho = sampleMaterial.numberDensity();
228 m_smu = sampleMaterial.totalScatterXSection() * rho;
230 }
231 peaksW->mutableSample().setShape(sphere);
232 } else if (peaksW->sample().getShape().hasValidShape()) {
233 sampleShape = &(peaksW->sample().getShape());
234 // if AddAbsorptionWeightedPathLengths has already been run on the workspace
235 // then keep those tbar values
236 if (std::all_of(peaks.cbegin(), peaks.cend(), [](auto &p) { return p.getAbsorptionWeightedPathLength() == 0; })) {
237 auto alg = createChildAlgorithm("AddAbsorptionWeightedPathLengths");
238 alg->setProperty("InputWorkspace", peaksW);
239 alg->setProperty("UseSinglePath", true);
240 alg->executeAsChildAlg();
241 }
242 }
243
244 if (correctPeaks) {
245 std::vector<double> spec(11);
246 std::string STRING;
247 std::ifstream infile;
248 std::string spectraFile = getPropertyValue("SpectraFile");
249 infile.open(spectraFile.c_str());
250 if (infile.is_open()) {
251 size_t a = 1;
252 for (int wi = 0; wi < 8; wi++)
253 getline(infile, STRING); // Saves the line in STRING.
254 while (!infile.eof()) // To get you all the lines.
255 {
256 time.resize(a + 1);
257 spectra.resize(a + 1);
258 getline(infile, STRING); // Saves the line in STRING.
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);
265
266 } else {
267 std::string temp;
268 size_t a0 = 1;
269 ss >> temp >> a0 >> temp >> a;
270 }
271 }
272 infile.close();
273 }
274 }
275 // =================== Save all Peaks ======================================
276 std::set<size_t> banned;
277 // Go through each peak at this run / bank
278
279 // Go in order of run numbers
280 runMap_t::iterator runMap_it;
281 for (runMap_it = runMap.begin(); runMap_it != runMap.end(); ++runMap_it) {
282 // Start of a new run
283 // int run = runMap_it->first;
284 bankMap_t &bankMap = runMap_it->second;
285
286 bankMap_t::iterator bankMap_it;
287 for (bankMap_it = bankMap.begin(); bankMap_it != bankMap.end(); ++bankMap_it) {
288 // Start of a new bank.
289 // int bank = bankMap_it->first;
290 std::vector<size_t> &ids = bankMap_it->second;
291
292 // Go through each peak at this run / bank
293 for (auto wi : ids) {
294
295 Peak &p = peaks[wi];
296 if (p.getIntensity() == 0.0 || !(std::isfinite(p.getIntensity())) || !(std::isfinite(p.getSigmaIntensity()))) {
297 banned.insert(wi);
298 continue;
299 }
300 if (minIsigI != EMPTY_DBL() && p.getIntensity() < std::abs(minIsigI * p.getSigmaIntensity())) {
301 banned.insert(wi);
302 continue;
303 }
304 if (minIntensity != EMPTY_DBL() && p.getIntensity() < minIntensity) {
305 banned.insert(wi);
306 continue;
307 }
308 const int runNumber = p.getRunNumber();
309 int seqNum = p.getPeakNumber();
310 int bank = 0;
311 std::string bankName = p.getBankName();
312 int nCols, nRows;
313 sizeBanks(bankName, nCols, nRows);
314 // peaks with detectorID=-1 are from LoadHKL
315 if (widthBorder != EMPTY_INT() && p.getDetectorID() != -1 &&
316 (p.getCol() < widthBorder || p.getRow() < widthBorder || p.getCol() > (nCols - widthBorder) ||
317 p.getRow() > (nRows - widthBorder))) {
318 banned.insert(wi);
319 continue;
320 }
321 // Take out the "bank" part of the bank name and convert to an int
322 bankName.erase(remove_if(bankName.begin(), bankName.end(), std::not_fn(::isdigit)), bankName.end());
323 Strings::convert(bankName, bank);
324
325 // Two-theta = polar angle = scattering angle = between +Z vector and
326 // the
327 // scattered beam
328 double scattering = p.getScattering();
329 double lambda = p.getWavelength();
330 double dsp = p.getDSpacing();
331 if (dsp < dMin || lambda < wlMin || lambda > wlMax) {
332 banned.insert(wi);
333 continue;
334 }
335
336 double transmission{0}, tbar{0};
337 if (radius != EMPTY_DBL()) {
338 // keep original method if radius is provided
339 transmission = absorbSphere(radius, scattering, lambda, tbar);
340 } else if (sampleShape) {
342 transmission = exp(-tbar * 0.01 * sampleShape->material().attenuationCoefficient(lambda));
343 }
344
345 // Anvred write from Art Schultz/
346 // hklFile.write('%4d%4d%4d%8.2f%8.2f%4d%8.4f%7.4f%7d%7d%7.4f%4d%9.5f%9.4f\n'
347 // % (H, K, L, FSQ, SIGFSQ, hstnum, WL, TBAR, CURHST, SEQNUM,
348 // TRANSMISSION, DN, TWOTH, DSP))
349 if (p.getH() == 0 && p.getK() == 0 && p.getL() == 0) {
350 banned.insert(wi);
351 continue;
352 }
353 if (decimalHKL == EMPTY_INT())
354 out << std::setw(4) << Utils::round(qSign * p.getH()) << std::setw(4) << Utils::round(qSign * p.getK())
355 << std::setw(4) << Utils::round(qSign * p.getL());
356 else
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;
361 double instBkg = 0;
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)));
365 if (correctPeaks) {
366 // correct for the slant path throught the scintillator glass
367 double mu = (9.614 * lambda) + 0.266; // mu for GS20 glass
368 double depth = 0.2;
369 double eff_center = 1.0 - std::exp(-mu * depth); // efficiency at center of detector
370
371 // Distance to center of detector
372 std::shared_ptr<const IComponent> det0 = inst->getComponentByName(p.getBankName());
373 if (inst->getName() == "CORELLI") // for Corelli with sixteenpack under bank
374 {
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);
379 det0 = children[0];
380 }
381 IComponent_const_sptr sample = inst->getSample();
382 double cosA = det0->getDistance(*sample) / p.getL2();
383 double pathlength = depth / cosA;
384 double eff_R = 1.0 - exp(-mu * pathlength); // efficiency at point R
385 double sp_ratio = eff_center / eff_R; // slant path efficiency ratio
386 double sinsqt = std::pow(lambda / (2.0 * dsp), 2);
387 double wl4 = std::pow(lambda, m_power_th);
388 double cmonx = 1.0;
389 if (p.getMonitorCount() > 0)
390 cmonx = 100e6 / p.getMonitorCount();
391 double spect = spectrumCalc(p.getTOF(), iSpec, time, spectra, bank);
392 // Find spectra at wavelength of 1 for normalization
393 std::vector<double> xdata(1, 1.0); // wl = 1
394 std::vector<double> ydata;
395 double theta2 = p.getScattering();
396 double l1 = p.getL1();
397 double l2 = p.getL2();
398 Mantid::Kernel::Unit_sptr unit = UnitFactory::Instance().create("Wavelength");
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));
403 if (spect1 != 0.0) {
404 spect /= spect1;
405 } else {
406 throw std::runtime_error("Wavelength for normalizing to spectrum is out of range.");
407 }
408 correc = scaleFactor * sinsqt * cmonx * sp_ratio / (wl4 * spect * transmission);
409
410 if (inst->hasParameter("detScale" + bankName))
411 correc *= static_cast<double>(inst->getNumberParameter("detScale" + bankName)[0]);
412
413 // instrument background constant for sigma
414 instBkg = 0. * 12.28 / cmonx * scaleFactor;
415 }
416
417 // SHELX can read data without the space between the l and intensity
418 if (p.getDetectorID() != -1) {
419 double ckIntensity = correc * p.getIntensity();
420 double cksigI = std::sqrt(std::pow(correc * p.getSigmaIntensity(), 2) +
421 std::pow(relSigSpect * correc * p.getIntensity(), 2) + instBkg);
422 p.setIntensity(ckIntensity);
423 p.setSigmaIntensity(cksigI);
424 if (ckIntensity > 99999.985)
425 g_log.warning() << "Scaled intensity, " << ckIntensity
426 << " is too large for format. Decrease ScalePeaks.\n";
427 out << std::setw(8) << std::fixed << std::setprecision(2) << ckIntensity;
428
429 out << std::setw(8) << std::fixed << std::setprecision(2) << cksigI;
430 } else {
431 // This is data from LoadHKL which is already corrected
432 out << std::setw(8) << std::fixed << std::setprecision(2) << p.getIntensity();
433
434 out << std::setw(8) << std::fixed << std::setprecision(2) << p.getSigmaIntensity();
435 }
436 if (type.compare(0, 2, "Ba") == 0)
437 out << std::setw(4) << bankSequence + 1;
438 else
439 out << std::setw(4) << runSequence + 1;
440
441 if (cosines) {
442 out << std::setw(8) << std::fixed << std::setprecision(5) << lambda;
443 out << std::setw(8) << std::fixed << std::setprecision(5) << tbar;
445
446 auto U = ol.getU();
447 auto RU = oriented * U;
448 RU.Transpose();
449
450 // This is the reverse incident beam
451 V3D reverse_incident = inst->getSource()->getPos() - inst->getSample()->getPos();
452 reverse_incident.normalize();
453 // This is the scattered beam direction
454 V3D dir = p.getDetPos() - inst->getSample()->getPos();
455 dir.normalize();
456
457 V3D dir_cos_1 = RU * reverse_incident;
458 V3D dir_cos_2 = RU * dir;
459
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];
463 }
464
465 out << std::setw(6) << runNumber;
466
467 out << std::setw(6) << seqNum;
468
469 out << std::setw(7) << std::fixed << std::setprecision(4) << transmission;
470
471 out << std::setw(4) << std::right << bank;
472
473 out << std::setw(9) << std::fixed << std::setprecision(5) << scattering; // two-theta scattering
474
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());
478 } else {
479 out << std::setw(8) << std::fixed << std::setprecision(4) << lambda;
480
481 out << std::setw(7) << std::fixed << std::setprecision(4) << tbar;
482
483 out << std::setw(7) << runNumber;
484
485 out << std::setw(7) << wi + 1;
486
487 out << std::setw(7) << std::fixed << std::setprecision(4) << transmission;
488
489 out << std::setw(4) << std::right << bank;
490
491 out << std::setw(9) << std::fixed << std::setprecision(5) << scattering; // two-theta scattering
492
493 out << std::setw(9) << std::fixed << std::setprecision(4) << dsp;
494 }
495
496 out << '\n';
497 }
498 }
499 }
500 if (decimalHKL == EMPTY_INT())
501 out << std::setw(4) << 0 << std::setw(4) << 0 << std::setw(4) << 0;
502 else
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;
506 if (cosines) {
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 "
509 "0.0000 0.00 0.00";
510 } else {
511 out << " 0.00 0.00 0 0.0000 0.0000 0 0 0.0000 "
512 " 0 0.00000 0.0000";
513 }
514 out << '\n';
515 out.flush();
516 out.close();
517 // delete banned peaks
518 std::vector<int> badPeaks;
519 for (auto it = banned.crbegin(); it != banned.crend(); ++it) {
520 badPeaks.emplace_back(static_cast<int>(*it));
521 }
522 peaksW->removePeaks(std::move(badPeaks));
523
524 bool append = getProperty("AppendFile");
525 if (append && Poco::File(filename.c_str()).exists()) {
526 auto load_alg = createChildAlgorithm("LoadHKL");
527 load_alg->setPropertyValue("Filename", filename);
528 load_alg->setProperty("OutputWorkspace", "peaks");
529 load_alg->executeAsChildAlg();
530 // Get back the result
531 DataObjects::PeaksWorkspace_sptr ws2 = load_alg->getProperty("OutputWorkspace");
532 ws2->setInstrument(inst);
533
534 auto plus_alg = createChildAlgorithm("CombinePeaksWorkspaces");
535 plus_alg->setProperty("LHSWorkspace", peaksW);
536 plus_alg->setProperty("RHSWorkspace", ws2);
537 plus_alg->executeAsChildAlg();
538 // Get back the result
539 peaksW = plus_alg->getProperty("OutputWorkspace");
540 }
541
542 setProperty("OutputWorkspace", peaksW);
543} // namespace Crystal
544
561double SaveHKL::absorbSphere(double radius, double twoth, double wl, double &tbar) {
562
563 const double mu = m_smu + (m_amu / 1.8f) * wl; // linear absorption coef
564 const double mur = mu * radius;
565
566 if (mur < 0. || mur > 2.5) {
567 std::ostringstream s;
568 s << mur;
569 throw std::runtime_error("muR is not in range of Dwiggins' table :" + s.str());
570 }
571
572 const double theta = twoth * radtodeg * 0.5;
573 if (theta < 0. || theta > 90.) {
574 std::ostringstream s;
575 s << theta;
576 throw std::runtime_error("theta is not valid it must be in range [0, 90]");
577 }
578
579 const double transmission = 1.f / AnvredCorrection::calc_Astar(theta, mur);
580
581 // calculate tbar as defined by coppens.
582 // transmission = exp(-mu*tbar)
583 if (std::fabs(mu) < 1e-300)
584 tbar = 0.0;
585 else
586 tbar = -std::log(transmission) / mu;
587
588 return transmission;
589}
590
591double SaveHKL::spectrumCalc(double TOF, int iSpec, std::vector<std::vector<double>> time,
592 std::vector<std::vector<double>> spectra, size_t id) {
593 double spect = 0;
594 if (iSpec == 1) {
595 //"Calculate the spectrum using spectral coefficients for the GSAS Type 2
596 // incident spectrum."
597 double T = TOF / 1000.; // time-of-flight in milliseconds
598
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];
610
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));
613 } else {
614 size_t i = 1;
615 for (i = 1; i < spectra[id].size(); ++i)
616 if (TOF < time[id][i])
617 break;
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]);
620 }
621
622 return spect;
623}
624void SaveHKL::sizeBanks(const std::string &bankName, int &nCols, int &nRows) {
625 if (bankName == "None")
626 return;
627 std::shared_ptr<const IComponent> parent = m_ws->getInstrument()->getComponentByName(bankName);
628 if (!parent)
629 return;
630 if (parent->type() == "RectangularDetector") {
631 std::shared_ptr<const RectangularDetector> RDet = std::dynamic_pointer_cast<const RectangularDetector>(parent);
632
633 nCols = RDet->xpixels();
634 nRows = RDet->ypixels();
635 } else {
636 if (m_ws->getInstrument()->getName() == "CORELLI") // for Corelli with sixteenpack under bank
637 {
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];
643 }
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());
654 }
655}
656
657} // namespace Mantid::Crystal
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
const std::vector< double > * lambda
double radius
Definition: Rasterize.cpp:31
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
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.
Definition: Algorithm.cpp:842
Kernel::Logger & g_log
Definition: Algorithm.h:451
@ OptionalLoad
to specify a file to read but the file doesn't have to exist
Definition: FileProperty.h:53
@ Save
to specify a file to write to, the file may or may not exist
Definition: FileProperty.h:49
bool hasProperty(const std::string &name) const
Does the property exist on the object.
Definition: LogManager.cpp:265
void addProperty(Kernel::Property *prop, bool overwrite=false)
Add data to the object in the form of a property.
Definition: LogManager.h:79
HeldType getPropertyValueAsType(const std::string &name) const
Get the value of a property as the given TYPE.
Definition: LogManager.cpp:332
This class stores information regarding an experimental run as a series of log entries.
Definition: Run.h:38
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:23
void exec() override
Run the algorithm.
Definition: SaveHKL.cpp:94
void sizeBanks(const std::string &bankName, int &nCols, int &nRows)
Definition: SaveHKL.cpp:624
DataObjects::PeaksWorkspace_sptr m_ws
Definition: SaveHKL.h:47
double absorbSphere(double radius, double twoth, double wl, double &tbar)
Definition: SaveHKL.cpp:561
double spectrumCalc(double TOF, int iSpec, std::vector< std::vector< double > > time, std::vector< std::vector< double > > spectra, size_t id)
Definition: SaveHKL.cpp:591
void setSigmaIntensity(double m_sigmaIntensity) override
Set the error on the integrated peak intensity.
Definition: BasePeak.cpp:206
double getL() const override
Get the L index of the peak.
Definition: BasePeak.cpp:100
double getIntensity() const override
Return the integrated peak intensity.
Definition: BasePeak.cpp:185
double getAbsorptionWeightedPathLength() const override
Gets the absorption weighted path length.
Definition: BasePeak.cpp:340
double getSigmaIntensity() const override
Return the error on the integrated peak intensity.
Definition: BasePeak.cpp:188
double getK() const override
Get the K index of the peak.
Definition: BasePeak.cpp:97
int getPeakNumber() const override
Returns the unique peak number Returns -1 if it could not find it.
Definition: BasePeak.cpp:234
int getRunNumber() const override
Return the run number this peak was measured at.
Definition: BasePeak.cpp:78
double getH() const override
Get the H index of the peak.
Definition: BasePeak.cpp:94
void setIntensity(double m_intensity) override
Set the integrated peak intensity.
Definition: BasePeak.cpp:198
Mantid::Kernel::Matrix< double > getGoniometerMatrix() const override
Get the goniometer rotation matrix at which this peak was measured.
Definition: BasePeak.cpp:210
double getMonitorCount() const override
Return the monitor count stored in this peak.
Definition: BasePeak.cpp:86
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:341
double getDSpacing() const override
Calculate the d-spacing of the peak, in 1/Angstroms
Definition: Peak.cpp:416
std::string getBankName() const
Find the name of the bank that is the parent of the detector.
Definition: Peak.cpp:353
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:332
double getL1() const override
Return the L1 flight path length (source to sample), in meters.
Definition: Peak.cpp:714
double getWavelength() const override
Calculate the neutron wavelength (in angstroms) at the peak (Note for inelastic scattering - it is th...
Definition: Peak.cpp:364
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:379
virtual Mantid::Kernel::V3D getDetPos() const
Return the detector position vector.
Definition: Peak.cpp:710
double getL2() const override
Return the L2 flight path length (sample to detector), in meters.
Definition: Peak.cpp:718
int getDetectorID() const
Get the ID of the detector at the center of the peak
Definition: Peak.cpp:271
double getScattering() const override
Calculate the scattering angle of the peak
Definition: Peak.cpp:397
IObject : Interface for geometry objects.
Definition: IObject.h:41
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 &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:86
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
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
Matrix< T > & Transpose()
Transpose the matrix.
Definition: Matrix.cpp:793
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
Class for 3D vectors.
Definition: V3D.h:34
double normalize()
Make a normalized vector (return norm value)
Definition: V3D.cpp:130
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:161
Holds support functions for strings.
Definition: RegexStrings.h:16
MANTID_KERNEL_DLL void readToEndOfLine(std::istream &in, bool ConsumeEOL)
Eat everything from the stream until the next EOL.
Definition: Strings.cpp:951
int convert(const std::string &A, T &out)
Convert a string into a number.
Definition: Strings.cpp:665
MANTID_KERNEL_DLL std::string getWord(std::istream &in, bool consumeEOL)
Returns the next word in the stream.
Definition: Strings.cpp:900
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:229
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:25
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition: EmptyValues.h:43
@ 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