Mantid
Loading...
Searching...
No Matches
LoadFullprofResolution.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 +
11#include "MantidAPI/TableRow.h"
17
18#include <boost/algorithm/string.hpp>
19#include <boost/algorithm/string/finder.hpp>
20#include <boost/algorithm/string/iter_find.hpp>
21#include <boost/algorithm/string/predicate.hpp>
22#include <boost/algorithm/string/trim.hpp>
23
24#include <Poco/DOM/AutoPtr.h>
25#include <Poco/DOM/DOMWriter.h>
26#include <Poco/DOM/Element.h>
27#include <Poco/XML/XMLWriter.h>
28
29#include <fstream>
30
31using namespace Mantid;
32using namespace Mantid::API;
33using namespace Mantid::DataObjects;
34using namespace Mantid::Kernel;
35using namespace std;
36using namespace Poco::XML;
37
40
41namespace Mantid::DataHandling {
42
44
45std::map<std::string, size_t> LoadFullprofResolution::m_rowNumbers;
46
47//----------------------------------------------------------------------------------------------
51 // Input file name
52 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Load, ".irf"),
53 "Path to an Fullprof .irf file to load.");
54
55 // Output table workspace
56 auto wsprop = std::make_unique<WorkspaceProperty<API::ITableWorkspace>>("OutputTableWorkspace", "", Direction::Output,
58 declareProperty(std::move(wsprop), "Name of the output TableWorkspace containing "
59 "profile parameters or bank information. ");
60
61 // Use bank numbers as given in file
62 declareProperty(std::make_unique<PropertyWithValue<bool>>("UseBankIDsInFile", true, Direction::Input),
63 "Use bank IDs as given in file rather than ordinal number of bank."
64 "If the bank IDs in the file are not unique, it is advised to set this "
65 "to false.");
66
67 // Bank to import
68 declareProperty(std::make_unique<ArrayProperty<int>>("Banks"), "ID(s) of specified bank(s) to load, "
69 "The IDs are as specified by UseBankIDsInFile."
70 "Default is all banks contained in input .irf file.");
71
72 // Workspace to put parameters into. It must be a workspace group with one
73 // workpace per bank from the IRF file
76 "A workspace group with the instrument to which we add the "
77 "parameters from the Fullprof .irf file with one workspace "
78 "for each bank of the .irf file");
79
80 // Workspaces for each bank
81 declareProperty(std::make_unique<ArrayProperty<int>>("WorkspacesForBanks"),
82 "For each Fullprof bank,"
83 " the ID of the corresponding workspace in same order as the "
84 "Fullprof banks are specified. "
85 "ID=1 refers to the first workspace in the workspace group, "
86 "ID=2 refers to the second workspace and so on. "
87 "Default is all workspaces in numerical order."
88 "If default banks are specified, they too are taken to be in "
89 "numerical order");
90}
91
92//----------------------------------------------------------------------------------------------
96 // Get input
97 string datafile = getProperty("Filename");
98 const bool useBankIDsInFile = getProperty("UseBankIDsInFile");
99 vector<int> outputbankids = getProperty("Banks");
100 WorkspaceGroup_sptr wsg = getProperty("Workspace");
101 vector<int> outputwsids = getProperty("WorkspacesForBanks");
102
103 // Import data
104 vector<string> lines;
105 loadFile(datafile, lines);
106
107 // Get Prof number
108 int nProf = getProfNumber(lines);
109
110 // Examine bank information
111 vector<int> vec_bankinirf;
112 map<int, int> bankstartindexmap, bankendindexmap;
113 scanBanks(lines, useBankIDsInFile, vec_bankinirf, bankstartindexmap, bankendindexmap);
114 if (useBankIDsInFile)
115 sort(vec_bankinirf.begin(), vec_bankinirf.end());
116
117 for (auto bank : vec_bankinirf)
118 g_log.debug() << "Irf containing bank " << bank << ".\n";
119
120 // Bank-workspace correspondence
121 map<int, size_t> workspaceOfBank;
122
123 vector<int> vec_bankids; // bank IDs to output to table workspace
124
125 if (vec_bankinirf.empty()) {
126 throw runtime_error("No Bank is found in input file.");
127 } else if (outputbankids.empty()) {
128 vec_bankids = vec_bankinirf;
129 // If workspaces, set up Bank-Workpace correspondence
130 if (wsg)
131 createBankToWorkspaceMap(vec_bankids, outputwsids, workspaceOfBank);
132 } else {
133 // If workspaces, set up Bank-Workpace correspondece, before banks are
134 // sorted.
135 if (wsg)
136 createBankToWorkspaceMap(outputbankids, outputwsids, workspaceOfBank);
137
138 // Deal with banks
139 sort(outputbankids.begin(), outputbankids.end());
140 for (auto outputbankid : outputbankids) {
141 if (outputbankid < 0) {
142 g_log.warning() << "Input bank ID (" << outputbankid << ") is negative. It is not allowed and is ignored. "
143 << ".\n";
144 } else {
145 auto fiter = lower_bound(vec_bankinirf.begin(), vec_bankinirf.end(), outputbankid);
146 if (fiter == vec_bankinirf.end() || *fiter != outputbankid) {
147 // Specified bank ID does not exist.
148 stringstream errmsg;
149 errmsg << "Specified output bank (ID = " << outputbankid << ") cannot be found in input " << datafile
150 << ", which includes bank : ";
151 for (size_t i = 0; i < vec_bankinirf.size(); ++i) {
152 errmsg << vec_bankinirf[i];
153 if (i != vec_bankinirf.size() - 1)
154 errmsg << ",";
155 }
156 g_log.error(errmsg.str());
157 throw runtime_error(errmsg.str());
158 } else {
159 vec_bankids.emplace_back(outputbankid);
160 }
161 }
162 }
163 if (vec_bankids.empty()) {
164 g_log.error("There is no valid specified bank IDs for output.");
165 throw runtime_error("There is no valid specified bank IDs for output.");
166 }
167 }
168
169 // Parse .irf and export profile parameters
170 map<int, map<string, double>> bankparammap;
171 for (int bankid : vec_bankids) {
172 g_log.debug() << "Parse bank " << bankid << " of total " << vec_bankids.size() << ".\n";
173 map<string, double> parammap;
174 parseResolutionStrings(parammap, lines, useBankIDsInFile, bankid, bankstartindexmap[bankid],
175 bankendindexmap[bankid], nProf);
176 bankparammap.emplace(bankid, parammap);
177 }
178
179 // Generate output table workspace
180 API::ITableWorkspace_sptr outTabWs = genTableWorkspace(bankparammap);
181
182 if (!getPropertyValue("OutputTableWorkspace").empty()) {
183 // Output the output table workspace
184 setProperty("OutputTableWorkspace", outTabWs);
185 }
186
187 // If workspace, put parameters there
188 if (wsg) {
189 // First check that number of workspaces in group matches number of banks,
190 // if no WorkspacesForBanks is specified.
191 if ((outputwsids.empty()) && (wsg->size() != vec_bankids.size())) {
192 std::ostringstream mess;
193 mess << "Number of banks (" << vec_bankids.size() << ") does not match number of workspaces (" << wsg->size()
194 << ") in group. Parameters not put into workspaces.";
195 g_log.error(mess.str());
196 } else // Numbers match, so put parameters into workspaces.
197 {
199 for (size_t i = 0; i < vec_bankids.size(); ++i) {
200 int bankId = vec_bankids[i];
201 size_t wsId = workspaceOfBank[bankId];
202 Workspace_sptr wsi = wsg->getItem(wsId - 1);
203 auto workspace = std::dynamic_pointer_cast<MatrixWorkspace>(wsi);
204 // Get column from table workspace
205 API::Column_const_sptr OutTabColumn = outTabWs->getColumn(i + 1);
206 std::string parameterXMLString;
207 putParametersIntoWorkspace(OutTabColumn, workspace, nProf, parameterXMLString);
208
209 // Load the string into the workspace
210 Algorithm_sptr loadParamAlg = createChildAlgorithm("LoadParameterFile");
211 loadParamAlg->setProperty("ParameterXML", parameterXMLString);
212 loadParamAlg->setProperty("Workspace", workspace);
213 loadParamAlg->execute();
214 }
215 }
216 } else if (getPropertyValue("OutputTableWorkspace").empty()) {
217 // We don't know where to output
218 throw std::runtime_error("Either the OutputTableWorkspace or Workspace property must be set.");
219 }
220}
221
222//----------------------------------------------------------------------------------------------
227void LoadFullprofResolution::loadFile(const string &filename, vector<string> &lines) {
228 string line;
229
230 // the variable of type ifstream:
231 ifstream myfile(filename.c_str());
232
233 // check to see if the file is opened:
234 if (myfile.is_open()) {
235 // while there are still lines in the
236 // file, keep reading:
237 while (!myfile.eof()) {
238 // place the line from myfile into the
239 // line variable:
240 getline(myfile, line);
241
242 // display the line we gathered:
243 boost::algorithm::trim(line);
244 if (!line.empty())
245 lines.emplace_back(line);
246 }
247
248 // close the stream:
249 myfile.close();
250 } else {
251 stringstream errmsg;
252 errmsg << "Input .irf file " << filename << " cannot be open. ";
253 g_log.error(errmsg.str());
254 throw runtime_error(errmsg.str());
255 }
256}
257
258//----------------------------------------------------------------------------------------------
262int LoadFullprofResolution::getProfNumber(const vector<string> &lines) {
263 // Assume the NPROF number is on the second line
264 if (lines[1].find("NPROF") != string::npos) {
265 // Split line to get the NPROF number
266 size_t nStart = lines[1].find("NPROF");
267 size_t nEq = lines[1].find('=', nStart);
268 size_t nEnd = lines[1].find(' ', nStart); // Assume the NRPOF number is followed by space
269 if (nEq == string::npos || nEnd == string::npos)
270 return (-1);
271 size_t nNumber = nEq + 1;
272 return (boost::lexical_cast<int>(lines[1].substr(nNumber, nEnd - nNumber)));
273 }
274
275 return (0);
276}
277
278//----------------------------------------------------------------------------------------------
289void LoadFullprofResolution::scanBanks(const vector<string> &lines, const bool useFileBankIDs, vector<int> &banks,
290 map<int, int> &bankstartindexmap, map<int, int> &bankendindexmap) {
291 int startindex = -1;
292 int endindex;
293 int bankid = 0;
294 for (size_t i = 0; i < lines.size(); ++i) {
295 string line = lines[i];
296 if (line.find("Bank") != string::npos) {
297 // A new line found
298 if (startindex >= 0) {
299 // Previous line is in a bank range. Then finish the previous bank
300 // range
301 endindex = static_cast<int>(i) - 1;
302 bankstartindexmap.emplace(banks.back(), startindex);
303 bankendindexmap.emplace(banks.back(), endindex);
304 }
305
306 // Start the new pair
307 startindex = static_cast<int>(i);
308 endindex = -1;
309
310 // Get bank ID
311 if (useFileBankIDs) { // Get bank ID from line
312 vector<string> level1s;
313 boost::split(level1s, line, boost::is_any_of("Bank"));
314 vector<string> level2s;
315 string bankterm = level1s.back();
316 boost::algorithm::trim(bankterm);
317 boost::split(level2s, bankterm, boost::is_any_of(" "));
318 bankid = std::stoi(level2s[0]);
319 } else { // Get bank ID as ordinal number of bank
320 bankid++;
321 }
322 banks.emplace_back(bankid);
323 }
324 }
325 if (startindex >= 0) {
326 endindex = static_cast<int>(lines.size()) - 1;
327 bankstartindexmap.emplace(banks.back(), startindex);
328 bankendindexmap.emplace(banks.back(), endindex);
329 }
330
331 g_log.debug() << "[DB1112] Number of bank IDs = " << banks.size() << ", "
332 << "Number of ranges = " << bankstartindexmap.size() << '\n';
333 for (auto &bank : banks) {
334 g_log.debug() << "Bank " << bank << " From line " << bankstartindexmap[bank] << " to " << bankendindexmap[bank]
335 << '\n';
336 }
337}
338
339//----------------------------------------------------------------------------------------------
352void LoadFullprofResolution::parseResolutionStrings(map<string, double> &parammap, const vector<string> &lines,
353 const bool useFileBankIDs, int bankid, int startlineindex,
354 int endlineindex, int profNumber) {
355 string bankline = lines[startlineindex];
356 double cwl;
357 int tmpbankid;
358 parseBankLine(bankline, cwl, tmpbankid);
359 if (tmpbankid != -1) {
360 g_log.debug() << "Found CWL = " << cwl << ", Bank ID = " << tmpbankid << "\n";
361 } else {
362 g_log.warning() << "No CWL found for bank " << bankid;
363 tmpbankid = bankid;
364 }
365 if (useFileBankIDs && (bankid != tmpbankid)) {
366 stringstream errss;
367 errss << "Input bank ID (" << bankid << ") is not same as the bank ID (" << tmpbankid
368 << ") found in the specified region from input. ";
369 throw runtime_error(errss.str());
370 }
371
372 parammap["NPROF"] = profNumber;
373 parammap["CWL"] = cwl;
374
375 for (int i = startlineindex + 1; i <= endlineindex; ++i) {
376 string line = lines[i];
377
378 // Skip information line
379 if (line[0] == '!')
380 continue;
381
382 // skip NPROF line, which is processed by getProfNumber
383 if (line.find("NPROF") != string::npos)
384 continue;
385
386 // Parse
387 g_log.debug() << "Parse Line " << i << "\t\t" << line << "\n";
388
389 if (boost::starts_with(line, "TOFRG")) {
390 // TOFRG tof-min step tof-max
391 vector<string> terms;
392 boost::split(terms, line, boost::is_any_of(" "), boost::token_compress_on);
393 if (terms.size() != 4) {
394 stringstream errmsg;
395 errmsg << "Line TOFRG has " << terms.size() << " terms. Different from 4 terms in definition.";
396 g_log.error(errmsg.str());
397 throw runtime_error(errmsg.str());
398 } else {
399 parammap["tof-min"] = parseDoubleValue(terms[1], "tof-min");
400 parammap["step"] = parseDoubleValue(terms[2], "step");
401 parammap["tof-max"] = parseDoubleValue(terms[3], "tof-max");
402 }
403 } else if (boost::starts_with(line, "D2TOF")) {
404 // D2TOF Dtt1 Dtt2 Zero
405 vector<string> terms;
406 boost::split(terms, line, boost::is_any_of(" "), boost::token_compress_on);
407 if (terms.size() != 2 && terms.size() != 4) {
408 stringstream errmsg;
409 errmsg << "Line D2TOF has " << terms.size() << " terms. Different from 2/4 terms in definition.";
410 g_log.error(errmsg.str());
411 throw runtime_error(errmsg.str());
412 } else {
413 parammap["Dtt1"] = parseDoubleValue(terms[1], "Dtt1");
414 if (terms.size() == 4) {
415 parammap["Dtt2"] = parseDoubleValue(terms[2], "Dtt2");
416 parammap["Zero"] = parseDoubleValue(terms[3], "Zero");
417 } else {
418 parammap["Dtt2"] = 0.0;
419 parammap["Zero"] = 0.0;
420 }
421 }
422 } // "D2TOF"
423 else if (boost::starts_with(line, "ZD2TOF")) {
424 vector<string> terms;
425 boost::split(terms, line, boost::is_any_of(" "), boost::token_compress_on);
426 if (terms.size() != 3) {
427 stringstream errmsg;
428 errmsg << "Line ZD2TOF has " << terms.size() << " terms. Different from 4 terms in definition.";
429 g_log.error(errmsg.str());
430 throw runtime_error(errmsg.str());
431 } else {
432 parammap["Zero"] = parseDoubleValue(terms[1], "Zero");
433 parammap["Dtt1"] = parseDoubleValue(terms[2], "Dtt1");
434 parammap["Dtt2"] = 0.;
435 }
436 } // "ZD2TOF"
437 else if (boost::starts_with(line, "D2TOT")) {
438 vector<string> terms;
439 boost::split(terms, line, boost::is_any_of(" "), boost::token_compress_on);
440 if (terms.size() != 6) {
441 stringstream errmsg;
442 errmsg << "Line TOFRG has " << terms.size() << " terms. Different from 4 terms in definition.";
443 g_log.error(errmsg.str());
444 throw runtime_error(errmsg.str());
445 } else {
446 parammap["Dtt1t"] = parseDoubleValue(terms[1], "Dtt1t");
447 parammap["Dtt2t"] = parseDoubleValue(terms[2], "Dtt2t");
448 parammap["Tcross"] = parseDoubleValue(terms[3], "Tcross");
449 parammap["Width"] = parseDoubleValue(terms[4], "Width");
450 parammap["Zerot"] = parseDoubleValue(terms[5], "Zerot");
451 }
452 } // "D2TOT"
453 else if (boost::starts_with(line, "ZD2TOT")) {
454 vector<string> terms;
455 boost::split(terms, line, boost::is_any_of(" "), boost::token_compress_on);
456 if (terms.size() != 6) {
457 stringstream errmsg;
458 errmsg << "Line TOFRG has " << terms.size() << " terms. Different from 4 terms in definition.";
459 g_log.error(errmsg.str());
460 throw runtime_error(errmsg.str());
461 } else {
462 parammap["Zerot"] = parseDoubleValue(terms[1], "Zerot");
463 parammap["Dtt1t"] = parseDoubleValue(terms[2], "Dtt1t");
464 parammap["Dtt2t"] = parseDoubleValue(terms[3], "Dtt2t");
465 parammap["Tcross"] = parseDoubleValue(terms[4], "Tcross");
466 parammap["Width"] = parseDoubleValue(terms[5], "Width");
467 }
468 } // "ZD2TOT"
469 else if (boost::starts_with(line, "TWOTH")) {
470 vector<string> terms;
471 boost::split(terms, line, boost::is_any_of(" "), boost::token_compress_on);
472 if (terms.size() != 2) {
473 stringstream errmsg;
474 errmsg << "Line TOFRG has " << terms.size() << " terms. Different from 4 terms in definition.";
475 g_log.error(errmsg.str());
476 throw runtime_error(errmsg.str());
477 } else {
478 parammap["twotheta"] = parseDoubleValue(terms[1], "twotheta");
479 }
480 } // "TWOTH"
481 else if (boost::starts_with(line, "SIGMA")) {
482 vector<string> terms;
483 boost::split(terms, line, boost::is_any_of(" "), boost::token_compress_on);
484 if (terms.size() != 4) {
485 stringstream errmsg;
486 errmsg << "Line TOFRG has " << terms.size() << " terms. Different from 4 terms in definition.";
487 g_log.error(errmsg.str());
488 throw runtime_error(errmsg.str());
489 } else {
490 parammap["Sig2"] = sqrt(parseDoubleValue(terms[1], "Sig2"));
491 parammap["Sig1"] = sqrt(parseDoubleValue(terms[2], "Sig1"));
492 parammap["Sig0"] = sqrt(parseDoubleValue(terms[3], "Sig0"));
493 }
494 } // "SIGMA"
495 else if (boost::starts_with(line, "GAMMA")) {
496 vector<string> terms;
497 boost::split(terms, line, boost::is_any_of(" "), boost::token_compress_on);
498 if (terms.size() != 4) {
499 stringstream errmsg;
500 errmsg << "Line TOFRG has " << terms.size() << " terms. Different from 4 terms in definition.";
501 g_log.error(errmsg.str());
502 throw runtime_error(errmsg.str());
503 } else {
504 parammap["Gam2"] = parseDoubleValue(terms[1], "Gam2");
505 parammap["Gam1"] = parseDoubleValue(terms[2], "Gam1");
506 parammap["Gam0"] = parseDoubleValue(terms[3], "Gam0");
507 }
508 } // "GAMMA"
509 else if (boost::starts_with(line, "ALFBE")) {
510 // ALFBE alph0 beta0 alph1 beta1
511 vector<string> terms;
512 boost::split(terms, line, boost::is_any_of(" "), boost::token_compress_on);
513 if (terms.size() != 5) {
514 stringstream errmsg;
515 errmsg << "Line ALFBE has " << terms.size() << " terms. Different from 4 terms in definition.";
516 g_log.error(errmsg.str());
517 throw runtime_error(errmsg.str());
518 } else {
519 parammap["Alph0"] = parseDoubleValue(terms[1], "Alph0");
520 parammap["Beta0"] = parseDoubleValue(terms[2], "Beta0");
521 parammap["Alph1"] = parseDoubleValue(terms[3], "Alph1");
522 parammap["Beta1"] = parseDoubleValue(terms[4], "Beta1");
523 }
524 } // "ALFBE"
525 else if (boost::starts_with(line, "ALFBT")) {
526 vector<string> terms;
527 boost::split(terms, line, boost::is_any_of(" "), boost::token_compress_on);
528 if (terms.size() != 5) {
529 stringstream errmsg;
530 errmsg << "Line ALFBT has " << terms.size() << " terms. Different from 4 terms in definition.";
531 g_log.error(errmsg.str());
532 throw runtime_error(errmsg.str());
533 } else {
534 parammap["Alph0t"] = parseDoubleValue(terms[1], "Alph0t");
535 parammap["Beta0t"] = parseDoubleValue(terms[2], "Beta0t");
536 parammap["Alph1t"] = parseDoubleValue(terms[3], "Alph1t");
537 parammap["Beta1t"] = parseDoubleValue(terms[4], "Beta1t");
538 }
539 } // "ALFBT"
540 else if (boost::starts_with(line, "END")) {
541 // Ignore END line
542 g_log.debug("END line of bank.");
543 } else {
544 g_log.warning() << "Line '" << line << "' is not processed.\n";
545 } // END -IF StartWith
546
547 } // For-all-line
548}
549
550//----------------------------------------------------------------------------------------------
553void LoadFullprofResolution::parseBankLine(string line, double &cwl, int &bankid) {
554 // 1. Split along 'Bank'
555 std::vector<std::string> v;
556 iter_split(v, line, boost::algorithm::first_finder("Bank"));
557
558 // 2. Split the rest around CWL if there is
559 string infostr = v[1];
560 boost::algorithm::trim(infostr);
561
562 cwl = -1.0;
563 bankid = -1;
564
565 if (infostr.find("CWL") != string::npos) {
566 // There is CWL
567 v.clear();
568 iter_split(v, infostr, boost::algorithm::first_finder("CWL"));
569
570 // Bank ID
571 bankid = std::stoi(v[0]);
572
573 // CWL
574 infostr = v[1];
575 v.clear();
576 boost::split(v, infostr, boost::is_any_of("=A"));
577 for (size_t i = 0; i < v.size(); ++i) {
578 g_log.debug() << "Last CWL splitted. Term " << i << ": \t\t"
579 << "'" << v[i] << "'\n";
580 string candidate = v[i];
581 boost::algorithm::trim(candidate);
582 if (!candidate.empty()) {
583 cwl = parseDoubleValue(candidate);
584 break;
585 }
586 }
587 }
588}
589
590double LoadFullprofResolution::parseDoubleValue(const std::string &value, const std::string &label) {
591 if (!value.empty()) {
592 try {
593 return std::stod(value);
594 } catch (...) {
595 std::stringstream msg;
596 msg << "Failed to convert \"" << value << "\" to a double";
597 if (!label.empty()) {
598 msg << " for \"" << label << "\"";
599 }
600 msg << " using 0. instead";
601 g_log.warning(msg.str());
602 }
603 }
604 return 0.;
605}
606
607//----------------------------------------------------------------------------------------------
610TableWorkspace_sptr LoadFullprofResolution::genTableWorkspace(map<int, map<string, double>> bankparammap) {
611 g_log.notice() << "Start to generate table workspace ...."
612 << ".\n";
613
614 // Retrieve some information
615 size_t numbanks = bankparammap.size();
616 if (numbanks == 0)
617 throw runtime_error("Unable to generate a table from an empty map!");
618
619 auto bankmapiter = bankparammap.begin();
620 size_t numparams = bankmapiter->second.size();
621
622 // vector of all parameter name
623 vector<string> vec_parname;
624 vector<int> vec_bankids;
625
626 map<string, double>::iterator parmapiter;
627 for (parmapiter = bankmapiter->second.begin(); parmapiter != bankmapiter->second.end(); ++parmapiter) {
628 string parname = parmapiter->first;
629 vec_parname.emplace_back(parname);
630 }
631
632 for (bankmapiter = bankparammap.begin(); bankmapiter != bankparammap.end(); ++bankmapiter) {
633 int bankid = bankmapiter->first;
634 vec_bankids.emplace_back(bankid);
635 }
636
637 g_log.debug() << "[DBx240] Number of imported parameters is " << numparams
638 << ", Number of banks = " << vec_bankids.size() << "."
639 << "\n";
640
641 // Create TableWorkspace
642 auto tablews = std::make_shared<TableWorkspace>();
643
644 // set columns :
645 // Any 2 columns cannot have the same name.
646 tablews->addColumn("str", "Name");
647 for (size_t i = 0; i < numbanks; ++i) {
648 stringstream colnamess;
649 int bankid = vec_bankids[i];
650 colnamess << "Value_" << bankid;
651 tablews->addColumn("double", colnamess.str());
652 }
653
654 g_log.debug() << "Number of column = " << tablews->columnCount() << ".\n";
655
656 // add BANK ID row
657 TableRow newrow = tablews->appendRow();
658 newrow << "BANK";
659 for (size_t i = 0; i < numbanks; ++i)
660 newrow << static_cast<double>(vec_bankids[i]);
661
662 g_log.debug() << "Number of row now = " << tablews->rowCount() << ".\n";
663
664 // add profile parameter rows
665 for (size_t i = 0; i < numparams; ++i) {
666 newrow = tablews->appendRow();
667
668 string parname = vec_parname[i];
669 newrow << parname;
670
671 for (size_t j = 0; j < numbanks; ++j) {
672 int bankid = vec_bankids[j];
673
674 // Locate map of bank 'bankid'
675 map<int, map<string, double>>::iterator bpmapiter;
676 bpmapiter = bankparammap.find(bankid);
677 if (bpmapiter == bankparammap.end()) {
678 throw runtime_error("Bank cannot be found in map.");
679 }
680
681 // Locate parameter
682 parmapiter = bpmapiter->second.find(parname);
683 if (parmapiter == bpmapiter->second.end()) {
684 throw runtime_error("Parameter cannot be found in a bank's map.");
685 } else {
686 double pvalue = parmapiter->second;
687 newrow << pvalue;
688 }
689
690 } // END(j)
691 } // END(i)
692
693 return tablews;
694}
695
696//----------------------------------------------------------------------------------------------
705void LoadFullprofResolution::createBankToWorkspaceMap(const std::vector<int> &banks, const std::vector<int> &workspaces,
706 std::map<int, size_t> &workspaceOfBank) {
707 if (workspaces.empty()) {
708 for (size_t i = 0; i < banks.size(); i++) {
709 workspaceOfBank.emplace(banks[i], i + 1);
710 }
711 } else {
712 for (size_t i = 0; i < banks.size(); i++) {
713 workspaceOfBank.emplace(banks[i], workspaces[i]);
714 }
715 }
716}
717
718//----------------------------------------------------------------------------------------------
728 const API::MatrixWorkspace_sptr &ws, int nProf,
729 std::string &parameterXMLString) {
730
731 // Get instrument name from matrix workspace
732 std::string instrumentName = ws->getInstrument()->getName();
733
734 // Convert table workspace column into DOM XML document
735 // Set up writer to Paremeter file
736 DOMWriter writer;
737 writer.setNewLine("\n");
738 writer.setOptions(XMLWriter::PRETTY_PRINT);
739
740 // Get current time
741 Types::Core::DateAndTime date = Types::Core::DateAndTime::getCurrentTime();
742 std::string ISOdate = date.toISO8601String();
743 std::string ISOdateShort = ISOdate.substr(0, 19); // Remove fraction of seconds
744
745 // Create document
746 AutoPtr<Document> mDoc = new Document();
747 AutoPtr<Element> rootElem = mDoc->createElement("parameter-file");
748 rootElem->setAttribute("date", ISOdateShort);
749 mDoc->appendChild(rootElem);
750
751 // Add instrument
752 AutoPtr<Element> instrumentElem = mDoc->createElement("component-link");
753 instrumentElem->setAttribute("name", instrumentName);
754 rootElem->appendChild(instrumentElem);
755 if (nProf == 9) // put parameters into BackToBackExponential function
756 {
757 addBBX_S_Parameters(column, mDoc, instrumentElem);
758 addBBX_A_Parameters(column, mDoc, instrumentElem);
759 addBBX_B_Parameters(column, mDoc, instrumentElem);
760 } else // Assume IkedaCarpenter PV
761 {
762 addALFBEParameter(column, mDoc, instrumentElem, "Alph0");
763 addALFBEParameter(column, mDoc, instrumentElem, "Beta0");
764 addALFBEParameter(column, mDoc, instrumentElem, "Alph1");
765 addALFBEParameter(column, mDoc, instrumentElem, "Beta1");
766 addSigmaParameters(column, mDoc, instrumentElem);
767 addGammaParameters(column, mDoc, instrumentElem);
768 }
769
770 // Convert DOM XML document into string
771 std::ostringstream outFile;
772 writer.writeNode(outFile, mDoc);
773 parameterXMLString = outFile.str();
774
775 // Useful code for testing upgrades commented out for production use
776 // std::ofstream outfileDebug("C:/Temp/test4_fullprof.xml");
777 // outfileDebug << parameterXMLString;
778 // outfileDebug.close();
779}
780
781/* Add an Ikeda Carpenter PV ALFBE parameter to the XML document according to
782 *the table workspace
783 *
784 * paramName is the name of the parameter as it appears in the table workspace
785 */
786void LoadFullprofResolution::addALFBEParameter(const API::Column_const_sptr &column, Poco::XML::Document *mDoc,
787 Element *parent, const std::string &paramName) {
788 AutoPtr<Element> parameterElem = mDoc->createElement("parameter");
789 parameterElem->setAttribute("name", getXMLParameterName(paramName));
790 parameterElem->setAttribute("type", "fitting");
791
792 AutoPtr<Element> formulaElem = mDoc->createElement("formula");
793 formulaElem->setAttribute("eq", getXMLEqValue(column, paramName));
794 if (paramName != "Beta1")
795 formulaElem->setAttribute("result-unit", "TOF");
796 parameterElem->appendChild(formulaElem);
797
798 AutoPtr<Element> fixedElem = mDoc->createElement("fixed");
799 parameterElem->appendChild(fixedElem);
800
801 parent->appendChild(parameterElem);
802}
803
804/* Add a set of Ikeda Carpenter PV SIGMA parameters to the XML document
805 * according to the table workspace
806 * for the bank at the given column of the table workspace
807 */
808void LoadFullprofResolution::addSigmaParameters(const API::Column_const_sptr &column, Poco::XML::Document *mDoc,
809 Poco::XML::Element *parent) {
810 AutoPtr<Element> parameterElem = mDoc->createElement("parameter");
811 parameterElem->setAttribute("name", "IkedaCarpenterPV:SigmaSquared");
812 parameterElem->setAttribute("type", "fitting");
813
814 AutoPtr<Element> formulaElem = mDoc->createElement("formula");
815 std::string eqValue = getXMLSquaredEqValue(column, "Sig1") + "*centre^2+" + getXMLSquaredEqValue(column, "Sig0");
816 formulaElem->setAttribute("eq", eqValue);
817 formulaElem->setAttribute("unit", "dSpacing");
818 formulaElem->setAttribute("result-unit", "TOF^2");
819 parameterElem->appendChild(formulaElem);
820
821 parent->appendChild(parameterElem);
822}
823
824/* Add a set of Ikeda Carpenter PV GAMMA parameters to the XML document
825 * according to the table workspace
826 * for the bank at the given column of the table workspace
827 */
828void LoadFullprofResolution::addGammaParameters(const API::Column_const_sptr &column, Poco::XML::Document *mDoc,
829 Poco::XML::Element *parent) {
830 AutoPtr<Element> parameterElem = mDoc->createElement("parameter");
831 parameterElem->setAttribute("name", "IkedaCarpenterPV:Gamma");
832 parameterElem->setAttribute("type", "fitting");
833
834 AutoPtr<Element> formulaElem = mDoc->createElement("formula");
835 std::string eqValue = getXMLEqValue(column, "Gam1") + "*centre";
836 formulaElem->setAttribute("eq", eqValue);
837 formulaElem->setAttribute("unit", "dSpacing");
838 formulaElem->setAttribute("result-unit", "TOF");
839 parameterElem->appendChild(formulaElem);
840
841 parent->appendChild(parameterElem);
842}
843
844/* Add a set of BackToBackExponential S parameters to the XML document according
845 * to the table workspace
846 * for the bank at the given column of the table workspace
847 */
848void LoadFullprofResolution::addBBX_S_Parameters(const API::Column_const_sptr &column, Poco::XML::Document *mDoc,
849 Poco::XML::Element *parent) {
850 AutoPtr<Element> parameterElem = mDoc->createElement("parameter");
851 parameterElem->setAttribute("name", "BackToBackExponential:S");
852 parameterElem->setAttribute("type", "fitting");
853
854 AutoPtr<Element> formulaElem = mDoc->createElement("formula");
855 std::string eqValue = "sqrt(" + getXMLSquaredEqValue(column, "Sig2") + "*centre^4 + " +
856 getXMLSquaredEqValue(column, "Sig1") + "*centre^2 + " + getXMLSquaredEqValue(column, "Sig0") +
857 ")";
858 formulaElem->setAttribute("eq", eqValue);
859 formulaElem->setAttribute("unit", "dSpacing");
860 formulaElem->setAttribute("result-unit", "TOF");
861 parameterElem->appendChild(formulaElem);
862
863 parent->appendChild(parameterElem);
864}
865
866/* Add a set of BackToBackExponential A parameters to the XML document according
867 * to the table workspace
868 * for the bank at the given column of the table workspace
869 */
870void LoadFullprofResolution::addBBX_A_Parameters(const API::Column_const_sptr &column, Poco::XML::Document *mDoc,
871 Poco::XML::Element *parent) {
872 AutoPtr<Element> parameterElem = mDoc->createElement("parameter");
873 parameterElem->setAttribute("name", "BackToBackExponential:A");
874 parameterElem->setAttribute("type", "fitting");
875
876 AutoPtr<Element> formulaElem = mDoc->createElement("formula");
877 std::string eqValue = "(" + getXMLEqValue(column, "Alph1") + "/centre) + " + getXMLEqValue(column, "Alph0");
878 formulaElem->setAttribute("eq", eqValue);
879 formulaElem->setAttribute("unit", "dSpacing");
880 formulaElem->setAttribute("result-unit", "TOF");
881 parameterElem->appendChild(formulaElem);
882
883 AutoPtr<Element> fixedElem = mDoc->createElement("fixed");
884 parameterElem->appendChild(fixedElem);
885
886 parent->appendChild(parameterElem);
887}
888
889/* Add a set of BackToBackExponential B parameters to the XML document according
890 * to the table workspace
891 * for the bank at the given column of the table workspace
892 */
893void LoadFullprofResolution::addBBX_B_Parameters(const API::Column_const_sptr &column, Poco::XML::Document *mDoc,
894 Poco::XML::Element *parent) {
895 AutoPtr<Element> parameterElem = mDoc->createElement("parameter");
896 parameterElem->setAttribute("name", "BackToBackExponential:B");
897 parameterElem->setAttribute("type", "fitting");
898
899 AutoPtr<Element> formulaElem = mDoc->createElement("formula");
900 std::string eqValue = "(" + getXMLEqValue(column, "Beta1") + "/centre^4) + " + getXMLEqValue(column, "Beta0");
901 formulaElem->setAttribute("eq", eqValue);
902 formulaElem->setAttribute("unit", "dSpacing");
903 formulaElem->setAttribute("result-unit", "TOF");
904 parameterElem->appendChild(formulaElem);
905
906 AutoPtr<Element> fixedElem = mDoc->createElement("fixed");
907 parameterElem->appendChild(fixedElem);
908
909 parent->appendChild(parameterElem);
910}
911
912/*
913 * Get the XML name of a parameter given its Table Workspace name
914 */
915std::string LoadFullprofResolution::getXMLParameterName(const std::string &name) {
916 // Only used for ALFBE parameters
917 std::string prefix = "IkedaCarpenterPV:";
918 if (name == "Alph0")
919 return prefix + "Alpha0";
920 if (name == "Beta0")
921 return prefix + "Beta0";
922 if (name == "Alph1")
923 return prefix + "Alpha1";
924 if (name == "Beta1")
925 return prefix + "Kappa";
926 return "?" + name;
927}
928
929/*
930 * Get the value string to put in the XML eq attribute of the formula element of
931 * the paramenter element
932 * given the name of the parameter in the table workspace.
933 */
934std::string LoadFullprofResolution::getXMLEqValue(const API::Column_const_sptr &column, const std::string &name) {
935 size_t paramNumber = LoadFullprofResolution::m_rowNumbers[name];
936 // API::Column_const_sptr column = tablews->getColumn( columnIndex );
937 double eqValue = column->cell<double>(paramNumber);
938 return boost::lexical_cast<std::string>(eqValue);
939}
940
941/*
942 * Get the value string to put in the XML eq attribute of the formula element of
943 * the SQUARED paramenter element
944 * given the name of the parameter in the table workspace.
945 */
947 const std::string &name) {
948 size_t paramNumber = LoadFullprofResolution::m_rowNumbers[name];
949 // API::Column_const_sptr column = tablews->getColumn( columnIndex );
950 double eqValue = column->cell<double>(paramNumber);
951 return boost::lexical_cast<std::string>(eqValue * eqValue);
952}
953
954/* This function fills in a list of the row numbers starting 0 of the parameters
955 in the table workspace, so one can find the position in a column of
956 the value of the given parameter.
957*/
959 std::map<std::string, size_t> &parammap) {
960 parammap.clear();
961
962 size_t numrows = tablews->rowCount();
963 for (size_t i = 0; i < numrows; ++i) {
964 TableRow row = tablews->getRow(i);
965 std::string name;
966 row >> name;
967 parammap.emplace(name, i);
968 }
969}
970
971} // namespace Mantid::DataHandling
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
double value
The value of the point.
Definition: FitMW.cpp:51
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
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
@ Load
allowed here which will be passed to the algorithm
Definition: FileProperty.h:52
TableRow represents a row in a TableWorkspace.
Definition: TableRow.h:39
A property class for workspaces.
LoadFullprofResolution : Load Fullprof resolution (.irf) file to TableWorkspace(s)
void loadFile(const std::string &filename, std::vector< std::string > &lines)
Load file to a vector of strings.
static std::string getXMLParameterName(const std::string &name)
static void getTableRowNumbers(const API::ITableWorkspace_sptr &tablews, std::map< std::string, size_t > &parammap)
Get row numbers of the parameters in the table workspace.
static void addALFBEParameter(const API::Column_const_sptr &, Poco::XML::Document *mDoc, Poco::XML::Element *parent, const std::string &paramName)
Add an Ikeda-Carpenter PV ALFBE parameter.
void parseResolutionStrings(std::map< std::string, double > &parammap, const std::vector< std::string > &lines, const bool useFileBankIDs, int bankid, int startlineindex, int endlineindex, int profNumber)
Parse .irf file to a map.
void exec() override
Implement abstract Algorithm methods.
static std::string getXMLEqValue(const API::Column_const_sptr &, const std::string &name)
Get value for XML eq attribute for parameter.
static void addGammaParameters(const API::Column_const_sptr &, Poco::XML::Document *mDoc, Poco::XML::Element *parent)
Add set of Ikeda-Carpenter PV Gamma parameters.
static std::string getXMLSquaredEqValue(const API::Column_const_sptr &column, const std::string &name)
Get value for XML eq attribute for squared parameter.
const std::string name() const override
Algorithm's name for identification overriding a virtual method.
static void putParametersIntoWorkspace(const API::Column_const_sptr &, const API::MatrixWorkspace_sptr &ws, int nProf, std::string &parameterXMLString)
Put parameters into a matrix workspace.
void init() override
Implement abstract Algorithm methods.
DataObjects::TableWorkspace_sptr genTableWorkspace(std::map< int, std::map< std::string, double > > bankparammap)
Generate output workspace.
void scanBanks(const std::vector< std::string > &lines, const bool useFileBankIDs, std::vector< int > &banks, std::map< int, int > &bankstartindexmap, std::map< int, int > &bankendindexmap)
Scan imported file for bank information.
void parseBankLine(std::string line, double &cwl, int &bankid)
Parse a line containig bank information.
static void addBBX_B_Parameters(const API::Column_const_sptr &, Poco::XML::Document *mDoc, Poco::XML::Element *parent)
Add set of BackToBackExponential B parameters.
static void addSigmaParameters(const API::Column_const_sptr &, Poco::XML::Document *mDoc, Poco::XML::Element *parent)
Add set of Ikeda-Carpenter PV Sigma parameters.
static void addBBX_A_Parameters(const API::Column_const_sptr &, Poco::XML::Document *mDoc, Poco::XML::Element *parent)
Add set of BackToBackExponential A parameters.
static void addBBX_S_Parameters(const API::Column_const_sptr &, Poco::XML::Document *mDoc, Poco::XML::Element *parent)
Add set of BackToBackExponential S parameters.
double parseDoubleValue(const std::string &value, const std::string &label=std::string())
Parse a value and prints warning if something is wrong.
int getProfNumber(const std::vector< std::string > &lines)
Get the NPROF number.
static void createBankToWorkspaceMap(const std::vector< int > &banks, const std::vector< int > &workspaces, std::map< int, size_t > &workspaceOfBank)
Create Bank to Workspace Correspondence.
static std::map< std::string, size_t > m_rowNumbers
Place to store the row numbers.
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void debug(const std::string &msg)
Logs at debug level.
Definition: Logger.cpp:114
void notice(const std::string &msg)
Logs at notice level.
Definition: Logger.cpp:95
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
The concrete, templated class for properties.
std::shared_ptr< WorkspaceGroup > WorkspaceGroup_sptr
shared pointer to Mantid::API::WorkspaceGroup
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
Definition: Workspace_fwd.h:20
std::shared_ptr< const Column > Column_const_sptr
Definition: Column.h:229
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
Definition: Algorithm.h:61
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< TableWorkspace > TableWorkspace_sptr
shared pointer to Mantid::DataObjects::TableWorkspace
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
std::shared_ptr< Instrument > Instrument_sptr
Shared pointer to an instrument object.
Helper class which provides the Collimation Length for SANS instruments.
STL namespace.
@ InOut
Both an input & output workspace.
Definition: Property.h:55
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54