musrfit 1.10.0
msr2msr.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 msr2msr.cpp
4
5 Author: Andreas Suter
6 e-mail: andreas.suter@psi.ch
7
8***************************************************************************/
9
10/***************************************************************************
11 * Copyright (C) 2007-2026 by Andreas Suter *
12 * andreas.suter@psi.ch *
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 * This program is distributed in the hope that it will be useful, *
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
22 * GNU General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU General Public License *
25 * along with this program; if not, write to the *
26 * Free Software Foundation, Inc., *
27 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
28 ***************************************************************************/
29
30#include <iostream>
31#include <fstream>
32#include <filesystem>
33#include <string>
34
35#include <cctype>
36#include <cstring>
37#include <cstdlib>
38
39#include <TString.h>
40
41#include "PStringUtils.h"
42
43//-------------------------------------------------------------
44// msr block header tags
45#define MSR_TAG_TITLE 0
46#define MSR_TAG_FITPARAMETER 1
47#define MSR_TAG_THEORY 2
48#define MSR_TAG_FUNCTIONS 3
49#define MSR_TAG_RUN 4
50#define MSR_TAG_COMMANDS 5
51#define MSR_TAG_PLOT 6
52#define MSR_TAG_STATISTIC 7
53#define MSR_TAG_NO_BLOCK 8
54
55//-------------------------------------------------------------
56// msr theory tags
57#define MSR_THEORY_INTERN_FLD 0
58#define MSR_THEORY_INTERN_BESSEL 1
59
60//--------------------------------------------------------------------------
65{
66 std::cout << std::endl << "usage: msr2msr <msr-file-in> <msr-file-out> | [--help]";
67 std::cout << std::endl << " <msr-file-in> : input msr-file";
68 std::cout << std::endl << " <msr-file-out>: converted msr-output-file";
69 std::cout << std::endl << " if the <msr-file-in> is already in the 2008 format";
70 std::cout << std::endl << " the output file will be identical to the input file.";
71 std::cout << std::endl << std::endl;
72}
73
74//--------------------------------------------------------------------------
85bool msr2msr_run(char *str, const std::size_t size)
86{
87 // not the RUN line itself, hence nothing to be done
88 if (!strstr(str, "RUN"))
89 return true;
90
91 TString run(str);
92 TString line(str);
93
94 // for filtering
95 run.ToUpper();
96
97 // remove run comment, i.e. (name ...
98 Ssiz_t idx = line.Index("(");
99 if (idx > 0)
100 line.Remove(idx);
101
102 // tokenize run
103 std::vector<std::string> tokens = PStringUtils::Split(line.Data(), " \t");
104 if (tokens.size() < 4) {
105 std::cout << std::endl << "**ERROR**: Something is wrong with the RUN block header:";
106 std::cout << std::endl << " >> " << str;
107 std::cout << std::endl << " >> no <msr-file-out> is created";
108 std::cout << std::endl;
109 return false;
110 }
111
112 if (tokens.size() == 5) { // already a new msr file, do only add the proper run comment
113 snprintf(str, size, "%s (name beamline institute data-file-format)", line.Data());
114 return true;
115 }
116
117 if (run.Contains("NEMU")) {
118 snprintf(str, size, "RUN %s MUE4 PSI WKM (name beamline institute data-file-format)", tokens[1].c_str());
119 } else if (run.Contains("PSI")) {
120 snprintf(str, size, "RUN %s %s PSI PSI-BIN (name beamline institute data-file-format)",
121 tokens[1].c_str(), tokens[2].c_str());
122 } else if (run.Contains("TRIUMF")) {
123 snprintf(str, size, "RUN %s %s TRIUMF MUD (name beamline institute data-file-format)",
124 tokens[1].c_str(), tokens[2].c_str());
125 } else if (run.Contains("RAL")) {
126 snprintf(str, size, "RUN %s %s RAL NEXUS (name beamline institute data-file-format)",
127 tokens[1].c_str(), tokens[2].c_str());
128 }
129
130 return true;
131}
132
133//--------------------------------------------------------------------------
145bool msr2msr_param(char *str)
146{
147 // check for comment header which needs to be replaced
148 if (strstr(str, "Nr.")) {
149 strcpy(str, "# No Name Value Step Pos_Error Boundaries");
150 return true;
151 }
152
153 // handle parameter line
154 TString line(str);
155 char sstr[256];
156 char spaces[256];
157
158 std::vector<std::string> tokens = PStringUtils::Split(line.Data(), " \t");
159 std::size_t noTokens = tokens.size();
160 if (noTokens == 4) {
161 // number
162 snprintf(sstr, sizeof(sstr), "%10s", tokens[0].c_str());
163 // name
164 strcat(sstr, " ");
165 strcat(sstr, tokens[1].c_str());
166 memset(spaces, 0, sizeof(spaces));
167 memset(spaces, ' ', 12-strlen(tokens[1].c_str()));
168 strcat(sstr, spaces);
169 // value
170 strcat(sstr, tokens[2].c_str());
171 if (strlen(tokens[2].c_str()) < 10) {
172 memset(spaces, 0, sizeof(spaces));
173 memset(spaces, ' ', 10-strlen(tokens[2].c_str()));
174 strcat(sstr, spaces);
175 } else {
176 strcat(sstr, " ");
177 }
178 // step
179 strcat(sstr, tokens[3].c_str());
180 if (strlen(tokens[3].c_str()) < 12) {
181 memset(spaces, 0, sizeof(spaces));
182 memset(spaces, ' ', 12-strlen(tokens[3].c_str()));
183 strcat(sstr, spaces);
184 } else {
185 strcat(sstr, " ");
186 }
187 strcat(sstr, "none");
188 strcpy(str, sstr);
189 } else if (noTokens == 6) {
190 // number
191 snprintf(sstr, sizeof(sstr), "%10s", tokens[0].c_str());
192 // name
193 strcat(sstr, " ");
194 strcat(sstr, tokens[1].c_str());
195 memset(spaces, 0, sizeof(spaces));
196 memset(spaces, ' ', 12-strlen(tokens[1].c_str()));
197 strcat(sstr, spaces);
198 // value
199 strcat(sstr, tokens[2].c_str());
200 if (strlen(tokens[2].c_str()) < 10) {
201 memset(spaces, 0, sizeof(spaces));
202 memset(spaces, ' ', 10-strlen(tokens[2].c_str()));
203 strcat(sstr, spaces);
204 } else {
205 strcat(sstr, " ");
206 }
207 // step
208 strcat(sstr, tokens[3].c_str());
209 if (strlen(tokens[3].c_str()) < 12) {
210 memset(spaces, 0, sizeof(spaces));
211 memset(spaces, ' ', 12-strlen(tokens[3].c_str()));
212 strcat(sstr, spaces);
213 } else {
214 strcat(sstr, " ");
215 }
216 // pos. error
217 strcat(sstr, "none ");
218 // lower boundary
219 strcat(sstr, tokens[4].c_str());
220 if (strlen(tokens[4].c_str()) < 8) {
221 memset(spaces, 0, sizeof(spaces));
222 memset(spaces, ' ', 8-strlen(tokens[4].c_str()));
223 strcat(sstr, spaces);
224 } else {
225 strcat(sstr, " ");
226 }
227 // upper boundary
228 strcat(sstr, tokens[5].c_str());
229 strcpy(str, sstr);
230 }
231
232 return true;
233}
234
235//--------------------------------------------------------------------------
248bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
249{
250 // handle theory line
251 TString line(str);
252 std::vector<std::string> tokens;
253 char sstr[256];
254
255 if ((line.Contains("sktt") || line.Contains("statKTTab")) && line.Contains("glf")) { // static Gauss KT LF table
256 // change cmd name
257 strcpy(sstr, "statGssKTLF ");
258
259 // tokenize the rest and extract the first two parameters
260 tokens = PStringUtils::Split(line.Data(), " \t");
261 std::size_t noTokens = tokens.size();
262 if (noTokens < 3) {
263 std::cout << std::endl << "**ERROR** in THEORY block";
264 std::cout << std::endl << " Line: '" << str << "' is not a valid statKTTab statement.";
265 std::cout << std::endl << " Cannot handle file." << std::endl;
266 return false;
267 }
268 for (Int_t i=1; i<3; i++) {
269 strcat(sstr, " ");
270 strcat(sstr, tokens[i].c_str());
271 }
272 strcat(sstr, " (frequency damping)");
273 strcpy(str, sstr);
274 } else if ((line.Contains("sktt") || line.Contains("statKTTab")) && line.Contains("llf")) { // static Lorentz KT LF table
275 // change cmd name
276 strcpy(sstr, "statExpKTLF ");
277
278 // tokenize the rest and extract the first two parameters
279 tokens = PStringUtils::Split(line.Data(), " \t");
280 std::size_t noTokens = tokens.size();
281 if (noTokens < 3) {
282 std::cout << std::endl << "**ERROR** in THEORY block";
283 std::cout << std::endl << " Line: '" << str << "' is not a valid statKTTab statement.";
284 std::cout << std::endl << " Cannot handle file." << std::endl;
285 return false;
286 }
287 for (Int_t i=1; i<3; i++) {
288 strcat(sstr, " ");
289 strcat(sstr, tokens[i].c_str());
290 }
291 strcat(sstr, " (frequency damping)");
292 strcpy(str, sstr);
293 } else if ((line.Contains("dktt") || line.Contains("dynmKTTab")) && line.Contains("kdglf")) { // dynamic Gauss KT LF table
294 // change cmd name
295 strcpy(sstr, "dynGssKTLF ");
296
297 // tokenize the rest and extract the first three parameters
298 tokens = PStringUtils::Split(line.Data(), " \t");
299 std::size_t noTokens = tokens.size();
300 if (noTokens < 4) {
301 std::cout << std::endl << "**ERROR** in THEORY block";
302 std::cout << std::endl << " Line: '" << str << "' is not a valid dynmKTTab statement.";
303 std::cout << std::endl << " Cannot handle file." << std::endl;
304 return false;
305 }
306 for (Int_t i=1; i<4; i++) {
307 strcat(sstr, " ");
308 strcat(sstr, tokens[i].c_str());
309 }
310 strcat(sstr, " (frequency damping hopping-rate)");
311 strcpy(str, sstr);
312 } else if ((line.Contains("dktt") || line.Contains("dynmKTTab")) && line.Contains("kdllf")) { // dynamic Lorentz KT LF table
313 // change cmd name
314 strcpy(sstr, "dynExpKTLF ");
315
316 // tokenize the rest and extract the first three parameters
317 tokens = PStringUtils::Split(line.Data(), " \t");
318 std::size_t noTokens = tokens.size();
319 if (noTokens < 4) {
320 std::cout << std::endl << "**ERROR** in THEORY block";
321 std::cout << std::endl << " Line: '" << str << "' is not a valid dynmKTTab statement.";
322 std::cout << std::endl << " Cannot handle file." << std::endl;
323 return false;
324 }
325 for (Int_t i=1; i<4; i++) {
326 strcat(sstr, " ");
327 strcat(sstr, tokens[i].c_str());
328 }
329 strcat(sstr, " (frequency damping hopping-rate)");
330 strcpy(str, sstr);
331 } else if (line.Contains("internFld")) {
333 noOfAddionalParams++;
334
335 // change cmd name
336 strcpy(sstr, "internFld ");
337
338 // tokenize the rest and extract the first three parameters
339 tokens = PStringUtils::Split(line.Data(), " \t");
340 std::size_t noTokens = tokens.size();
341 if (noTokens < 4) {
342 std::cout << std::endl << "**ERROR** in THEORY block";
343 std::cout << std::endl << " Line: '" << str << "' is not a valid internFld statement.";
344 std::cout << std::endl << " Cannot handle file." << std::endl;
345 return false;
346 }
347 strcat(sstr, " _x_");
348 for (Int_t i=1; i<4; i++) {
349 strcat(sstr, " ");
350 strcat(sstr, tokens[i].c_str());
351 }
352 strcat(sstr, " (fraction phase frequency Trate Lrate)");
353 strcpy(str, sstr);
354 } else if (line.Contains("internBsl")) {
356 noOfAddionalParams++;
357
358 // change cmd name
359 strcpy(sstr, "internBsl ");
360
361 // tokenize the rest and extract the first three parameters
362 tokens = PStringUtils::Split(line.Data(), " \t");
363 std::size_t noTokens = tokens.size();
364 if (noTokens < 4) {
365 std::cout << std::endl << "**ERROR** in THEORY block";
366 std::cout << std::endl << " Line: '" << str << "' is not a valid internBsl statement.";
367 std::cout << std::endl << " Cannot handle file." << std::endl;
368 return false;
369 }
370 strcat(sstr, " _x_");
371 for (Int_t i=1; i<4; i++) {
372 strcat(sstr, " ");
373 strcat(sstr, tokens[i].c_str());
374 }
375 strcat(sstr, " (fraction phase frequency Trate Lrate)");
376 strcpy(str, sstr);
377 }
378
379 return true;
380}
381
382
383//--------------------------------------------------------------------------
393bool msr2msr_is_comment(const char *str)
394{
395 bool isComment = false;
396
397 for (unsigned int i=0; i<strlen(str); i++) {
398 if ((str[i] == ' ') || (str[i] == '\t'))
399 continue;
400 if (str[i] == '#') {
401 isComment = true;
402 break;
403 } else {
404 isComment = false;
405 break;
406 }
407 }
408
409 return isComment;
410}
411
412//--------------------------------------------------------------------------
422bool msr2msr_is_whitespace(const char *str)
423{
424 bool isWhitespace = true;
425
426 if (strlen(str) != 0) {
427 for (unsigned int i=0; i<strlen(str); i++) {
428 if ((str[i] != ' ') && (str[i] != '\t')) {
429 isWhitespace = false;
430 break;
431 }
432 }
433 }
434
435 return isWhitespace;
436}
437
438//--------------------------------------------------------------------------
445void msr2msr_replace(std::string &str, int paramNo)
446{
447 const std::string no{std::to_string(paramNo)};
448
449 // build the result in a std::string: the previous fixed size scratch buffer
450 // overflowed for msr-lines longer than its size.
451 std::string temp;
452 temp.reserve(str.length());
453
454 for (std::string::size_type i=0; i<str.length(); i++) {
455 if (str[i] != '_') {
456 temp += str[i];
457 } else { // '_x_' placeholder -> parameter number
458 temp += no;
459 i += 2;
460 }
461 }
462
463 str = temp;
464}
465
466//--------------------------------------------------------------------------
475bool msr2msr_finalize_theory(char *fln, int theoryTag, int noOfAddionalParams)
476{
477 std::ifstream fin;
478 fin.open(fln, std::iostream::in);
479 if (!fin.is_open()) {
480 std::cout << std::endl << "**ERROR**: Couldn't open input msr-file " << fln;
481 std::cout << std::endl << " Will quit." << std::endl;
482 return 0;
483 }
484
485 // open temporary output msr-file
486 std::ofstream fout;
487 fout.open("__temp.msr", std::iostream::out);
488 if (!fout.is_open()) {
489 std::cout << std::endl << "**ERROR**: Couldn't open output msr-file __temp.msr";
490 std::cout << std::endl << " Will quit." << std::endl;
491 fin.close();
492 return 0;
493 }
494
495 std::string str;
496 int tag = -1;
497 bool success = true;
498 int param = 0;
499 int count = 0;
500 while (std::getline(fin, str) && success) {
501 if (str.find("FITPARAMETER") != std::string::npos) {
503 } else if (str.find("THEORY") != std::string::npos) {
504 tag = MSR_TAG_THEORY;
505 }
506
507 if ((tag == MSR_TAG_FITPARAMETER) && (str.find("FITPARAMETER") == std::string::npos)) {
508 if ((theoryTag == MSR_THEORY_INTERN_FLD) || (theoryTag == MSR_THEORY_INTERN_BESSEL)) {
509 if (!msr2msr_is_comment(str.c_str())) {
510 param++;
511 if (msr2msr_is_whitespace(str.c_str())) {
512 // add needed parameters
513 for (int i=0; i<noOfAddionalParams; i++) {
514 fout << " " << param+i << " frac" << i+1 << " 0.333333 0.0 none" << std::endl;
515 }
516 }
517 }
518 }
519 }
520
521 if (tag == MSR_TAG_THEORY) {
522 if ((theoryTag == MSR_THEORY_INTERN_FLD) || (theoryTag == MSR_THEORY_INTERN_BESSEL)) {
523 if (str.find("_x_") != std::string::npos) {
524 msr2msr_replace(str, param+count);
525 count++;
526 }
527 }
528 }
529
530 fout << str << std::endl;
531 }
532
533 // close files
534 fout.close();
535 fin.close();
536
537
538 // cp __temp.msr fln, and rm __temp.msr afterwards. Done via std::filesystem
539 // rather than system(): a shell command assembled in a fixed size buffer would
540 // silently truncate for long paths (and choke on paths containing blanks).
541 std::error_code ec;
542 std::filesystem::copy_file(std::filesystem::path("__temp.msr"), std::filesystem::path(fln),
543 std::filesystem::copy_options::overwrite_existing, ec);
544 if (ec) {
545 std::cerr << "**ERROR** couldn't copy __temp.msr -> " << fln << ": " << ec.message() << std::endl;
546 return false;
547 }
548 std::filesystem::remove(std::filesystem::path("__temp.msr"), ec);
549 if (ec) {
550 std::cerr << "**ERROR** couldn't remove __temp.msr: " << ec.message() << std::endl;
551 return false;
552 }
553
554 return true;
555}
556
557//--------------------------------------------------------------------------
569bool msr2msr_statistic(char *str, const std::size_t size) {
570 bool success = true;
571
572 char *pstr;
573 int status;
574 double chisq, chisqred;
575 if (strstr(str, " chi")) {
576 pstr = strstr(str, "abs = ");
577 if (pstr != nullptr) {
578 status = sscanf(pstr, "abs = %lf", &chisq);
579 if (status != 1) {
580 success = false;
581 }
582 }
583 pstr = strstr(str, "norm = ");
584 if (pstr != nullptr) {
585 status = sscanf(pstr, "norm = %lf", &chisqred);
586 if (status != 1) {
587 success = false;
588 }
589 }
590 if (success) {
591 snprintf(str, size, " chisq = %lf, NDF = %d, chisq/NDF = %lf", chisq, static_cast<int>(chisq/chisqred), chisqred);
592 }
593 }
594
595 return success;
596}
597
598//--------------------------------------------------------------------------
606int main(int argc, char *argv[])
607{
608
609 // check the number of arguments
610 if (argc != 3) {
612 return 0;
613 }
614
615 // open input msr-file
616 std::ifstream fin;
617 fin.open(argv[1], std::iostream::in);
618 if (!fin.is_open()) {
619 std::cout << std::endl << "**ERROR**: Couldn't open input msr-file " << argv[1];
620 std::cout << std::endl << " Will quit." << std::endl;
621 return 0;
622 }
623
624 // open output msr-file
625 std::ofstream fout;
626 fout.open(argv[2], std::iostream::out);
627 if (!fout.is_open()) {
628 std::cout << std::endl << "**ERROR**: Couldn't open output msr-file " << argv[2];
629 std::cout << std::endl << " Will quit." << std::endl;
630 fin.close();
631 return 0;
632 }
633
634 // read input file and write output file
635 char str[256];
636 int tag = -1;
637 int theoryTag = -1;
638 int noOfAddionalParams = 0;
639 bool success = true;
640 while (!fin.eof() && success) {
641 fin.getline(str, sizeof(str));
642
643 if (strstr(str, "FITPARAMETER")) {
645 } else if (strstr(str, "RUN")) { // analyze and change header
646 tag = MSR_TAG_RUN;
647 } else if (strstr(str, "THEORY")) {
648 tag = MSR_TAG_THEORY;
649 } else if (strstr(str, "STATISTIC")) {
650 tag = MSR_TAG_STATISTIC;
651 }
652
653 switch (tag) {
655 success = msr2msr_param(str);
656 break;
657 case MSR_TAG_THEORY:
658 success = msr2msr_theory(str, theoryTag, noOfAddionalParams);
659 break;
660 case MSR_TAG_RUN:
661 success = msr2msr_run(str, sizeof(str));
662 break;
664 success = msr2msr_statistic(str, sizeof(str));
665 break;
666 default:
667 break;
668 }
669
670 fout << str << std::endl;
671 }
672
673 // close files
674 fout.close();
675 fin.close();
676
677 // check if conversion seems to be OK
678 if (!success) {
679 std::error_code ec;
680 std::filesystem::remove_all(std::filesystem::path(argv[2]), ec);
681 if (ec) {
682 std::cerr << "**ERROR** couldn't remove " << argv[2] << ": " << ec.message() << std::endl;
683 return 0;
684 }
685 }
686
687 if (theoryTag != -1) {
688 msr2msr_finalize_theory(argv[2], theoryTag, noOfAddionalParams);
689 }
690
691 std::cout << std::endl << "done ..." << std::endl;
692
693 return 1;
694}
#define MSR_TAG_RUN
RUN block - run-specific settings and data file information.
Definition PMusr.h:198
#define MSR_TAG_THEORY
THEORY block - specifies the theory function(s) to fit.
Definition PMusr.h:192
#define MSR_TAG_FITPARAMETER
FITPARAMETER block - defines fit parameters with initial values and constraints.
Definition PMusr.h:190
#define MSR_TAG_STATISTIC
STATISTIC block - fit statistics and results (generated after fit)
Definition PMusr.h:206
return status
int main(int argc, char *argv[])
Definition msr2msr.cpp:606
bool msr2msr_param(char *str)
Definition msr2msr.cpp:145
#define MSR_THEORY_INTERN_FLD
Definition msr2msr.cpp:57
bool msr2msr_run(char *str, const std::size_t size)
Definition msr2msr.cpp:85
#define MSR_THEORY_INTERN_BESSEL
Definition msr2msr.cpp:58
void msr2msr_replace(std::string &str, int paramNo)
Definition msr2msr.cpp:445
bool msr2msr_statistic(char *str, const std::size_t size)
Definition msr2msr.cpp:569
bool msr2msr_is_comment(const char *str)
Definition msr2msr.cpp:393
bool msr2msr_is_whitespace(const char *str)
Definition msr2msr.cpp:422
bool msr2msr_theory(char *str, int &tag, int &noOfAddionalParams)
Definition msr2msr.cpp:248
bool msr2msr_finalize_theory(char *fln, int theoryTag, int noOfAddionalParams)
Definition msr2msr.cpp:475
void msr2msr_syntax()
Definition msr2msr.cpp:64