Mantid
Loading...
Searching...
No Matches
SaveGSASInstrumentFile.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 +
10#include "MantidAPI/TableRow.h"
14
15#include <boost/algorithm/string/classification.hpp>
16#include <boost/algorithm/string/split.hpp>
17
18#include <cstdio>
19#include <iomanip>
20
21using namespace Mantid;
22using namespace Mantid::API;
23using namespace Mantid::Kernel;
24using namespace Mantid::DataObjects;
25
26using namespace std;
27
28namespace Mantid::DataHandling {
29
31
33public:
34 explicit ChopperConfiguration(vector<int> bankids);
35 ChopperConfiguration(const int freq, const std::string &bankidstr, const std::string &cwlstr,
36 const std::string &mndspstr, const std::string &mxdspstr, const std::string &maxtofstr);
37
39 std::vector<unsigned int> getBankIDs() const;
41 bool hasBank(unsigned int bankid) const;
43 double getParameter(unsigned int bankid, const std::string &paramname) const;
45 void setParameter(unsigned int bankid, const std::string &paramname, double value);
46
47private:
48 std::string parseString() const;
50 std::vector<double> parseStringDbl(const std::string &instring) const;
52 std::vector<unsigned int> parseStringUnsignedInt(const std::string &instring) const;
53
54 const double m_frequency;
55 std::vector<unsigned int> m_bankIDs;
56 std::map<unsigned int, size_t> m_bankIDIndexMap;
57
58 std::vector<double> m_vec2Theta;
59 std::vector<double> m_vecL1;
60 std::vector<double> m_vecL2;
61
62 std::vector<double> m_vecCWL;
63 std::vector<double> m_mindsps;
64 std::vector<double> m_maxdsps;
65 std::vector<double> m_maxtofs;
66
67 std::vector<double> m_splitds;
68 std::vector<int> m_vruns;
69};
70
71using ChopperConfiguration_sptr = std::shared_ptr<ChopperConfiguration>;
72
73//----------------------------------------------------------------------------------------------
76ChopperConfiguration::ChopperConfiguration(vector<int> bankids) : m_frequency(0) {
77 const size_t numbanks = bankids.size();
78
79 // Initialize vectors
80 m_bankIDs.assign(numbanks, 0);
81 m_vecCWL.assign(numbanks, EMPTY_DBL());
82 m_mindsps.assign(numbanks, EMPTY_DBL());
83 m_maxdsps.assign(numbanks, EMPTY_DBL());
84 m_maxtofs.assign(numbanks, EMPTY_DBL());
85
86 // Set bank IDs
87 m_bankIDs.assign(bankids.begin(), bankids.end());
88 m_bankIDIndexMap.clear();
89 for (size_t ib = 0; ib < numbanks; ++ib) {
90 m_bankIDIndexMap.emplace(m_bankIDs[ib], ib);
91 }
92}
93
94//----------------------------------------------------------------------------------------------
98ChopperConfiguration::ChopperConfiguration(const int freq, const std::string &bankidstr, const std::string &cwlstr,
99 const std::string &mndspstr, const std::string &mxdspstr,
100 const std::string &maxtofstr)
101 : m_frequency(freq), m_bankIDs(parseStringUnsignedInt(bankidstr)), m_vecCWL(parseStringDbl(cwlstr)),
102 m_mindsps(parseStringDbl(mndspstr)), m_maxdsps(parseStringDbl(mxdspstr)), m_maxtofs(parseStringDbl(maxtofstr))
103
104{
105 size_t numbanks = m_bankIDs.size();
106
107 // Check size
108 if (m_vecCWL.size() != numbanks || m_mindsps.size() != numbanks || m_maxdsps.size() != numbanks ||
109 m_maxtofs.size() != numbanks) {
110 std::string errmsg("Default chopper constants have different number of elements. ");
111 throw runtime_error(errmsg);
112 }
113
114 // Set up index map
115 m_vec2Theta.resize(numbanks, 0.);
116 m_vecL1.resize(numbanks, 0.);
117 m_vecL2.resize(numbanks, 0.);
118
119 // Set up bank ID / looking up index map
120 m_bankIDIndexMap.clear();
121 for (size_t ib = 0; ib < numbanks; ++ib) {
122 m_bankIDIndexMap.emplace(m_bankIDs[ib], ib);
123 }
124}
125
126//----------------------------------------------------------------------------------------------
129vector<unsigned int> ChopperConfiguration::getBankIDs() const { return m_bankIDs; }
130
131//----------------------------------------------------------------------------------------------
132
133bool ChopperConfiguration::hasBank(unsigned int bankid) const {
134 return std::find(m_bankIDs.begin(), m_bankIDs.end(), bankid) != m_bankIDs.end();
135}
136
137//----------------------------------------------------------------------------------------------
140double ChopperConfiguration::getParameter(unsigned int bankid, const string &paramname) const {
141 // Obtain index for the bank
142 auto biter = m_bankIDIndexMap.find(bankid);
143 if (biter == m_bankIDIndexMap.end()) {
144 stringstream errss;
145 errss << "Bank ID and index map does not have entry for bank " << bankid;
146 throw runtime_error(errss.str());
147 }
148 size_t bindex = biter->second;
149
150 double value(EMPTY_DBL());
151
152 if (paramname == "TwoTheta") {
153 value = m_vec2Theta[bindex];
154 } else if (paramname == "MinDsp") {
155 // cout << "size of min-dsp = " << m_mindsps.size() << ". --> bindex = " <<
156 // bindex << ".\n";
157 value = m_mindsps[bindex];
158 } else if (paramname == "MaxDsp") {
159 // cout << "size of max-dsp = " << m_maxdsps.size() << ". --> bindex = " <<
160 // bindex << ".\n";
161 value = m_maxdsps[bindex];
162 } else if (paramname == "MaxTOF") {
163 // cout << "size of max-tof = " << m_maxtofs.size() << ". --> bindex = " <<
164 // bindex << ".\n";
165 value = m_maxtofs[bindex];
166 } else if (paramname == "CWL") {
167 value = m_vecCWL[bindex];
168 } else {
169 stringstream errss;
170 errss << "ChopperConfiguration unable to locate: Bank ID = " << bankid << ", Parameter = " << paramname;
171 throw runtime_error(errss.str());
172 }
173
174 return value;
175}
176
177//----------------------------------------------------------------------------------------------
180void ChopperConfiguration::setParameter(unsigned int bankid, const string &paramname, double value) {
181 auto biter = m_bankIDIndexMap.find(bankid);
182
183 if (biter == m_bankIDIndexMap.end()) {
184 stringstream errss;
185 errss << "Chopper configuration does not have bank " << bankid;
186 throw runtime_error(errss.str());
187 } else {
188 size_t ibank = biter->second;
189
190 if (paramname == "2Theta")
191 m_vec2Theta[ibank] = value;
192 else if (paramname == "CWL")
193 m_vecCWL[ibank] = value;
194 else if (paramname == "L1")
195 m_vecL1[ibank] = value;
196 else if (paramname == "L2")
197 m_vecL2[ibank] = value;
198 else if (paramname == "MinTOF") {
199 // m_mintofs[ibank] = value;
200 } else if (paramname == "MaxTOF")
201 m_maxtofs[ibank] = value * 1.0E-3;
202 else if (paramname == "MinDsp")
203 m_mindsps[ibank] = value;
204 else if (paramname == "MaxDsp")
205 m_maxdsps[ibank] = value;
206 else {
207 stringstream errss;
208 errss << "In Chopper configuration's bank " << bankid << ", there is no parameter named " << paramname;
209 throw runtime_error(errss.str());
210 }
211 }
212}
213
214//----------------------------------------------------------------------------------------------
217vector<double> ChopperConfiguration::parseStringDbl(const string &instring) const {
218 vector<string> strs;
219 boost::split(strs, instring, boost::is_any_of(", "));
220
221 vector<double> vecdouble;
222 for (auto &str : strs) {
223 if (!str.empty()) {
224 double item = std::stod(str.c_str());
225 vecdouble.emplace_back(item);
226 // cout << "[C] |" << strs[i] << "|" << item << "\n";
227 }
228 }
229
230 // cout << "[C]* Input: " << instring << ": size of double vector: " <<
231 // vecdouble.size() << '\n';
232
233 return vecdouble;
234}
235
236//----------------------------------------------------------------------------------------------
239vector<unsigned int> ChopperConfiguration::parseStringUnsignedInt(const string &instring) const {
240 vector<string> strs;
241 boost::split(strs, instring, boost::is_any_of(", "));
242
243 vector<unsigned int> vecinteger;
244 for (auto &str : strs) {
245 if (!str.empty()) {
246 int item = std::stoi(str);
247 if (item < 0) {
248 throw runtime_error("Found negative number in a string for unsigned integers.");
249 }
250 vecinteger.emplace_back(static_cast<unsigned int>(item));
251 }
252 }
253
254 // cout << "[C]* Input : " << instring << ": size of string vector: " <<
255 // vecinteger.size() << '\n';
256
257 return vecinteger;
258}
259
260//----------------------------------------------------------------------------------------------
264 : API::Algorithm(), m_instrument(), m_L1(0.), m_L2(0.), m_2theta(0.), m_frequency(0), m_id_line(), m_sample(),
265 m_vecBankID2File(), m_gsasFileName(), m_configuration(), m_profileMap(), m_gdsp(), m_gdt(), m_galpha(), m_gbeta(),
266 m_bank_mndsp(), m_bank_mxtof() {}
267
268//----------------------------------------------------------------------------------------------
272 declareProperty(std::make_unique<WorkspaceProperty<ITableWorkspace>>("InputWorkspace", "", Direction::Input,
274 "Name of the table workspace containing the parameters.");
275
276 vector<string> infileexts{".irf"};
277 auto infileprop = std::make_unique<FileProperty>("InputFileName", "", FileProperty::OptionalLoad, infileexts);
278 declareProperty(std::move(infileprop), "Name of the input Fullprof resolution file (.irf).");
279
280 vector<string> outfileexts{".iparam", ".prm"};
281 auto fileprop = std::make_unique<FileProperty>("OutputFileName", "", FileProperty::Save, outfileexts);
282 declareProperty(std::move(fileprop), "Name of the output GSAS instrument file.");
283
284 declareProperty(std::make_unique<ArrayProperty<unsigned int>>("BankIDs"),
285 "Bank IDs of the banks to be written to GSAS instrument file.");
286
287 vector<string> instruments{"powgen", "nomad"};
288 declareProperty("Instrument", "powgen", std::make_shared<StringListValidator>(instruments),
289 "Name of the instrument that parameters are belonged to. "
290 "So far, only PG3 and NOM are supported.");
291
292 vector<string> vecfreq{"10", "30", "60"};
293 declareProperty("ChopperFrequency", "60", std::make_shared<StringListValidator>(vecfreq),
294 "Frequency of the chopper. ");
295
296 declareProperty("IDLine", "", "ID line to be written in GSAS instrument file");
297 declareProperty("Sample", "", "Sample information written to header (title) ");
298
299 std::shared_ptr<BoundedValidator<double>> mustBePositive(new BoundedValidator<double>());
300 mustBePositive->setLower(0.0);
301
302 declareProperty("L1", EMPTY_DBL(), mustBePositive, "L1 (primary flight path) of the instrument. ");
304 "L2 (secondary flight path) of the instrument. "
305 "It must be given if 2Theta is not given. ");
306 declareProperty("TwoTheta", EMPTY_DBL(), mustBePositive,
307 "Angle of the detector bank. "
308 "It must be given if L2 is not given. ");
309}
310
311//----------------------------------------------------------------------------------------------
315 // Process user specified properties
317
318 // Parse profile table workspace
319 map<unsigned int, map<string, double>> bankprofileparammap;
320 parseProfileTableWorkspace(m_inpWS, bankprofileparammap);
321
322 // Initialize some conversion constants related to the chopper
323 initConstants(bankprofileparammap);
324
325 // Deal with a default
326 if (m_vecBankID2File.empty()) {
327 // Default is to export all banks
328 for (auto &miter : bankprofileparammap) {
329 unsigned int bankid = miter.first;
330 m_vecBankID2File.emplace_back(bankid);
331 }
332 sort(m_vecBankID2File.begin(), m_vecBankID2File.end());
333 }
334 g_log.debug() << "Number of banks to output = " << m_vecBankID2File.size() << ".\n";
335
336 // Convert to GSAS
337 convertToGSAS(m_vecBankID2File, m_gsasFileName, bankprofileparammap);
338
339 // Fix?
341 IAlgorithm_sptr fit;
342 try {
343 // Fitting the candidate peaks to a Gaussian
344 fit = createChildAlgorithm("FixGSASInstrumentFile", -1, -1, true);
345 fit->initialize();
346 fit->setProperty("InputFilename", m_gsasFileName);
347 fit->setProperty("OutputFilename", m_gsasFileName);
348 fit->execute();
349 } catch (Exception::NotFoundError &) {
350 std::string errorstr("FindPeaks algorithm requires the CurveFitting library");
351 g_log.error(errorstr);
352 throw std::runtime_error(errorstr);
353 }
354}
355
356//----------------------------------------------------------------------------------------------
360 // Input workspace
361 bool loadirf = false;
362 m_inpWS = getProperty("InputWorkspace");
363 if (!m_inpWS)
364 loadirf = true;
365
366 if (loadirf) {
367 // Load .irf file to m_inpWS
368 string irffilename = getProperty("InputFileName");
369 loadFullprofResolutionFile(irffilename);
370
371 if (!m_inpWS) {
372 stringstream errss;
373 errss << "Neither input table workspace (" << getPropertyValue("InputWorkspace") << ") nor "
374 << "input .irf file " << getPropertyValue("InputFileName") << " is valid. ";
375 g_log.error(errss.str());
376 throw runtime_error(errss.str());
377 }
378 }
379
380 // Instrument information
381 m_instrument = getPropertyValue("Instrument");
382 m_id_line = getPropertyValue("IDLine"); // Standard Run LB4844 Vanadium: 4866 J.P. Hodges 2011-09-01
383 m_sample = getPropertyValue("Sample"); // titleline = "LaB6 NIST RT 4844[V=4866] 60Hz CW=.533"
384
385 m_gsasFileName = getPropertyValue("OutputFileName");
386 m_vecBankID2File = getProperty("BankIDs");
387
388 m_L1 = getProperty("L1");
389 if (isEmpty(m_L1))
390 throw runtime_error("L1 must be given!");
391 m_2theta = getProperty("TwoTheta");
392 m_L2 = getProperty("L2");
393 string freqtempstr = getProperty("ChopperFrequency");
394 m_frequency = std::stoi(freqtempstr);
395
396 /* Set default value for L1
397 if (m_L1 == EMPTY_DBL())
398 {
399 if (m_instrument == "PG3")
400 {
401 m_L1 = 60.0;
402 }
403 else if (m_instrument == "NOM")
404 {
405 m_L1 = 19.5;
406 }
407 else
408 {
409 stringstream errss;
410 errss << "L1 is not given. There is no default value for instrument " <<
411 m_instrument
412 << "Only NOMAD and POWGEN are supported now.\n";
413 g_log.error(errss.str());
414 throw runtime_error(errss.str());
415 }
416 }
417 else if (m_L1 <= 0.)
418 {
419 throw runtime_error("Input L1 cannot be less or equal to 0.");
420 }
421 */
422
423 // Set default value for L2
424 if (isEmpty(m_2theta)) {
425 if (isEmpty(m_L2)) {
426 string errmsg("User must specify either 2theta or L2. Neither of them is given.");
427 g_log.error(errmsg);
428 throw runtime_error(errmsg);
429 }
430 } else {
431 // Override L2 by 2theta
432 m_L2 = EMPTY_DBL();
433 }
434}
435
436//----------------------------------------------------------------------------------------------
441void SaveGSASInstrumentFile::initConstants(const map<unsigned int, map<string, double>> &profmap) {
443
444 /*
445 if (m_instrument == "PG3")
446 {
447 m_configuration = setupPG3Constants(chopperfrequency);
448 }
449 else if (m_instrument == "NOM")
450 {
451 m_configuration = setupNOMConstants(chopperfrequency);
452 }
453 else
454 {
455 stringstream errss;
456 errss << "Instrument " << m_instrument << " is not supported. ";
457 throw runtime_error(errss.str());
458 }
459 */
460}
461
462//----------------------------------------------------------------------------------------------
466 map<unsigned int, map<string, double>> &profilemap) {
467 size_t numbanks = ws->columnCount() - 1;
468 size_t numparams = ws->rowCount();
469 vector<map<string, double>> vec_maptemp(numbanks);
470 vector<unsigned int> vecbankindex(numbanks);
471
472 // Check
473 vector<string> colnames = ws->getColumnNames();
474 if (colnames[0] != "Name")
475 throw runtime_error("The first column must be Name");
476
477 // Parse
478 for (size_t irow = 0; irow < numparams; ++irow) {
479 TableRow tmprow = ws->getRow(irow);
480 string parname;
481 tmprow >> parname;
482 if (parname != "BANK") {
483 for (size_t icol = 0; icol < numbanks; ++icol) {
484 double tmpdbl;
485 tmprow >> tmpdbl;
486 vec_maptemp[icol].emplace(parname, tmpdbl);
487 }
488 } else {
489 for (size_t icol = 0; icol < numbanks; ++icol) {
490 double tmpint;
491 tmprow >> tmpint;
492 vecbankindex[icol] = static_cast<unsigned int>(tmpint);
493 }
494 }
495 }
496
497 // debug output
498 stringstream db1ss;
499 db1ss << "[DBx912] Number of banks in profile table = " << vecbankindex.size() << " containing bank ";
500 for (auto bankIndex : vecbankindex)
501 db1ss << bankIndex << ", ";
502 g_log.information(db1ss.str());
503
504 // Construct output
505 profilemap.clear();
506
507 for (size_t i = 0; i < vecbankindex.size(); ++i) {
508 unsigned int bankid = vecbankindex[i];
509 profilemap.emplace(bankid, vec_maptemp[i]);
510 }
511}
512
513//----------------------------------------------------------------------------------------------
517SaveGSASInstrumentFile::setupInstrumentConstants(const map<unsigned int, map<string, double>> &profmap) {
518 // Collect bank ids
519 vector<int> bankids;
520 map<unsigned int, map<string, double>>::const_iterator bmiter;
521 for (bmiter = profmap.begin(); bmiter != profmap.end(); ++bmiter) {
522 int bankid = bmiter->first;
523 bankids.emplace_back(bankid);
524 }
525
526 // Create a configuration object
527 ChopperConfiguration_sptr chconfig = std::make_shared<ChopperConfiguration>(bankids);
528
529 // Add chopper/instrument constants by banks
530 for (bmiter = profmap.begin(); bmiter != profmap.end(); ++bmiter) {
531 int bankid = bmiter->first;
532
533 double cwl = getProfileParameterValue(bmiter->second, "CWL");
534 double mintof = getProfileParameterValue(bmiter->second, "tof-min");
535 double maxtof = getProfileParameterValue(bmiter->second, "tof-max");
536 double dtt1 = getProfileParameterValue(bmiter->second, "Dtt1");
537 double zero = getProfileParameterValue(bmiter->second, "Zero");
538
539 double dmin = calDspRange(dtt1, zero, mintof);
540 double dmax = calDspRange(dtt1, zero, maxtof);
541
542 chconfig->setParameter(bankid, "CWL", cwl);
543 chconfig->setParameter(bankid, "MaxTOF", maxtof);
544 chconfig->setParameter(bankid, "MinDsp", dmin);
545 chconfig->setParameter(bankid, "MaxDsp", dmax);
546
547 g_log.information() << "Import bank " << bankid << ". TOF range: " << mintof << ", " << maxtof
548 << "; D-space range: " << dmin << ", " << dmax << ".\n";
549 }
550
551 return chconfig;
552}
553
554//----------------------------------------------------------------------------------------------
558 string bankidstr, cwlstr, mndspstr, mxdspstr, maxtofstr;
559
560 // Create string
561 switch (intfrequency) {
562 case 60:
563 bankidstr = "1,2,3,4,5,6,7";
564 cwlstr = "0.533, 1.066, 1.333, 1.599, 2.665, 3.731, 4.797";
565 mndspstr = "0.10, 0.276, 0.414, 0.552, 1.104, 1.656, 2.208";
566 mxdspstr = "2.06, 3.090, 3.605, 4.120, 6.180, 8.240, 10.30";
567 maxtofstr = "46.76, 70.14, 81.83, 93.52, 140.3, 187.0, 233.8";
568
569 break;
570 case 30:
571 bankidstr = "1,2,3";
572 cwlstr = "1.066, 3.198, 5.33";
573 mndspstr = "0.10, 1.104, 2.208";
574 mxdspstr = "4.12, 8.24, 12.36";
575 maxtofstr = "93.5, 187.0, 280.5";
576
577 break;
578
579 case 10:
580 // Frequency = 10
581 bankidstr = "1";
582 cwlstr = "3.198";
583 mndspstr = "0.10";
584 mxdspstr = "12.36";
585 maxtofstr = "280.5";
586
587 break;
588
589 default:
590 throw runtime_error("Not supported");
591 break;
592 }
593
594 // Return
595 return std::make_shared<ChopperConfiguration>(intfrequency, bankidstr, cwlstr, mndspstr, mxdspstr, maxtofstr);
596}
597
598//----------------------------------------------------------------------------------------------
603 // Set up string
604 string bankidstr, cwlstr, mndspstr, mxdspstr, maxtofstr;
605
606 // FIXME : Requiring more banks
607 switch (intfrequency) {
608 case 60:
609 bankidstr = "4,5";
610 cwlstr = "1.500, 1.5000";
611 mndspstr = "0.052, 0.0450";
612 mxdspstr = "2.630, 2.6000";
613 maxtofstr = "93.52, 156.00";
614 break;
615
616 default:
617 stringstream errss;
618 errss << "NOMAD Frequency = " << intfrequency << " is not supported. ";
619 throw runtime_error(errss.str());
620 break;
621 }
622
623 // Create configuration
624 return std::make_shared<ChopperConfiguration>(intfrequency, bankidstr, cwlstr, mndspstr, mxdspstr, maxtofstr);
625}
626
627//----------------------------------------------------------------------------------------------
635 const std::vector<unsigned int> &outputbankids, const std::string &gsasinstrfilename,
636 const std::map<unsigned int, std::map<std::string, double>> &bankprofilemap) {
637 // Check
638 if (!m_configuration)
639 throw runtime_error("Not set up yet!");
640
641 // Set up min-dsp, max-tof
642 for (auto bankid : outputbankids) {
643 if (!m_configuration->hasBank(bankid))
644 throw runtime_error("Chopper configuration does not have some certain bank.");
645
646 double mndsp = m_configuration->getParameter(bankid, "MinDsp");
647 m_bank_mndsp.emplace(bankid, mndsp);
648 double mxtof = m_configuration->getParameter(bankid, "MaxTOF");
649 m_bank_mxtof.emplace(bankid, mxtof);
650 }
651
652 // Write bank header
653 g_log.information() << "Export header of GSAS instrument file " << gsasinstrfilename << ".\n";
654 writePRMHeader(outputbankids, gsasinstrfilename);
655
656 // Convert and write
657 vector<unsigned int> banks = outputbankids;
658 sort(banks.begin(), banks.end());
659 for (auto bankid : banks) {
660 if (m_configuration->hasBank(bankid)) {
661 buildGSASTabulatedProfile(bankprofilemap, bankid);
662 writePRMSingleBank(bankprofilemap, bankid, gsasinstrfilename);
663 } else {
664 vector<unsigned int> bankids = m_configuration->getBankIDs();
665 stringstream errss;
666 errss << "Bank " << bankid << " does not exist in source resolution file. "
667 << "There are " << bankids.size() << " banks given, including "
668 << ".\n";
669 for (size_t i = 0; i < bankids.size(); ++i) {
670 errss << bankids[i];
671 if (i < bankids.size() - 1)
672 errss << ", ";
673 }
674 g_log.error(errss.str());
675 throw runtime_error(errss.str());
676 }
677 }
678}
679
680//----------------------------------------------------------------------------------------------
688 const std::map<unsigned int, std::map<std::string, double>> &bankprofilemap, unsigned int bankid) {
689 // Locate the profile map
690 auto biter = bankprofilemap.find(bankid);
691 if (biter == bankprofilemap.end())
692 throw runtime_error("Bank ID cannot be found in bank-profile-map-map. 001");
693 const map<string, double> &profilemap = biter->second;
694
695 // Init data structure
696 // m_gdsp = gdsp;
697 // m_gdt = gdt;
698 // m_galpha = galpha;
699 // m_gbeta = gbeta;
700
701 m_gdsp.assign(90, 0.); // TOF_thermal(d_k)
702 m_galpha.assign(90, 0.); // delta(alpha)
703 m_gbeta.assign(90, 0.); // delta(beta)
704 m_gdt.assign(90, 0.);
705
706 vector<double> gtof(90, 0.); // TOF_thermal(d_k) - TOF(d_k)
707 vector<double> gpkX(90, 0.); // ratio (n) b/w thermal and epithermal neutron
708
709 // double twotheta = m_configuration->getParameter(bankid, "TwoTheta");
710 double mx = getProfileParameterValue(profilemap, "Tcross");
711 double mxb = getProfileParameterValue(profilemap, "Width");
712
713 double zero = getProfileParameterValue(profilemap, "Zero");
714 double zerot = getProfileParameterValue(profilemap, "Zerot");
715 double dtt1 = getProfileParameterValue(profilemap, "Dtt1");
716 double dtt1t = getProfileParameterValue(profilemap, "Dtt1t");
717 double dtt2 = getProfileParameterValue(profilemap, "Dtt2");
718 double dtt2t = getProfileParameterValue(profilemap, "Dtt2t");
719
720 double alph0 = getProfileParameterValue(profilemap, "Alph0");
721 double alph1 = getProfileParameterValue(profilemap, "Alph1");
722 double alph0t = getProfileParameterValue(profilemap, "Alph0t");
723 double alph1t = getProfileParameterValue(profilemap, "Alph1t");
724
725 double beta0 = getProfileParameterValue(profilemap, "Beta0");
726 double beta1 = getProfileParameterValue(profilemap, "Beta1");
727 double beta0t = getProfileParameterValue(profilemap, "Beta0t");
728 double beta1t = getProfileParameterValue(profilemap, "Beta1t");
729
730 double instC = dtt1 - 4 * (alph0 + alph1);
731
732 double mxdsp = m_configuration->getParameter(bankid, "MaxDsp");
733 double mndsp = m_configuration->getParameter(bankid, "MinDsp");
734
735 double ddstep = ((1.05 * mxdsp) - (0.9 * mndsp)) / 90.;
736
737 for (size_t k = 0; k < 90; ++k) {
738 m_gdsp[k] = (0.9 * mndsp) + (static_cast<double>(k) * ddstep);
739 double rd = 1.0 / m_gdsp[k];
740 double dmX = mx - rd;
741 gpkX[k] = 0.5 * erfc(mxb * dmX); // # this is n in the formula
742 gtof[k] = calTOF(gpkX[k], zero, dtt1, dtt2, zerot, dtt1t, -dtt2t, m_gdsp[k]);
743 m_gdt[k] = gtof[k] - (instC * m_gdsp[k]);
744 m_galpha[k] = aaba(gpkX[k], alph0, alph1, alph0t, alph1t, m_gdsp[k]);
745 m_gbeta[k] = aaba(gpkX[k], beta0, beta1, beta0t, beta1t, m_gdsp[k]);
746
747 g_log.debug() << k << "\t" << setw(20) << setprecision(10) << gtof[k] << "\t " << setw(20) << setprecision(10)
748 << m_gdsp[k] << "\t " << setw(20) << setprecision(10) << instC << "\t " << setw(20)
749 << setprecision(10) << m_gdt[k] << ".\n";
750 }
751}
752
753//----------------------------------------------------------------------------------------------
756void SaveGSASInstrumentFile::writePRMHeader(const vector<unsigned int> &banks, const string &prmfilename) {
757 auto numbanks = static_cast<int>(banks.size());
758
759 FILE *pFile;
760 pFile = fopen(prmfilename.c_str(), "w");
761 if (!pFile) {
762 stringstream errss;
763 errss << "Unable to open file " << prmfilename << " in write-mode";
764 throw runtime_error(errss.str());
765 }
766 fprintf(pFile, " "
767 "1234567890123456789012345678901234567890123456789012345678901"
768 "2345678\n");
769 fprintf(pFile, "ID %s\n", m_id_line.c_str());
770 fprintf(pFile, "INS BANK %5d\n", numbanks);
771 fprintf(pFile, "INS FPATH1 %f \n", m_L1);
772 fprintf(pFile, "INS HTYPE PNTR \n");
773 fclose(pFile);
774}
775
776//----------------------------------------------------------------------------------------------
783 const std::map<unsigned int, std::map<std::string, double>> &bankprofilemap, unsigned int bankid,
784 const std::string &prmfilename) {
785 // Get access to the profile map
786 auto biter = bankprofilemap.find(bankid);
787 if (biter == bankprofilemap.end())
788 throw runtime_error("Bank does not exist in bank-profile-map. 002");
789
790 const map<string, double> &profilemap = biter->second;
791
792 // Collect parameters used for output
793 double zero = getProfileParameterValue(profilemap, "Zero");
794 double dtt1 = getProfileParameterValue(profilemap, "Dtt1");
795 double alph0 = getProfileParameterValue(profilemap, "Alph0");
796 double alph1 = getProfileParameterValue(profilemap, "Alph1");
797 double twotheta = getProfileParameterValue(profilemap, "twotheta");
798
799 double sig0 = getProfileParameterValue(profilemap, "Sig0");
800 sig0 = sig0 * sig0;
801 double sig1 = getProfileParameterValue(profilemap, "Sig1");
802 sig1 = sig1 * sig1;
803 double sig2 = getProfileParameterValue(profilemap, "Sig2");
804 sig2 = sig2 * sig2;
805 double gam0 = getProfileParameterValue(profilemap, "Gam0");
806 double gam1 = getProfileParameterValue(profilemap, "Gam1");
807 double gam2 = getProfileParameterValue(profilemap, "Gam2");
808
809 int randint = 10001 + (rand() % (99999 - 10001 + 1));
810
811 double mindsp = m_configuration->getParameter(bankid, "MinDsp");
812 double maxtof = m_configuration->getParameter(bankid, "MaxTOF");
813 double cwl = m_configuration->getParameter(bankid, "CWL");
814
815 // Calculate L2
816 double instC = dtt1 - (4 * (alph0 + alph1));
817 g_log.debug() << "Bank " << bankid << ": MaxTOF = " << maxtof << "; Dtt1 = " << dtt1 << ", Alph0 = " << alph0
818 << ", Alph1 = " << alph1 << ", MinDsp = " << mindsp << ".\n";
819
820 if (m_L2 <= 0. || m_L2 == EMPTY_DBL()) {
822 }
823
824 // Title line
825 stringstream titless;
826 titless << m_sample << " " << static_cast<int>(m_frequency) << "Hz CW=" << cwl;
827 string titleline(titless.str());
828
829 // Write to file
830 FILE *pFile;
831 pFile = fopen(prmfilename.c_str(), "a");
832 if (!pFile) {
833 stringstream errss;
834 errss << "Unable to open file " << prmfilename << " in append-mode";
835 throw runtime_error(errss.str());
836 }
837
838 fprintf(pFile, "INS %2u ICONS%10.3f%10.3f%10.3f %10.3f%5d%10.3f\n", bankid, instC * 1.00009, 0.0, zero, 0.0,
839 0, 0.0);
840 fprintf(pFile, "INS %2uBNKPAR%10.3f%10.3f%10.3f%10.3f%10.3f%5d%5d\n", bankid, m_L2, twotheta, 0., 0., 0.2, 1, 1);
841
842 fprintf(pFile, "INS %2uBAKGD 1 4 Y 0 Y\n", bankid);
843 fprintf(pFile, "INS %2uI HEAD %s\n", bankid, titleline.c_str());
844 fprintf(pFile, "INS %2uI ITYP%5d%10.4f%10.4f%10i\n", bankid, 0, mindsp * 0.001 * instC, maxtof, randint);
845 fprintf(pFile, "INS %2uINAME %s \n", bankid, m_instrument.c_str());
846 fprintf(pFile, "INS %2uPRCF1 %5d%5d%10.5f\n", bankid, -3, 21, 0.002);
847 fprintf(pFile, "INS %2uPRCF11%15.6f%15.6f%15.6f%15.6f\n", bankid, 0.0, 0.0, 0.0, sig0);
848 fprintf(pFile, "INS %2uPRCF12%15.6f%15.6f%15.6f%15.6f\n", bankid, sig1, sig2, gam0, gam1);
849 fprintf(pFile, "INS %2uPRCF13%15.6f%15.6f%15.6f%15.6f\n", bankid, gam2, 0.0, 0.0, 0.0);
850 fprintf(pFile, "INS %2uPRCF14%15.6f%15.6f%15.6f%15.6f\n", bankid, 0.0, 0.0, 0.0, 0.0);
851 fprintf(pFile, "INS %2uPRCF15%15.6f%15.6f%15.6f%15.6f\n", bankid, 0.0, 0.0, 0.0, 0.0);
852 fprintf(pFile, "INS %2uPRCF16%15.6f\n", bankid, 0.0);
853 fprintf(pFile, "INS %2uPAB3 %3d\n", bankid, 90);
854
855 for (size_t k = 0; k < 90; ++k) {
856 fprintf(pFile, "INS %2uPAB3%2d%10.5f%10.5f%10.5f%10.5f\n", bankid, static_cast<int>(k) + 1, m_gdsp[k], m_gdt[k],
857 m_galpha[k], m_gbeta[k]);
858 }
859 fprintf(pFile, "INS %2uPRCF2 %5i%5i%10.5f\n", bankid, -4, 27, 0.002);
860 fprintf(pFile, "INS %2uPRCF21%15.6f%15.6f%15.6f%15.6f\n", bankid, 0.0, 0.0, 0.0, sig1);
861 fprintf(pFile, "INS %2uPRCF22%15.6f%15.6f%15.6f%15.6f\n", bankid, sig2, gam2, 0.0, 0.0);
862 fprintf(pFile, "INS %2uPRCF23%15.6f%15.6f%15.6f%15.6f\n", bankid, 0.0, 0.0, 0.0, 0.0);
863 fprintf(pFile, "INS %2uPRCF24%15.6f%15.6f%15.6f%15.6f\n", bankid, 0.0, 0.0, 0.0, 0.0);
864 fprintf(pFile, "INS %2uPRCF25%15.6f%15.6f%15.6f%15.6f\n", bankid, 0.0, 0.0, 0.0, 0.0);
865 fprintf(pFile, "INS %2uPRCF26%15.6f%15.6f%15.6f%15.6f\n", bankid, 0.0, 0.0, 0.0, 0.0);
866 fprintf(pFile, "INS %2uPRCF27%15.6f%15.6f%15.6f \n", bankid, 0.0, 0.0, 0.0);
867
868 fprintf(pFile, "INS %2uPAB4 %3i\n", bankid, 90);
869 for (size_t k = 0; k < 90; ++k) {
870 fprintf(pFile, "INS %2uPAB4%2d%10.5f%10.5f%10.5f%10.5f\n", bankid, static_cast<int>(k) + 1, m_gdsp[k], m_gdt[k],
871 m_galpha[k], m_gbeta[k]);
872 }
873
874 fprintf(pFile, "INS %2uPRCF3 %5i%5i%10.5f\n", bankid, -5, 21, 0.002);
875 fprintf(pFile, "INS %2uPRCF31%15.6f%15.6f%15.6f%15.6f\n", bankid, 0.0, 0.0, 0.0, sig0);
876 fprintf(pFile, "INS %2uPRCF32%15.6f%15.6f%15.6f%15.6f\n", bankid, sig1, sig2, gam0, gam1);
877 fprintf(pFile, "INS %2uPRCF33%15.6f%15.6f%15.6f%15.6f\n", bankid, gam2, 0.0, 0.0, 0.0);
878 fprintf(pFile, "INS %2uPRCF34%15.6f%15.6f%15.6f%15.6f\n", bankid, 0.0, 0.0, 0.0, 0.0);
879 fprintf(pFile, "INS %2uPRCF35%15.6f%15.6f%15.6f%15.6f\n", bankid, 0.0, 0.0, 0.0, 0.0);
880 fprintf(pFile, "INS %2uPRCF36%15.6f\n", bankid, 0.0);
881
882 fprintf(pFile, "INS %2uPAB5 %3i\n", bankid,
883 90); // 90 means there will be 90 lines of table
884 for (size_t k = 0; k < 90; k++) {
885 fprintf(pFile, "INS %2uPAB5%2d%10.5f%10.5f%10.5f%10.5f\n", bankid, static_cast<int>(k) + 1, m_gdsp[k], m_gdt[k],
886 m_galpha[k], m_gbeta[k]);
887 }
888
889 fclose(pFile);
890}
891
892//----------------------------------------------------------------------------------------------
896double SaveGSASInstrumentFile::calL2FromDtt1(double difc, double L1, double twotheta) {
897 double l2 = difc / (252.816 * 2.0 * sin(0.5 * twotheta * M_PI / 180.0)) - L1;
898 g_log.debug() << "DIFC = " << difc << ", L1 = " << L1 << ", 2Theta = " << twotheta << " ==> L2 = " << l2 << ".\n";
899
900 return l2;
901}
902
903//----------------------------------------------------------------------------------------------
918double SaveGSASInstrumentFile::calTOF(double n, double ep, double eq, double er, double tp, double tq, double tr,
919 double dsp) {
920 double te = ep + (eq * dsp) + er * 0.5 * erfc(((1.0 / dsp) - 1.05) * 10.0);
921 double tt = tp + (tq * dsp) + (tr / dsp);
922 double t = (n * te) + tt - (n * tt);
923
924 return t;
925}
926
927//----------------------------------------------------------------------------------------------
931double SaveGSASInstrumentFile::aaba(double n, double ea1, double ea2, double ta1, double ta2, double dsp) {
932 double ea = ea1 + (ea2 * dsp);
933 double ta = ta1 - (ta2 / dsp);
934 double am1 = (n * ea) + ta - (n * ta);
935 double a = 1.0 / am1;
936
937 return a;
938}
939
940//----------------------------------------------------------------------------------------------
943double SaveGSASInstrumentFile::getValueFromMap(const map<string, double> &profilemap, const string &parname) {
944 std::map<std::string, double>::const_iterator piter;
945 piter = profilemap.find(parname);
946 if (piter == profilemap.end()) {
947 stringstream errss;
948 errss << "Profile parameter map does not contain parameter" << parname << ". ";
949 g_log.error(errss.str());
950 throw runtime_error(errss.str());
951 }
952
953 double value = piter->second;
954
955 return value;
956}
957
958//----------------------------------------------------------------------------------------------
961double SaveGSASInstrumentFile::getProfileParameterValue(const map<string, double> &profilemap,
962 const string &paramname) {
963 auto piter = profilemap.find(paramname);
964 if (piter == profilemap.end()) {
965 stringstream errss;
966 errss << "Profile map does not contain parameter " << paramname << ". Available parameters are ";
967 for (const auto &parameter : profilemap) {
968 errss << parameter.first << ", ";
969 }
970 g_log.error(errss.str());
971 throw runtime_error(errss.str());
972 }
973
974 double value = piter->second;
975
976 return value;
977}
978
979//----------------------------------------------------------------------------------------------
986double SaveGSASInstrumentFile::calDspRange(double dtt1, double zero, double tof) {
987 double dsp = (tof - zero) / dtt1;
988 return dsp;
989}
990
991//----------------------------------------------------------------------------------------------
997void SaveGSASInstrumentFile::loadFullprofResolutionFile(const std::string &irffilename) {
998 IAlgorithm_sptr loadfpirf;
999 try {
1000 loadfpirf = createChildAlgorithm("LoadFullprofResolution");
1001 } catch (Exception::NotFoundError &) {
1002 g_log.error("SaveGSASInstrumentFile requires DataHandling library for "
1003 "LoadFullprofResolution.");
1004 throw runtime_error("SaveGSASInstrumentFile requires DataHandling library "
1005 "for LoadFullprofResolution.");
1006 }
1007
1008 loadfpirf->setProperty("Filename", irffilename);
1009 loadfpirf->setProperty("OutputTableWorkspace", "outputTableWorkspace");
1010
1011 loadfpirf->execute();
1012 if (!loadfpirf->isExecuted())
1013 throw runtime_error("LoadFullprof cannot be executed. ");
1014
1015 m_inpWS = loadfpirf->getProperty("OutputTableWorkspace");
1016 if (!m_inpWS)
1017 throw runtime_error("Failed to obtain a table workspace from "
1018 "LoadFullprofResolution's output.");
1019}
1020
1021//----------------------------------------------------------------------------------------------
1025 double x = fabs(xx);
1026 double t = 1.0 / (1.0 + (0.5 * x));
1027 double ty = (0.27886807 + t * (-1.13520398 + t * (1.48851587 + t * (-0.82215223 + t * 0.17087277))));
1028 double tx = (1.00002368 + t * (0.37409196 + t * (0.09678418 + t * (-0.18628806 + t * ty))));
1029 double y = t * exp(-x * x - 1.26551223 + t * tx);
1030 if (xx < 0)
1031 y = 2.0 - y;
1032
1033 return y;
1034}
1035
1036} // namespace Mantid::DataHandling
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
static std::unique_ptr< QThreadPool > tp
double value
The value of the point.
Definition: FitMW.cpp:51
const std::vector< double > & m_L2
Definition: LoadEMU.cpp:231
#define fabs(x)
Definition: Matrix.cpp:22
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:85
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
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
static bool isEmpty(const NumT toCheck)
checks that the value was not set by users, uses the value in empty double/int.
@ 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
TableRow represents a row in a TableWorkspace.
Definition: TableRow.h:39
size_t size() const
Returns the number of rows in the TableWorkspace.
Definition: TableRow.h:45
A property class for workspaces.
ChopperConfiguration(vector< int > bankids)
Constructor.
std::vector< unsigned int > getBankIDs() const
Get bank IDs in configuration.
std::map< unsigned int, size_t > m_bankIDIndexMap
double getParameter(unsigned int bankid, const std::string &paramname) const
Get a parameter from a bank.
bool hasBank(unsigned int bankid) const
Check wehther a bank is defined.
std::vector< double > parseStringDbl(const std::string &instring) const
Parse string to a double vector.
std::vector< unsigned int > parseStringUnsignedInt(const std::string &instring) const
Parse string to an integer vector.
void setParameter(unsigned int bankid, const std::string &paramname, double value)
Set a parameter to a bank.
SaveGSASInstrumentFile : Convert Fullprof"s instrument resolution file (.irf) to GSAS"s instrument f...
API::ITableWorkspace_sptr m_inpWS
Input workspace.
double calDspRange(double dtt1, double zero, double tof)
Calcualte d-space value.
void buildGSASTabulatedProfile(const std::map< unsigned int, std::map< std::string, double > > &bankprofilemap, unsigned int bankid)
Build a data structure for GSAS's tabulated peak profile.
void convertToGSAS(const std::vector< unsigned int > &outputbankids, const std::string &gsasinstrfilename, const std::map< unsigned int, std::map< std::string, double > > &bankprofilemap)
Convert to GSAS instrument file.
std::shared_ptr< ChopperConfiguration > m_configuration
Chopper configuration.
double getProfileParameterValue(const std::map< std::string, double > &profilemap, const std::string &paramname)
Get parameter value from class storage.
double aaba(double n, double ea1, double ea2, double ta1, double ta2, double dsp)
Calculate a value related to (alph0, alph1, alph0t, alph1t) or (beta0, beta1, beta0t,...
std::shared_ptr< ChopperConfiguration > setupInstrumentConstants(const std::map< unsigned int, std::map< std::string, double > > &profmap)
Set up chopper/instrument constant parameters from profile map.
double calL2FromDtt1(double difc, double L1, double twotheta)
Caclualte L2 from DIFFC and L1.
double calTOF(double n, double ep, double eq, double er, double tp, double tq, double tr, double dsp)
Calculate TOF difference.
void initConstants(const std::map< unsigned int, std::map< std::string, double > > &profmap)
Set up some constant by default.
double erfc(double xx)
Complementary error function.
void loadFullprofResolutionFile(const std::string &irffilename)
Load fullprof resolution file.
std::vector< unsigned int > m_vecBankID2File
Banks IDs to process.
std::shared_ptr< ChopperConfiguration > setupPG3Constants(int intfrequency)
Set up for PG3 chopper constants.
void parseProfileTableWorkspace(const API::ITableWorkspace_sptr &ws, std::map< unsigned int, std::map< std::string, double > > &profilemap)
Parse profile table workspace to a map.
void writePRMSingleBank(const std::map< unsigned int, std::map< std::string, double > > &bankprofilemap, unsigned int bankid, const std::string &prmfilename)
Write out .prm/.iparm file.
double getValueFromMap(const std::map< std::string, double > &profilemap, const std::string &parname)
Get parameter value from a map.
std::shared_ptr< ChopperConfiguration > setupNOMConstants(int intfrequency)
Set up for NOM chopper constants.
void writePRMHeader(const std::vector< unsigned int > &banks, const std::string &prmfilename)
Write the header of the file.
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
BoundedValidator is a validator that requires the values to be between upper or lower bounds,...
Exception for when an item is not found in a collection.
Definition: Exception.h:145
void debug(const std::string &msg)
Logs at debug level.
Definition: Logger.cpp:114
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< IAlgorithm > IAlgorithm_sptr
shared pointer to Mantid::API::IAlgorithm
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
std::shared_ptr< ChopperConfiguration > ChopperConfiguration_sptr
Helper class which provides the Collimation Length for SANS instruments.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition: EmptyValues.h:43
STL namespace.
@ Input
An input workspace.
Definition: Property.h:53