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