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