musrfit 1.10.0
PStartupHandler.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 PStartupHandler.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 <sys/types.h>
31#include <sys/stat.h>
32
33#include <cstdlib>
34#include <iostream>
35#include <fstream>
36
37#include <TColor.h>
38#include <TList.h>
39#include <TXMLAttr.h>
40
41#include "PStartupHandler.h"
42#include "PStringUtils.h"
43
45
46//--------------------------------------------------------------------------
47// This function is a replacement for the ParseFile method of TSAXParser.
48// It is needed because in certain environments ParseFile does not work but ParseBuffer does.
49//--------------------------------------------------------------------------
82int parseXmlFile(TSAXParser *saxParser, const char *startup_path_name)
83{
84 int status;
85 std::fstream xmlFile;
86 unsigned int xmlSize = 0;
87 char *xmlBuffer = nullptr;
88
89 xmlFile.open(startup_path_name, std::ios::in | std::ios::ate); // open file for reading and go to the end of the file
90 if (xmlFile.is_open()) { // check if file has been opened successfully
91 xmlSize = xmlFile.tellg(); // get the position within the stream == size of the file (since we are at the end)
92 xmlFile.seekg(0, std::ios::beg); // go back to the beginning of the stream
93 xmlBuffer = new char[xmlSize]; // allocate buffer memory for the whole XML file
94 xmlFile.read(xmlBuffer, xmlSize); // read in the whole XML file into the buffer
95 xmlFile.close(); // close the XML file
96 }
97 if (!xmlBuffer) { // file has not been read into the buffer
98 status = 1;
99 } else {
100 status = saxParser->ParseBuffer(xmlBuffer, xmlSize); // parse buffer
101 delete[] xmlBuffer; // free the buffer memory
102 xmlBuffer = nullptr;
103 }
104
105 return status;
106}
107
108//--------------------------------------------------------------------------
109// Constructor
110//--------------------------------------------------------------------------
147PStartupHandler::PStartupHandler(bool reset_startup_file)
148{
149 fStartupFileFound = false;
150 fStartupFilePath = "";
151
152 // get default path (for the moment only linux like)
153 Char_t *pmusrpath=nullptr;
154 Char_t *home=nullptr;
155 Char_t musrpath[128];
156 Char_t startup_path_name[128];
157
158 strncpy(musrpath, "", sizeof(musrpath));
159
160 // check if the startup file is found in the current directory
161 strcpy(startup_path_name, "./musrfit_startup.xml");
163 fStartupFileFound = true;
165 }
166 if (!fStartupFileFound) { // startup file not found in the current directory
167 // check if the startup file is found under $HOME/.musrfit
168 home = getenv("HOME");
169 if (home != nullptr) {
170 snprintf(startup_path_name, sizeof(startup_path_name), "%s/.musrfit/musrfit_startup.xml", home);
173 fStartupFileFound = true;
174 }
175 }
176 }
177 if (!fStartupFileFound) { // startup file not found in $HOME/.musrfit
178 // check if the MUSRFITPATH system variable is set
179 pmusrpath = getenv("MUSRFITPATH");
180 if (pmusrpath != nullptr) {
181 snprintf(startup_path_name, sizeof(startup_path_name), "%s/musrfit_startup.xml", pmusrpath);
184 fStartupFileFound = true;
185 }
186 }
187 }
188 if (!fStartupFileFound) { // MUSRFITPATH not set or empty, will try $ROOTSYS/bin
189 home = getenv("ROOTSYS");
190 if (home != nullptr) {
191 snprintf(musrpath, sizeof(musrpath), "%s/bin", home);
192 std::cerr << std::endl << "**WARNING** MUSRFITPATH environment variable not set will try " << musrpath << std::endl;
193 snprintf(startup_path_name, sizeof(startup_path_name), "%s/musrfit_startup.xml", musrpath);
196 fStartupFileFound = true;
197 }
198 }
199 }
200
201 // musrfit_startup.xml found. Check if it should be rewritten
202 if (fStartupFileFound && reset_startup_file) {
203 std::cout << std::endl;
204 std::cout << ">> Will only reset the file: '" << fStartupFilePath.Data() << "'."<< std::endl;
205 std::cout << std::endl;
206 if (!WriteDefaultStartupFile(reset_startup_file)) {
207 std::cerr << std::endl << "**ERROR** couldn't re-write " << fStartupFilePath.Data() << "." << std::endl;
208 return;
209 }
210 }
211
212 // if musrfit_startup.xml is still not found, will create a default one
213 if (!fStartupFileFound) {
214 std::cout << std::endl << "**INFO** no musrfit_startup.xml file found, will write a default one." << std::endl;
216 std::cerr << std::endl << "**ERROR** couldn't write default musrfit_startup.xml." << std::endl;
217 } else {
218 home = getenv("HOME");
219 if (home != nullptr) {
220 snprintf(startup_path_name, sizeof(startup_path_name), "%s/.musrfit/musrfit_startup.xml", home);
223 fStartupFileFound = true;
224 }
225 }
226 }
227 }
228}
229
230//--------------------------------------------------------------------------
231// Destructor
232//--------------------------------------------------------------------------
246{
247 // clean up
248 fDataPathList.clear();
249 fMarkerList.clear();
250 fColorList.clear();
251 fRunNameTemplate.clear();
252}
253
254//--------------------------------------------------------------------------
255// OnStartDocument
256//--------------------------------------------------------------------------
279{
280 fKey = eEmpty;
281
282 // init fourier default variables
283 fFourierDefaults.fFourierBlockPresent = false;
285 fFourierDefaults.fFourierPower = 0;
286 fFourierDefaults.fApodization = FOURIER_APOD_NONE;
288 fFourierDefaults.fRangeForPhaseCorrection[0] = -1.0;
289 fFourierDefaults.fRangeForPhaseCorrection[1] = -1.0;
290 fFourierDefaults.fPlotRange[0] = -1.0;
291 fFourierDefaults.fPlotRange[1] = -1.0;
292 fFourierDefaults.fPhaseIncrement = 1.0;
293}
294
295//--------------------------------------------------------------------------
296// OnEndDocument
297//--------------------------------------------------------------------------
311{
312 // check if anything was set, and if not set some default stuff
313 CheckLists();
314}
315
316//--------------------------------------------------------------------------
317// OnStartElement
318//--------------------------------------------------------------------------
348void PStartupHandler::OnStartElement(const Char_t *str, const TList *attributes)
349{
350 if (!strcmp(str, "data_path")) {
351 fKey = eDataPath;
352 } else if (!strcmp(str, "run_name_template")) {
354 TXMLAttr *attr;
355 TIter next(attributes);
356 while ((attr = (TXMLAttr*) next())) {
357 if (!strcmp(attr->GetName(), "inst")) {
358 fCurrentInstrumentName = attr->GetValue();
359 }
360 }
361 } else if (!strcmp(str, "marker")) {
362 fKey = eMarker;
363 } else if (!strcmp(str, "color")) {
364 fKey = eColor;
365 } else if (!strcmp(str, "units")) {
366 fKey = eUnits;
367 } else if (!strcmp(str, "fourier_power")) {
369 } else if (!strcmp(str, "apodization")) {
371 } else if (!strcmp(str, "plot")) {
372 fKey = ePlot;
373 } else if (!strcmp(str, "phase")) {
374 fKey = ePhase;
375 } else if (!strcmp(str, "phase_increment")) {
377 }
378}
379
380//--------------------------------------------------------------------------
381// OnEndElement
382//--------------------------------------------------------------------------
394void PStartupHandler::OnEndElement(const Char_t *str)
395{
396 fKey = eEmpty;
397}
398
399//--------------------------------------------------------------------------
400// OnCharacters
401//--------------------------------------------------------------------------
451void PStartupHandler::OnCharacters(const Char_t *str)
452{
453 TString tstr;
454 Int_t color, r, g, b, ival;
455
456 PRunNameTemplate tmpl;
457 switch (fKey) {
458 case eDataPath:
459 // check that str is a valid path
460 // add str to the path list
461 fDataPathList.push_back(str);
462 break;
463 case eRunNameTemplate:
465 tmpl.runNameTemplate = str;
466 fRunNameTemplate.push_back(tmpl);
468 break;
469 case eMarker:
470 // check that str is a number
471 tstr = TString(str);
472 if (tstr.IsDigit()) {
473 // add converted str to the marker list
474 fMarkerList.push_back(tstr.Atoi());
475 } else {
476 std::cerr << std::endl << "PStartupHandler **WARNING** '" << str << "' is not a number, will ignore it";
477 std::cerr << std::endl;
478 }
479 break;
480 case eColor:
481 {
482 // check that str is a rbg code
483 std::vector<std::string> rgb = PStringUtils::Split(str, ",");
484 // check there is the right number of tokens
485 if (rgb.size() != 3) {
486 std::cerr << std::endl << "PStartupHandler **WARNING** '" << str << "' is not a rbg code, will ignore it";
487 std::cerr << std::endl;
488 return;
489 }
490 // get r
491 if (PStringUtils::IsInt(rgb[0])) {
492 r = PStringUtils::ToInt(rgb[0]);
493 } else {
494 std::cerr << std::endl << "PStartupHandler **WARNING** r within the rgb code is not a number, will ignore it";
495 std::cerr << std::endl;
496 return;
497 }
498 // get g
499 if (PStringUtils::IsInt(rgb[1])) {
500 g = PStringUtils::ToInt(rgb[1]);
501 } else {
502 std::cerr << std::endl << "PStartupHandler **WARNING** g within the rgb code is not a number, will ignore it";
503 std::cerr << std::endl;
504 return;
505 }
506 // get b
507 if (PStringUtils::IsInt(rgb[2])) {
508 b = PStringUtils::ToInt(rgb[2]);
509 } else {
510 std::cerr << std::endl << "PStartupHandler **WARNING** b within the rgb code is not a number, will ignore it";
511 std::cerr << std::endl;
512 return;
513 }
514 // generate the ROOT color code based on str
515 color = TColor::GetColor(r,g,b);
516 // add the color code to the color list
517 fColorList.push_back(color);
518 }
519 break;
520 case eUnits:
521 tstr = TString(str);
522 if (!tstr.CompareTo("gauss", TString::kIgnoreCase)) {
524 } else if (!tstr.CompareTo("tesla", TString::kIgnoreCase)) {
526 } else if (!tstr.CompareTo("mhz", TString::kIgnoreCase)) {
528 } else if (!tstr.CompareTo("mc/s", TString::kIgnoreCase)) {
530 } else {
531 std::cerr << std::endl << "PStartupHandler **WARNING** '" << str << "' is not a valid unit, will ignore it.";
532 std::cerr << std::endl;
533 }
534 break;
535 case eFourierPower:
536 tstr = TString(str);
537 if (tstr.IsDigit()) {
538 ival = tstr.Atoi();
539 if ((ival >= 0) && (ival <= 20)) {
540 fFourierDefaults.fFourierPower = ival;
541 } else {
542 std::cerr << std::endl << "PStartupHandler **WARNING** fourier power '" << str << "' is not a valid number (0..20), will ignore it.";
543 std::cerr << std::endl;
544 }
545 } else {
546 std::cerr << std::endl << "PStartupHandler **WARNING** fourier power '" << str << "' is not a valid number (0..20), will ignore it.";
547 std::cerr << std::endl;
548 }
549 break;
550 case eApodization:
551 tstr = TString(str);
552 if (!tstr.CompareTo("none", TString::kIgnoreCase)) {
553 fFourierDefaults.fApodization = FOURIER_APOD_NONE;
554 } else if (!tstr.CompareTo("weak", TString::kIgnoreCase)) {
555 fFourierDefaults.fApodization = FOURIER_APOD_WEAK;
556 } else if (!tstr.CompareTo("medium", TString::kIgnoreCase)) {
558 } else if (!tstr.CompareTo("strong", TString::kIgnoreCase)) {
560 } else {
561 std::cerr << std::endl << "PStartupHandler **WARNING** '" << str << "' is not a valid apodization, will ignore it.";
562 std::cerr << std::endl;
563 }
564 break;
565 case ePlot:
566 tstr = TString(str);
567 if (!tstr.CompareTo("real", TString::kIgnoreCase)) {
569 } else if (!tstr.CompareTo("imag", TString::kIgnoreCase)) {
571 } else if (!tstr.CompareTo("real_and_imag", TString::kIgnoreCase)) {
573 } else if (!tstr.CompareTo("power", TString::kIgnoreCase)) {
575 } else if (!tstr.CompareTo("phase", TString::kIgnoreCase)) {
577 } else {
578 std::cerr << std::endl << "PStartupHandler **WARNING** '" << str << "' is not a valid plot option, will ignore it.";
579 std::cerr << std::endl;
580 }
581 break;
582 case ePhase:
583 tstr = TString(str);
584 if (tstr.IsFloat()) {
585 fFourierDefaults.fPhase.push_back(tstr.Atof());
586 } else {
587 std::cerr << std::endl << "PStartupHandler **WARNING** '" << str << "' is not a valid phase, will ignore it.";
588 std::cerr << std::endl;
589 }
590 break;
591 case ePhaseIncrement:
592 tstr = TString(str);
593 if (tstr.IsFloat()) {
594 fFourierDefaults.fPhaseIncrement = tstr.Atof();
595 } else {
596 std::cerr << std::endl << "PStartupHandler **WARNING** '" << str << "' is not a valid phase increment, will ignore it.";
597 std::cerr << std::endl;
598 }
599 break;
600 default:
601 break;
602 }
603}
604
605//--------------------------------------------------------------------------
606// OnComment
607//--------------------------------------------------------------------------
618void PStartupHandler::OnComment(const Char_t *str)
619{
620 // nothing to be done for now
621}
622
623//--------------------------------------------------------------------------
624// OnWarning
625//--------------------------------------------------------------------------
639void PStartupHandler::OnWarning(const Char_t *str)
640{
641 std::cerr << std::endl << "PStartupHandler **WARNING** " << str;
642 std::cerr << std::endl;
643}
644
645//--------------------------------------------------------------------------
646// OnError
647//--------------------------------------------------------------------------
662void PStartupHandler::OnError(const Char_t *str)
663{
664 std::cerr << std::endl << "PStartupHandler **ERROR** " << str;
665 std::cerr << std::endl;
666}
667
668//--------------------------------------------------------------------------
669// OnFatalError
670//--------------------------------------------------------------------------
686void PStartupHandler::OnFatalError(const Char_t *str)
687{
688 std::cerr << std::endl << "PStartupHandler **FATAL ERROR** " << str;
689 std::cerr << std::endl;
690}
691
692//--------------------------------------------------------------------------
693// OnCdataBlock
694//--------------------------------------------------------------------------
708void PStartupHandler::OnCdataBlock(const Char_t *str, Int_t len)
709{
710 // nothing to be done for now
711}
712
713//--------------------------------------------------------------------------
714// CheckLists
715//--------------------------------------------------------------------------
747{
748 // check if anything was set, and if not set some default stuff
749
750 // check if any data path is given
751 if (fDataPathList.size() == 0) {
752 fDataPathList.push_back(TString("/mnt/data/nemu/his"));
753 fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/lem/his/"));
754 fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/alc/his/"));
755 fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/dolly/his/"));
756 fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/flame/his/"));
757 fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/gpd/his/"));
758 fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/gps/his/"));
759 fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/hal/his/"));
760 fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/ltf/his/"));
761 fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/misc/his/"));
762 fDataPathList.push_back(TString("/psi.ch/group/lmu/public/data/vms/his/"));
763 }
764
765 // check if any markers are given
766 if (fMarkerList.size() == 0) {
767 fMarkerList.push_back(24); // open circle
768 fMarkerList.push_back(25); // open square
769 fMarkerList.push_back(26); // open triangle
770 fMarkerList.push_back(27); // open diamond
771 fMarkerList.push_back(28); // open cross
772 fMarkerList.push_back(29); // full star
773 fMarkerList.push_back(30); // open star
774 fMarkerList.push_back(20); // full circle
775 fMarkerList.push_back(21); // full square
776 fMarkerList.push_back(22); // full triangle
777 fMarkerList.push_back(23); // full down triangle
778 fMarkerList.push_back(2); // thin cross
779 fMarkerList.push_back(3); // thin star
780 fMarkerList.push_back(5); // thin cross 45° rotated
781 }
782
783 // check if any colors are given
784 if (fColorList.size() == 0) {
785 fColorList.push_back(TColor::GetColor(0, 0, 0)); // kBlack
786 fColorList.push_back(TColor::GetColor(255, 0, 0)); // kRed
787 fColorList.push_back(TColor::GetColor(0, 255, 0)); // kGreen
788 fColorList.push_back(TColor::GetColor(0, 0, 255)); // kBlue
789 fColorList.push_back(TColor::GetColor(255, 0, 255)); // kMagneta
790 fColorList.push_back(TColor::GetColor(0, 255, 255)); // kCyan
791 fColorList.push_back(TColor::GetColor(156, 0, 255)); // kViolette-3
792 fColorList.push_back(TColor::GetColor(99, 101, 49)); // kYellow-1
793 fColorList.push_back(TColor::GetColor(49, 101, 49)); // kGreen-1
794 fColorList.push_back(TColor::GetColor(156, 48, 0)); // kOrange-4
795 }
796}
797
798//--------------------------------------------------------------------------
799// StartupFileExists
800//--------------------------------------------------------------------------
816{
817 Bool_t result = false;
818
819 std::ifstream ifile(fln);
820
821 if (ifile.fail()) {
822 result = false;
823 } else {
824 result = true;
825 ifile.close();
826 }
827
828 return result;
829}
830
831//--------------------------------------------------------------------------
832// WriteDefaultStartupFile
833//--------------------------------------------------------------------------
880Bool_t PStartupHandler::WriteDefaultStartupFile(bool reset_startup_file)
881{
882 Char_t startup_path_name[256];
883 if (reset_startup_file) { // reset the found
884 snprintf(startup_path_name, sizeof(startup_path_name), "%s", fStartupFilePath.Data());
885 } else { // no musrfit_startup.xml found, hence write default under $HOME/.musrfit
886 // get home
887 Char_t *home = nullptr;
888 home = getenv("HOME");
889 if (home == nullptr) {
890 std::cerr << std::endl << "**ERROR** couldn't obtain $HOME." << std::endl;
891 return false;
892 }
893
894 // first check that $HOME/.musrfit exists and if NOT create it
895 struct stat info;
896
897 snprintf(startup_path_name, sizeof(startup_path_name), "%s/.musrfit", home);
898 if (!stat(startup_path_name, &info)) {
899 if (!(info.st_mode & S_IFDIR))
900 return false;
901 } else {
902 if (mkdir(startup_path_name, 0777)) {
903 std::cerr << std::endl << "**ERROR** couldn't create '" << startup_path_name << "'" << std::endl;
904 return false;
905 }
906 }
907
908 // set path-name for musrfit_startup.xml
909 snprintf(startup_path_name, sizeof(startup_path_name), "%s/.musrfit/musrfit_startup.xml", home);
910 }
911
912 std::ofstream fout(startup_path_name, std::ofstream::out);
913 if (!fout.is_open()) {
914 std::cerr << std::endl << "**ERROR** couldn't open '" << startup_path_name << "' for writing." << std::endl;
915 return false;
916 }
917
918 // write default musrfit_startup.xml
919 fout << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
920 fout << "<musrfit xmlns=\"https://lmu.pages.psi.ch/musrfit-docu/\">" << std::endl;
921 fout << " <comment>" << std::endl;
922 fout << " Defines default settings for the musrfit package" << std::endl;
923 fout << " </comment>" << std::endl;
924 fout << " <data_path>/psi.ch/group/lmu/public/data/lem/his</data_path>" << std::endl;
925 fout << " <data_path>/psi.ch/group/lmu/public/data/alc/his</data_path>" << std::endl;
926 fout << " <data_path>/psi.ch/group/lmu/public/data/dolly/his</data_path>" << std::endl;
927 fout << " <data_path>/psi.ch/group/lmu/public/data/flame/his</data_path>" << std::endl;
928 fout << " <data_path>/psi.ch/group/lmu/public/data/gpd/his</data_path>" << std::endl;
929 fout << " <data_path>/psi.ch/group/lmu/public/data/gps/his</data_path>" << std::endl;
930 fout << " <data_path>/psi.ch/group/lmu/public/data/hal/his</data_path>" << std::endl;
931 fout << " <data_path>/psi.ch/group/lmu/public/data/ltf/his</data_path>" << std::endl;
932 fout << " <data_path>/psi.ch/group/lmu/public/data/misc/his</data_path>" << std::endl;
933 fout << " <data_path>/psi.ch/group/lmu/public/data/vms/his</data_path>" << std::endl;
934 fout << " <!-- MISC/PSI 1985 - 1990 -->" << std::endl;
935 fout << " <run_name_template inst=\"misc\">d%yyyy%/deltat_misc_%rrrr%.bin</run_name_template>" << std::endl;
936 fout << " <!-- ALC TD/PSI -->" << std::endl;
937 fout << " <run_name_template inst=\"alc\">d%yyyy%/deltat_zh_chem_%rrrr%.bin</run_name_template>" << std:: endl;
938 fout << " <run_name_template inst=\"alc\">d%yyyy%/deltat_tdc_alc_%rrrr%.bin</run_name_template>" << std::endl;
939 fout << " <run_name_template inst=\"alc\">d%yyyy%/tdc/deltat_tdc_alc_%rrrr%.bin</run_name_template>" << std::endl;
940 fout << " <!-- VMS/PSI -->" << std::endl;
941 fout << " <run_name_template inst=\"vms\">d%yyyy%/tdc/root/deltat_tdc_vms_%yyyy%_%rrrr%.root</run_name_template>" << std::endl;
942 fout << " <!-- Dolly/PSI -->" << std::endl;
943 fout << " <run_name_template inst=\"dolly\">d%yyyy%/tdc/root/deltat_tdc_dolly_%yyyy%_%rrrr%.root</run_name_template>" << std::endl;
944 fout << " <run_name_template inst=\"dolly\">d%yyyy%/pie1/deltat_flc_%rrrr%.bin</run_name_template>" << std::endl;
945 fout << " <run_name_template inst=\"dolly\">d%yyyy%/pie3/deltat_flc_%rrrr%.bin</run_name_template>" << std::endl;
946 fout << " <run_name_template inst=\"dolly\">d%yyyy%/deltat_flc_%rrrr%.bin</run_name_template>" << std::endl;
947 fout << " <run_name_template inst=\"dolly\">d%yyyy%/deltat_pta_dolly_%rrrr%.bin</run_name_template>" << std::endl;
948 fout << " <run_name_template inst=\"dolly\">d%yyyy%/pta/deltat_pta_dolly_%rrrr%.bin</run_name_template>" << std::endl;
949 fout << " <run_name_template inst=\"dolly\">d%yyyy%/tdc/deltat_tdc_dolly_%rrrr%.bin</run_name_template>" << std::endl;
950 fout << " <run_name_template inst=\"dolly\">d%yyyy%/tdc/mdu/deltat_tdc_dolly_%rrrr%.mdu</run_name_template>" << std::endl;
951 fout << " <!-- Flame/PSI -->" << std::endl;
952 fout << " <run_name_template inst=\"flame\">d%yyyy%/tdc/root/deltat_tdc_flame_%yyyy%_%rrrr%.root</run_name_template>" << std::endl;
953 fout << " <run_name_template inst=\"flame\">d%yyyy%/tdc/deltat_tdc_flame_%rrrr%.bin</run_name_template>" << std::endl;
954 fout << " <run_name_template inst=\"flame\">d%yyyy%/tdc/mdu/deltat_tdc_flame_%yyyy%_%rrrr%.mdu</run_name_template>" << std::endl;
955 fout << " <!-- GPD/PSI -->" << std::endl;
956 fout << " <run_name_template inst=\"gpd\">d%yyyy%/tdc/root/deltat_tdc_gpd_%yyyy%_%rrrr%.root</run_name_template>" << std::endl;
957 fout << " <run_name_template inst=\"gpd\">d%yyyy%/deltat_mue1_%rrrr%.bin</run_name_template>" << std::endl;
958 fout << " <run_name_template inst=\"gpd\">d%yyyy%/deltat_fq_si_%rrrr%.bin</run_name_template>" << std::endl;
959 fout << " <run_name_template inst=\"gpd\">d%yyyy%/deltat_strobo_%rrrr%.bin</run_name_template>" << std::endl;
960 fout << " <run_name_template inst=\"gpd\">d%yyyy%/deltat_hp_ni_ht_%rrrr%.bin</run_name_template>" << std::endl;
961 fout << " <run_name_template inst=\"gpd\">d%yyyy%/deltat_hp_ni_%rrrr%.bin</run_name_template>" << std::endl;
962 fout << " <run_name_template inst=\"gpd\">d%yyyy%/deltat_ccr2_%rrrr%.bin</run_name_template>" << std::endl;
963 fout << " <run_name_template inst=\"gpd\">d%yyyy%/deltat_gpd_%rrrr%.bin</run_name_template>" << std::endl;
964 fout << " <run_name_template inst=\"gpd\">d%yyyy%/deltat_janis_%rrrr%.bin</run_name_template>" << std::endl;
965 fout << " <run_name_template inst=\"gpd\">d%yyyy%/deltat_janis_gpd_%rrrr%.bin</run_name_template>" << std::endl;
966 fout << " <run_name_template inst=\"gpd\">d%yyyy%/deltat_pta_gpd_%rrrr%.bin</run_name_template>" << std::endl;
967 fout << " <run_name_template inst=\"gpd\">d%yyyy%/pta/deltat_pta_gpd_%rrrr%.bin</run_name_template>" << std::endl;
968 fout << " <run_name_template inst=\"gpd\">d%yyyy%/tdc/deltat_tdc_gpd_%rrrr%.bin</run_name_template>" << std::endl;
969 fout << " <run_name_template inst=\"gpd\">d%yyyy%/tdc/mdu/deltat_tdc_gpd_%rrrr%.mdu</run_name_template>" << std::endl;
970 fout << " <!-- GPS/PSI -->" << std::endl;
971 fout << " <run_name_template inst=\"gps\">d%yyyy%/tdc/root/deltat_tdc_gps_%yyyy%_%rrrr%.root</run_name_template>" << std::endl;
972 fout << " <run_name_template inst=\"gps\">d%yyyy%/deltat_ccr_%rrrr%.bin</run_name_template>" << std::endl;
973 fout << " <run_name_template inst=\"gps\">d%yyyy%/deltat_he3_%rrrr%.bin</run_name_template>" << std::endl;
974 fout << " <run_name_template inst=\"gps\">d%yyyy%/deltat_stutt_%rrrr%.bin</run_name_template>" << std::endl;
975 fout << " <run_name_template inst=\"gps\">d%yyyy%/deltat_ltf_%rrrr%.bin</run_name_template>" << std::endl;
976 fout << " <run_name_template inst=\"gps\">d%yyyy%/deltat_flc_%rrrr%.bin</run_name_template>" << std::endl;
977 fout << " <run_name_template inst=\"gps\">d%yyyy%/deltat_flc2_%rrrr%.bin</run_name_template>" << std::endl;
978 fout << " <run_name_template inst=\"gps\">d%yyyy%/deltat_oven_%rrrr%.bin</run_name_template>" << std::endl;
979 fout << " <run_name_template inst=\"gps\">d%yyyy%/deltat_oven2_%rrrr%.bin</run_name_template>" << std::endl;
980 fout << " <run_name_template inst=\"gps\">d%yyyy%/deltat_pta_gps_%rrrr%.bin</run_name_template>" << std::endl;
981 fout << " <run_name_template inst=\"gps\">d%yyyy%/tdc/deltat_tdc_gps_%rrrr%.bin</run_name_template>" << std::endl;
982 fout << " <run_name_template inst=\"gps\">d%yyyy%/tdc/mdu/deltat_tdc_gps_%yyyy%_%rrrr%.mdu</run_name_template>" << std::endl;
983 fout << " <!-- HAL-9500/PSI == HIFI/PSI -->" << std::endl;
984 fout << " <run_name_template inst=\"hifi\">d%yyyy%/tdc/root/deltat_tdc_hifi_%yyyy%_%rrrr%.root</run_name_template>" << std::endl;
985 fout << " <run_name_template inst=\"hifi\">d%yyyy%/tdc/deltat_hifi_%rrrr%.bin</run_name_template>" << std::endl;
986 fout << " <run_name_template inst=\"hifi\">d%yyyy%/tdc/tdc_hifi_%yyyy%_%rrrrr%.mdu</run_name_template>" << std::endl;
987 fout << " <run_name_template inst=\"hifi\">d%yyyy%/tdc/root/deltat_tdc_hifi_%yyyy%_%rrrr%.mdu</run_name_template>" << std::endl;
988 fout << " <!-- LTF/PSI -->" << std::endl;
989 fout << " <run_name_template inst=\"ltf\">d%yyyy%/deltat_ltf_%rrrr%.bin</run_name_template>" << std::endl;
990 fout << " <run_name_template inst=\"ltf\">d%yyyy%/deltat_ltf2_%rrrr%.bin</run_name_template>" << std::endl;
991 fout << " <run_name_template inst=\"ltf\">d%yyyy%/deltat_pta_ltf_%rrrr%.bin</run_name_template>" << std::endl;
992 fout << " <run_name_template inst=\"ltf\">d%yyyy%/pta/deltat_pta_ltf_%rrrr%.bin</run_name_template>" << std::endl;
993 fout << " <run_name_template inst=\"ltf\">d%yyyy%/tdc/deltat_tdc_ltf_%rrrr%.bin</run_name_template>" << std::endl;
994 fout << " <!-- LEM/PSI -->" << std::endl;
995 fout << " <run_name_template inst=\"lem\">%yyyy%/lem%yy%_his_%rrrr%.root</run_name_template>" << std::endl;
996 fout << " <run_name_template inst=\"lem\">d%yyyy%/tdc/lem%yy%_his_%rrrr%.root</run_name_template>" << std::endl;
997 fout << " <run_name_template inst=\"lem\">%yyyy%/lem%yy%_his_%rrrrr%.root</run_name_template>" << std::endl;
998 fout << " <run_name_template inst=\"lem\">d%yyyy%/tdc/lem%yy%_his_%rrrrr%.root</run_name_template>" << std::endl;
999 fout << " <fourier_settings>" << std::endl;
1000 fout << " <units>Gauss</units>" << std::endl;
1001 fout << " <fourier_power>0</fourier_power>" << std::endl;
1002 fout << " <apodization>none</apodization>" << std::endl;
1003 fout << " <plot>real_and_imag</plot>" << std::endl;
1004 fout << " <phase>0.0</phase>" << std::endl;
1005 fout << " <phase_increment>1.0</phase_increment>" << std::endl;
1006 fout << " </fourier_settings>" << std::endl;
1007 fout << " <root_settings>" << std::endl;
1008 fout << " <marker_list>" << std::endl;
1009 fout << " <!-- Root marker numbers -->" << std::endl;
1010 fout << " <marker>24</marker> <!-- open circle -->" << std::endl;
1011 fout << " <marker>25</marker> <!-- open square -->" << std::endl;
1012 fout << " <marker>26</marker> <!-- open triangle -->" << std::endl;
1013 fout << " <marker>27</marker> <!-- open diamond -->" << std::endl;
1014 fout << " <marker>28</marker> <!-- open cross -->" << std::endl;
1015 fout << " <marker>29</marker> <!-- full star -->" << std::endl;
1016 fout << " <marker>30</marker> <!-- open star -->" << std::endl;
1017 fout << " <marker>20</marker> <!-- full circle -->" << std::endl;
1018 fout << " <marker>21</marker> <!-- full square -->" << std::endl;
1019 fout << " <marker>22</marker> <!-- full triangle -->" << std::endl;
1020 fout << " <marker>23</marker> <!-- full triangle down -->" << std::endl;
1021 fout << " <marker>2</marker> <!-- thin cross -->" << std::endl;
1022 fout << " <marker>3</marker> <!-- thin star -->" << std::endl;
1023 fout << " <marker>5</marker> <!-- thin x -->" << std::endl;
1024 fout << " </marker_list>" << std::endl;
1025 fout << " <color_list>" << std::endl;
1026 fout << " <!-- Color as RGB coded string -->" << std::endl;
1027 fout << " <color>0,0,0</color> <!-- kBlack -->" << std::endl;
1028 fout << " <color>255,0,0</color> <!-- kRed -->" << std::endl;
1029 fout << " <color>0,153,0</color> <!-- kGreen+2 -->" << std::endl;
1030 fout << " <color>0,0,255</color> <!-- kBlue -->" << std::endl;
1031 fout << " <color>255,0,255</color> <!-- kMagenta -->" << std::endl;
1032 fout << " <color>0,255,255</color> <!-- kCyan -->" << std::endl;
1033 fout << " <color>153,0,255</color> <!-- kViolet-3 -->" << std::endl;
1034 fout << " <color>102,102,51</color> <!-- kYellow-1 -->" << std::endl;
1035 fout << " <color>51,102,51</color> <!-- kGreen-1 -->" << std::endl;
1036 fout << " <color>153,0,0</color> <!-- kRed+2 -->" << std::endl;
1037 fout << " </color_list>" << std::endl;
1038 fout << " </root_settings>" << std::endl;
1039 fout << "</musrfit>" << std::endl;
1040
1041 fout.close();
1042
1043 return true;
1044}
1045
1046// -------------------------------------------------------------------------
1047// end
1048// -------------------------------------------------------------------------
1049
#define FOURIER_UNIT_FREQ
Frequency in MHz.
Definition PMusr.h:290
#define FOURIER_PLOT_REAL_AND_IMAG
Plot both real and imaginary components (default)
Definition PMusr.h:328
#define FOURIER_UNIT_GAUSS
Magnetic field in Gauss (G)
Definition PMusr.h:286
#define FOURIER_PLOT_POWER
Plot power spectrum |F(ω)|²
Definition PMusr.h:330
#define FOURIER_PLOT_REAL
Plot real component only.
Definition PMusr.h:324
#define FOURIER_APOD_WEAK
Weak apodization (gentle windowing)
Definition PMusr.h:308
#define FOURIER_APOD_NONE
No apodization (rectangular window)
Definition PMusr.h:306
#define FOURIER_UNIT_CYCLES
Angular frequency in Mc/s (Mega-cycles per second)
Definition PMusr.h:292
#define FOURIER_APOD_STRONG
Strong apodization (heavy windowing for best frequency resolution)
Definition PMusr.h:312
#define FOURIER_PLOT_IMAG
Plot imaginary component only.
Definition PMusr.h:326
#define FOURIER_APOD_MEDIUM
Medium apodization (moderate windowing)
Definition PMusr.h:310
#define FOURIER_PLOT_PHASE
Plot phase spectrum arg(F(ω))
Definition PMusr.h:332
#define FOURIER_UNIT_TESLA
Magnetic field in Tesla (T)
Definition PMusr.h:288
const char * startup_path_name
ClassImpQ(PStartupHandler) int parseXmlFile(TSAXParser *saxParser
Replacement for TSAXParser::ParseFile() that uses buffer-based parsing.
char * xmlBuffer
std::fstream xmlFile
if(xmlFile.is_open())
return status
unsigned int xmlSize
int parseXmlFile(TSAXParser *, const char *)
Replacement function for TSAXParser::ParseFile().
Handles the musrfit XML startup configuration file (musrfit_startup.xml).
PRunNameTemplateList fRunNameTemplate
List of instrument-specific run name patterns.
PStartupHandler(bool reset_startup_file=false)
Constructor that locates and parses the musrfit startup configuration file.
virtual void CheckLists()
Validates configuration lists and fills missing entries with defaults.
virtual void OnComment(const Char_t *)
SAX callback: Called when XML comment is found (unused).
PIntVector fColorList
List of ROOT TColor codes (from RGB) for plotting.
PStringVector fDataPathList
List of directories to search for data files.
Bool_t fStartupFileFound
True if musrfit_startup.xml was located.
virtual void OnWarning(const Char_t *)
SAX callback: Called when XML parser issues a warning.
virtual void OnError(const Char_t *)
SAX callback: Called when XML parser encounters an error.
virtual void OnFatalError(const Char_t *)
SAX callback: Called when XML parser encounters a fatal error.
EKeyWords fKey
Current XML element type (SAX parser state)
TString fStartupFilePath
Full path to located startup file (empty if not found)
@ eApodization
Inside <apodization> element (none/weak/medium/strong)
@ eFourierPower
Inside <fourier_power> element (0-20)
@ eEmpty
No active element (between elements or unknown)
@ eMarker
Inside <marker> element (ROOT marker code)
@ ePhaseIncrement
Inside <phase_increment> element (degrees per step)
@ eUnits
Inside <units> element (Gauss/Tesla/MHz/Mc/s)
@ ePhase
Inside <phase> element (degrees)
@ ePlot
Inside <plot> element (real/imag/real_and_imag/power/phase)
@ eColor
Inside <color> element (RGB comma-separated)
@ eRunNameTemplate
Inside <run_name_template> element.
@ eDataPath
Inside <data_path> element.
TString fCurrentInstrumentName
Instrument name from run_name_template inst attribute.
virtual void OnEndElement(const Char_t *)
SAX callback: Called when an XML end element is encountered.
virtual void OnCharacters(const Char_t *)
SAX callback: Called with element text content.
PIntVector fMarkerList
List of ROOT TMarker style codes for plotting.
virtual ~PStartupHandler()
Destructor releasing allocated resources.
virtual void OnEndDocument()
SAX callback: Called when XML document parsing ends. Triggers CheckLists() to ensure all required set...
Bool_t WriteDefaultStartupFile(bool reset_startup_file=false)
Creates or overwrites a startup file with default configuration.
virtual void OnCdataBlock(const Char_t *, Int_t)
SAX callback: Called for CDATA blocks (unused).
PMsrFourierStructure fFourierDefaults
Fourier transform default settings structure.
virtual void OnStartElement(const Char_t *, const TList *)
SAX callback: Called when an XML start element is encountered.
virtual void OnStartDocument()
SAX callback: Called when XML document parsing begins. Initializes all configuration variables to def...
Bool_t StartupFileExists(Char_t *fln)
Checks if a file exists at the specified path.
TString runNameTemplate
File path template with placeholders (r=run, y=year)
Definition PMusr.h:1465
TString instrument
Instrument identifier (e.g., "GPS", "LEM", "DOLLY")
Definition PMusr.h:1464