musrfit 1.10.0
TMusrRunHeader.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 TMusrRunHeader.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 <cstdlib>
31#include <ctime>
32#include <iostream>
33#include <iomanip>
34#include <memory>
35
36#include "TMusrRunHeader.h"
37
38#include <TPaveText.h>
39#include <TCanvas.h>
40#include <TObjArray.h>
41#include <TObjString.h>
42#include <TString.h>
43#include <TList.h>
44#include <TMap.h>
45#include <TKey.h>
46
48
49//--------------------------------------------------------------------------
50// Constructor
51//--------------------------------------------------------------------------
56{
57 fLabel = "n/a";
58 fDemand = MRH_UNDEFINED;
59 fValue = MRH_UNDEFINED;
60 fError = MRH_UNDEFINED;
61 fUnit = "n/a";
62 fDescription = "n/a";
63}
64
65//--------------------------------------------------------------------------
66// Constructor
67//--------------------------------------------------------------------------
78TMusrRunPhysicalQuantity::TMusrRunPhysicalQuantity(TString label, Double_t demand, Double_t value, Double_t error, TString unit, TString description) :
79 TObject(), fLabel(label), fDemand(demand), fValue(value), fError(error), fUnit(unit)
80{
81 if (description.IsWhitespace())
82 fDescription = "n/a";
83 else
84 fDescription = description;
85}
86
87//--------------------------------------------------------------------------
88// Constructor
89//--------------------------------------------------------------------------
99TMusrRunPhysicalQuantity::TMusrRunPhysicalQuantity(TString label, Double_t demand, Double_t value, TString unit, TString description) :
100 TObject(), fLabel(label), fDemand(demand), fValue(value), fUnit(unit)
101{
103 if (description.IsWhitespace())
104 fDescription = "n/a";
105 else
106 fDescription = description;
107}
108
109//--------------------------------------------------------------------------
110// Constructor
111//--------------------------------------------------------------------------
120TMusrRunPhysicalQuantity::TMusrRunPhysicalQuantity(TString label, Double_t value, TString unit, TString description) :
121 TObject(), fLabel(label), fValue(value), fUnit(unit)
122{
125 if (description.IsWhitespace())
126 fDescription = "n/a";
127 else
128 fDescription = description;
129}
130
131//--------------------------------------------------------------------------
132// Set (public)
133//--------------------------------------------------------------------------
144void TMusrRunPhysicalQuantity::Set(TString label, Double_t demand, Double_t value, Double_t error, TString unit, TString description)
145{
146 fLabel = label;
147 fDemand = demand;
148 fValue = value;
149 fError = error;
150 fUnit = unit;
151 if (description.IsWhitespace())
152 fDescription = "n/a";
153 else
154 fDescription = description;
155}
156
157//--------------------------------------------------------------------------
158// Set (public)
159//--------------------------------------------------------------------------
169void TMusrRunPhysicalQuantity::Set(TString label, Double_t demand, Double_t value, TString unit, TString description)
170{
171 fLabel = label;
172 fDemand = demand;
173 fValue = value;
175 fUnit = unit;
176 if (description.IsWhitespace())
177 fDescription = "n/a";
178 else
179 fDescription = description;
180}
181
182//--------------------------------------------------------------------------
183// Set (public)
184//--------------------------------------------------------------------------
193void TMusrRunPhysicalQuantity::Set(TString label, Double_t value, TString unit, TString description)
194{
195 fLabel = label;
197 fValue = value;
199 fUnit = unit;
200 if (description.IsWhitespace())
201 fDescription = "n/a";
202 else
203 fDescription = description;
204}
205
206//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
207
209
210//--------------------------------------------------------------------------
211// Constructor
212//--------------------------------------------------------------------------
218TMusrRunHeader::TMusrRunHeader(bool quiet) : TObject(), fQuiet(quiet)
219{
220 Init();
221}
222
223//--------------------------------------------------------------------------
224// Constructor
225//--------------------------------------------------------------------------
232TMusrRunHeader::TMusrRunHeader(const char *fileName, bool quiet) : TObject()
233{
234 fQuiet = quiet;
235 Init(TString(fileName));
236}
237
238//--------------------------------------------------------------------------
239// Init (private)
240//--------------------------------------------------------------------------
246void TMusrRunHeader::Init(TString fileName)
247{
249
250 fFileName = fileName;
251 fVersion = TString("git-sha: dae9ef0ffba4");
252 Set("RunInfo/Version", fVersion);
253 Set("RunInfo/Generic Validator URL", "http://lmu.web.psi.ch/facilities/software/MusrRoot/validation/MusrRoot.xsd");
254 Set("RunInfo/Specific Validator URL", "n/a");
255 Set("RunInfo/Generator", "n/a");
256 Set("RunInfo/Proposal Number", -1);
257 Set("RunInfo/Main Proposer", "n/a");
258 Set("RunInfo/File Name", "n/a");
259 Set("RunInfo/Run Title", "n/a");
260 Set("RunInfo/Run Number", -1);
261 Set("RunInfo/Run Start Time", "1970-01-01 00:00:00");
262 Set("RunInfo/Run Stop Time", "1970-01-01 00:00:00");
263 prop.Set("Run Duration", 0.0, "sec");
264 Set("RunInfo/Run Duration", prop);
265 Set("RunInfo/Laboratory", "n/a");
266 Set("RunInfo/Instrument", "n/a");
267 prop.Set("Muon Beam Momentum", 0.0, "MeV/c");
268 Set("RunInfo/Muon Beam Momentum", prop);
269 Set("RunInfo/Muon Species", "n/a");
270 Set("RunInfo/Muon Source", "n/a");
271 Set("RunInfo/Setup", "n/a");
272 Set("RunInfo/Comment", "n/a");
273 Set("RunInfo/Sample Name", "n/a");
274 prop.Set("Sample Temperature", 0.0, "K");
275 Set("RunInfo/Sample Temperature", prop);
276 prop.Set("Sample Magnetic Field", 1000.0, "T");
277 Set("RunInfo/Sample Magnetic Field", prop);
278 Set("RunInfo/No of Histos", 0);
279 prop.Set("Time Resolution", 0.0, "ns");
280 Set("RunInfo/Time Resolution", prop);
281 std::vector<int> ivec;
282 ivec.push_back(0);
283 Set("RunInfo/RedGreen Offsets", ivec);
284
285 Set("DetectorInfo/Detector001/Name", "n/a");
286 Set("DetectorInfo/Detector001/Histo Number", 0);
287 Set("DetectorInfo/Detector001/Histo Length", 0);
288 Set("DetectorInfo/Detector001/Time Zero Bin", static_cast<Double_t>(0.0));
289 Set("DetectorInfo/Detector001/First Good Bin", 0);
290 Set("DetectorInfo/Detector001/Last Good Bin", 0);
291
292 Set("SampleEnvironmentInfo/Cryo", "n/a");
293
294 Set("MagneticFieldEnvironmentInfo/Magnet Name", "n/a");
295
296 Set("BeamlineInfo/Name", "n/a");
297}
298
299//--------------------------------------------------------------------------
300// Destructor
301//--------------------------------------------------------------------------
309
310//--------------------------------------------------------------------------
311// CleanUp (private)
312//--------------------------------------------------------------------------
317{
318 fStringObj.clear();
319 fIntObj.clear();
320 fDoubleObj.clear();
322 fStringVectorObj.clear();
323 fIntVectorObj.clear();
324 fDoubleVectorObj.clear();
325
326 fPathNameOrder.clear();
327}
328
329//--------------------------------------------------------------------------
330// FillFolder (public)
331//--------------------------------------------------------------------------
341Bool_t TMusrRunHeader::FillFolder(TFolder *folder)
342{
343 TObjArray *oarray;
344 TObjString ostr, *p_ostr;
345 TString path, name, str;
346 Ssiz_t pos=0;
347 bool found=false;
348
349 if (folder == nullptr) {
350 std::cerr << std::endl << ">> TMusrRunHeader::FillFolder(): **ERROR** folder == nullptr!!" << std::endl;
351 return false;
352 }
353
354 folder->SetOwner(); // folder takes ownership of all added objects! This means that the folder object does the cleanup
355
356 // update/generate tree structure in folder
357 for (UInt_t i=0; i<fPathNameOrder.size(); i++) {
358 path=fPathNameOrder[i];
359
360 if (!UpdateFolder(folder, path))
361 return false;
362 }
363
364 // update/generate tree content
365 for (UInt_t i=0; i<fPathNameOrder.size(); i++) {
366 path=fPathNameOrder[i];
367 pos = path.Last('/');
368 if (pos == -1) {
369 std::cerr << std::endl << ">> TMusrRunHeader::FillFolder(): **ERROR** somethig is wrong with the path=" << path << " !!" << std::endl;
370 return false;
371 }
372 path.Remove(pos); // remove the value from the path
373
374 oarray = dynamic_cast<TObjArray*>(FindObject(folder, path));
375 if (!oarray) {
376 std::cerr << std::endl << ">> TMusrRunHeader::FillFolder(): **ERROR** couldn't create header structure!!" << std::endl;
377 return false;
378 }
379
380 // check if <value> is already found in oarray
381 ostr = GetHeaderString(i); // encode the string for the MusrRoot file
382 name = ostr.GetString(); // convert to TString
383 str = GetFirst(name, ':'); // get the first part of the encoded string, i.e. <nnn> - <name>
384 found = false;
385 for (Int_t j=0; j<oarray->GetEntriesFast(); j++) {
386 p_ostr = dynamic_cast<TObjString*>(oarray->At(j));
387 if (p_ostr->GetString().BeginsWith(str)) { // present hence replace
388 oarray->AddAt(ostr.Clone(), j);
389 found = true;
390 break;
391 }
392 }
393 if (!found) {
394 oarray->AddLast(ostr.Clone());
395 }
396 }
397
398 return true;
399}
400
401//--------------------------------------------------------------------------
402// FillDirectory (public)
403//--------------------------------------------------------------------------
413Bool_t TMusrRunHeader::FillDirectory(TDirectory *dir)
414{
415 if (dir == nullptr) {
416 std::cerr << std::endl << ">> TMusrRunHeader::FillDirectory(): **ERROR** dir == nullptr!!" << std::endl;
417 return false;
418 }
419
420 if (!UpdateDirTree(dir))
421 return false;
422
423 // update/generate tree content
424 TString path, name, str;
425 TObjString ostr, *p_ostr;
426 Ssiz_t pos=0;
427 TDirectory *currDir=nullptr;
428 TObjArray *oarray=nullptr;
429 Bool_t found;
430 for (UInt_t i=0; i<fPathNameOrder.size(); i++) {
431 path=fPathNameOrder[i];
432 pos = path.Last('/');
433 if (pos == -1) {
434 std::cerr << std::endl << ">> TMusrRunHeader::FillDirectory(): **ERROR** somethig is wrong with the path=" << path << " !!" << std::endl;
435 return false;
436 }
437 path.Remove(pos); // remove the value from the path
438 dir->cd(path);
439 currDir = dir->CurrentDirectory();
440 if (currDir->GetList()->Last() == nullptr) { // no oarray present, hence create it
441 oarray = new TObjArray();
442 } else {
443 oarray = dynamic_cast<TObjArray*>(currDir->GetList()->First());
444 }
445
446 // check if <value> is already found in oarray
447 ostr = GetHeaderString(i); // encode the string for the MusrRoot file
448 name = ostr.GetString(); // convert to TString
449 str = GetFirst(name, ':'); // get the first part of the encoded string, i.e. <nnn> - <name>
450 found = false;
451 for (Int_t j=0; j<oarray->GetEntriesFast(); j++) {
452 p_ostr = dynamic_cast<TObjString*>(oarray->At(j));
453 if (p_ostr->GetString().BeginsWith(str)) { // present hence replace
454 oarray->AddAt(ostr.Clone(), j);
455 found = true;
456 break;
457 }
458 }
459 if (!found) {
460 oarray->AddLast(ostr.Clone());
461 }
462 oarray->Write();
463 }
464
465 return true;
466}
467
468//--------------------------------------------------------------------------
469// GetTypeOfPath (public)
470//--------------------------------------------------------------------------
478TString TMusrRunHeader::GetTypeOfPath(TString pathName)
479{
480 TString type("undef");
481
482 // find pathName
483 for (Int_t i=0; i<fStringObj.size(); i++) {
484 if (fStringObj[i].GetPathName() == pathName) {
485 type = fStringObj[i].GetType();
486 return type;
487 }
488 }
489 for (Int_t i=0; i<fIntObj.size(); i++) {
490 if (fIntObj[i].GetPathName() == pathName) {
491 type = fIntObj[i].GetType();
492 return type;
493 }
494 }
495 for (Int_t i=0; i<fDoubleObj.size(); i++) {
496 if (fDoubleObj[i].GetPathName() == pathName) {
497 type = fDoubleObj[i].GetType();
498 return type;
499 }
500 }
501 for (Int_t i=0; i<fMusrRunPhysQuantityObj.size(); i++) {
502 if (fMusrRunPhysQuantityObj[i].GetPathName() == pathName) {
503 type = fMusrRunPhysQuantityObj[i].GetType();
504 return type;
505 }
506 }
507 for (Int_t i=0; i<fStringVectorObj.size(); i++) {
508 if (fStringVectorObj[i].GetPathName() == pathName) {
509 type = fStringVectorObj[i].GetType();
510 return type;
511 }
512 }
513 for (Int_t i=0; i<fIntVectorObj.size(); i++) {
514 if (fIntVectorObj[i].GetPathName() == pathName) {
515 type = fIntVectorObj[i].GetType();
516 return type;
517 }
518 }
519 for (Int_t i=0; i<fDoubleVectorObj.size(); i++) {
520 if (fDoubleVectorObj[i].GetPathName() == pathName) {
521 type = fDoubleVectorObj[i].GetType();
522 return type;
523 }
524 }
525
526
527 return type;
528}
529
530//--------------------------------------------------------------------------
531// Get (public)
532//--------------------------------------------------------------------------
540void TMusrRunHeader::Get(TString pathName, TString &value, Bool_t &ok)
541{
542 ok = false;
543
544 for (UInt_t i=0; i<fStringObj.size(); i++) {
545 if (fStringObj[i].GetPathName() == pathName) {
546 value = fStringObj[i].GetValue();
547 ok = true;
548 }
549 }
550}
551
552//--------------------------------------------------------------------------
553// Get (public)
554//--------------------------------------------------------------------------
562void TMusrRunHeader::Get(TString pathName, Int_t &value, Bool_t &ok)
563{
564 ok = false;
565
566 for (UInt_t i=0; i<fIntObj.size(); i++) {
567 if (fIntObj[i].GetPathName() == pathName) {
568 value = fIntObj[i].GetValue();
569 ok = true;
570 }
571 }
572}
573
574//--------------------------------------------------------------------------
575// Get (public)
576//--------------------------------------------------------------------------
584void TMusrRunHeader::Get(TString pathName, Double_t &value, Bool_t &ok)
585{
586 ok = false;
587
588 for (UInt_t i=0; i<fDoubleObj.size(); i++) {
589 if (fDoubleObj[i].GetPathName() == pathName) {
590 value = fDoubleObj[i].GetValue();
591 ok = true;
592 }
593 }
594}
595
596//--------------------------------------------------------------------------
597// Get (public)
598//--------------------------------------------------------------------------
606void TMusrRunHeader::Get(TString pathName, TMusrRunPhysicalQuantity &value, Bool_t &ok)
607{
608 ok = false;
609
610 for (UInt_t i=0; i<fMusrRunPhysQuantityObj.size(); i++) {
611 if (fMusrRunPhysQuantityObj[i].GetPathName() == pathName) {
612 value = fMusrRunPhysQuantityObj[i].GetValue();
613 ok = true;
614 }
615 }
616}
617
618//--------------------------------------------------------------------------
619// Get (public)
620//--------------------------------------------------------------------------
628void TMusrRunHeader::Get(TString pathName, TStringVector &value, Bool_t &ok)
629{
630 ok = false;
631
632 for (UInt_t i=0; i<fStringVectorObj.size(); i++) {
633 if (fStringVectorObj[i].GetPathName() == pathName) {
634 value = fStringVectorObj[i].GetValue();
635 ok = true;
636 }
637 }
638}
639
640//--------------------------------------------------------------------------
641// Get (public)
642//--------------------------------------------------------------------------
650void TMusrRunHeader::Get(TString pathName, TIntVector &value, Bool_t &ok)
651{
652 ok = false;
653
654 for (UInt_t i=0; i<fIntVectorObj.size(); i++) {
655 if (fIntVectorObj[i].GetPathName() == pathName) {
656 value = fIntVectorObj[i].GetValue();
657 ok = true;
658 }
659 }
660}
661
662//--------------------------------------------------------------------------
663// Get (public)
664//--------------------------------------------------------------------------
672void TMusrRunHeader::Get(TString pathName, TDoubleVector &value, Bool_t &ok)
673{
674 ok = false;
675
676 for (UInt_t i=0; i<fDoubleVectorObj.size(); i++) {
677 if (fDoubleVectorObj[i].GetPathName() == pathName) {
678 value = fDoubleVectorObj[i].GetValue();
679 ok = true;
680 }
681 }
682}
683
684//--------------------------------------------------------------------------
685// Set (public)
686//--------------------------------------------------------------------------
693void TMusrRunHeader::Set(TString pathName, TString value)
694{
695 // check if pathName is already set, if not add it as a new entry, otherwise replace it
696 UInt_t i=0;
697 for (i=0; i<fStringObj.size(); i++) {
698 if (!fStringObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
699 if (!fQuiet)
700 std::cerr << std::endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << std::endl;
701 fStringObj[i].SetType("TString");
702 fStringObj[i].SetValue(value);
703 break;
704 }
705 }
706
707 // if not found in the previous loop, it is a new object
708 if (i == fStringObj.size()) {
709 // feed object
710 TMusrRunObject<TString> obj(pathName, "TString", value);
711 fStringObj.push_back(obj);
712
713 // feed path-name to keep track of the order
714 fPathNameOrder.push_back(pathName);
715 }
716}
717
718//--------------------------------------------------------------------------
719// Set (public)
720//--------------------------------------------------------------------------
727void TMusrRunHeader::Set(TString pathName, Int_t value)
728{
729 // check if pathName is already set, if not add it as a new entry, otherwise replace it
730 UInt_t i=0;
731 for (i=0; i<fIntObj.size(); i++) {
732 if (!fIntObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
733 if (!fQuiet)
734 std::cerr << std::endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << std::endl;
735 fIntObj[i].SetType("Int_t");
736 fIntObj[i].SetValue(value);
737 break;
738 }
739 }
740
741 // if not found in the previous loop, it is a new object
742 if (i == fIntObj.size()) {
743 // feed object
744 TMusrRunObject<Int_t> obj(pathName, "Int_t", value);
745 fIntObj.push_back(obj);
746
747 // feed path-name to keep track of the order
748 fPathNameOrder.push_back(pathName);
749 }
750}
751
752//--------------------------------------------------------------------------
753// Set (public)
754//--------------------------------------------------------------------------
761void TMusrRunHeader::Set(TString pathName, Double_t value)
762{
763 // check if pathName is already set, if not add it as a new entry, otherwise replace it
764 UInt_t i=0;
765 for (i=0; i<fDoubleObj.size(); i++) {
766 if (!fDoubleObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
767 if (!fQuiet)
768 std::cerr << std::endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << std::endl;
769 fDoubleObj[i].SetType("Double_t");
770 fDoubleObj[i].SetValue(value);
771 break;
772 }
773 }
774
775 // if not found in the previous loop, it is a new object
776 if (i == fDoubleObj.size()) {
777 // feed object
778 TMusrRunObject<Double_t> obj(pathName, "Double_t", value);
779 fDoubleObj.push_back(obj);
780
781 // feed path-name to keep track of the order
782 fPathNameOrder.push_back(pathName);
783 }
784}
785
786//--------------------------------------------------------------------------
787// Set (public)
788//--------------------------------------------------------------------------
796{
797 // check if pathName is already set, if not add it as a new entry, otherwise replace it
798 UInt_t i=0;
799 for (i=0; i<fMusrRunPhysQuantityObj.size(); i++) {
800 if (!fMusrRunPhysQuantityObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
801 if (!fQuiet)
802 std::cerr << std::endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << std::endl;
803 fMusrRunPhysQuantityObj[i].SetType("TMusrRunHeader");
804 fMusrRunPhysQuantityObj[i].SetValue(value);
805 break;
806 }
807 }
808
809 // if not found in the previous loop, it is a new object
810 if (i == fMusrRunPhysQuantityObj.size()) {
811 // feed object
812 TMusrRunObject<TMusrRunPhysicalQuantity> obj(pathName, "TMusrRunPhysicalQuantity", value);
813 fMusrRunPhysQuantityObj.push_back(obj);
814
815 // feed path-name to keep track of the order
816 fPathNameOrder.push_back(pathName);
817 }
818}
819
820//--------------------------------------------------------------------------
821// Set (public)
822//--------------------------------------------------------------------------
829void TMusrRunHeader::Set(TString pathName, TStringVector value)
830{
831 // check if pathName is already set, if not add it as a new entry, otherwise replace it
832 UInt_t i=0;
833 for (i=0; i<fStringVectorObj.size(); i++) {
834 if (!fStringVectorObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
835 if (!fQuiet)
836 std::cerr << std::endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << std::endl;
837 fStringVectorObj[i].SetType("TStringVector");
838 fStringVectorObj[i].SetValue(value);
839 break;
840 }
841 }
842
843 // if not found in the previous loop, it is a new object
844 if (i == fStringVectorObj.size()) {
845 // feed object
846 TMusrRunObject<TStringVector> obj(pathName, "TStringVector", value);
847 fStringVectorObj.push_back(obj);
848
849 // feed path-name to keep track of the order
850 fPathNameOrder.push_back(pathName);
851 }
852}
853
854//--------------------------------------------------------------------------
855// Set (public)
856//--------------------------------------------------------------------------
863void TMusrRunHeader::Set(TString pathName, TIntVector value)
864{
865 // check if pathName is already set, if not add it as a new entry, otherwise replace it
866 UInt_t i=0;
867 for (i=0; i<fIntVectorObj.size(); i++) {
868 if (!fIntVectorObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
869 if (!fQuiet)
870 std::cerr << std::endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << std::endl;
871 fIntVectorObj[i].SetType("TIntVector");
872 fIntVectorObj[i].SetValue(value);
873 break;
874 }
875 }
876
877 // if not found in the previous loop, it is a new object
878 if (i == fIntVectorObj.size()) {
879 // feed object
880 TMusrRunObject<TIntVector> obj(pathName, "TIntVector", value);
881 fIntVectorObj.push_back(obj);
882
883 // feed path-name to keep track of the order
884 fPathNameOrder.push_back(pathName);
885 }
886}
887
888//--------------------------------------------------------------------------
889// Set (public)
890//--------------------------------------------------------------------------
897void TMusrRunHeader::Set(TString pathName, TDoubleVector value)
898{
899 // check if pathName is already set, if not add it as a new entry, otherwise replace it
900 UInt_t i=0;
901 for (i=0; i<fDoubleVectorObj.size(); i++) {
902 if (!fDoubleVectorObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
903 if (!fQuiet)
904 std::cerr << std::endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << std::endl;
905 fDoubleVectorObj[i].SetType("TDoubleVector");
906 fDoubleVectorObj[i].SetValue(value);
907 break;
908 }
909 }
910
911 // if not found in the previous loop, it is a new object
912 if (i == fDoubleVectorObj.size()) {
913 // feed object
914 TMusrRunObject<TDoubleVector> obj(pathName, "TDoubleVector", value);
915 fDoubleVectorObj.push_back(obj);
916
917 // feed path-name to keep track of the order
918 fPathNameOrder.push_back(pathName);
919 }
920}
921
922
923//--------------------------------------------------------------------------
924// ExtractAll (public)
925//--------------------------------------------------------------------------
934Bool_t TMusrRunHeader::ExtractAll(TFolder *folder)
935{
936 TIter next(folder->GetListOfFolders());
937 TObjArray* entry;
938
939 // clean up all internal structures - just in case this is called multiple times
940 CleanUp();
941
942 while ((entry = dynamic_cast<TObjArray*>(next()))) {
943 ExtractHeaderInformation(entry, entry->GetName());
944 }
945
946 return true;
947}
948
949//--------------------------------------------------------------------------
950// ExtractAll (public)
951//--------------------------------------------------------------------------
960Bool_t TMusrRunHeader::ExtractAll(TDirectory *dir)
961{
962 TIter next(dir->GetListOfKeys());
963 TKey *key;
964 TObjString *entry;
965
966 // clean up all internal structures - just in case this is called multiple times
967 if (!strcmp(dir->GetName(), "RunHeader")) {
968 CleanUp();
969 }
970
971 while ((key = (TKey*)next())) {
972 if (strcmp(key->GetClassName(), "TDirectoryFile") == 0) {
973 TDirectory *subdir = (TDirectory*)key->ReadObj();
974 ExtractAll(subdir);
975 } else if (strcmp(key->GetClassName(), "TObjString") == 0) {
976 entry = (TObjString*)key->ReadObj();
977 TString str = dir->GetPath();
978 Ssiz_t start_idx = str.Index("RunHeader/");
979 start_idx += 10; // got to end of 'RunHeader/'
980 ExtractHeaderInformationData(entry, str(start_idx, str.Length()-start_idx));
981 }
982 }
983
984 return true;
985}
986
987
988//--------------------------------------------------------------------------
989// ExtractHeaderInformationData (public)
990//--------------------------------------------------------------------------
999Bool_t TMusrRunHeader::ExtractHeaderInformationData(TObjString *headerData, TString requestedPath)
1000{
1001 TString label(""), pathName(""), str(""), strValue(""), type("");
1002 TObjString *ostr = nullptr;
1003 TObjArray *tokens = nullptr;
1004 Ssiz_t idx1;
1005 Int_t intValue;
1006 Double_t dval;
1007
1008 ostr = dynamic_cast<TObjString*>(headerData);
1009 str = ostr->GetString();
1010
1011 // get the run header label
1012 label = GetLabel(str);
1013 if (label == "n/a") // not a TMusrRunHeader object, hence ignore it
1014 return true;
1015
1016 // get the run header 'value'
1017 strValue = GetStrValue(str);
1018
1019 // construct path name
1020 pathName = requestedPath + TString("/") + label;
1021
1022 // get type from map
1023 type = GetType(str);
1024 if (type == "n/a") // not a TMusrRunHeader object, hence ignore it
1025 return true;
1026
1027 if (type == "TString") {
1028 Set(pathName, strValue);
1029 } else if (type == "Int_t") {
1030 intValue = strValue.Atoi();
1031 Set(pathName, intValue);
1032 } else if (type == "Double_t") {
1033 dval = strValue.Atof();
1034 Set(pathName, dval);
1035 } else if (type == "TMusrRunPhysicalQuantity") {
1037 prop.SetLabel(label);
1038
1039 // 1st get the description if present
1040 tokens = strValue.Tokenize(";");
1041 if (tokens == nullptr) {
1042 std::cerr << std::endl << ">> **ERROR** Couldn't tokenize entry in Bool_t TMusrRunHeader::ExtractHeaderInformationData(TObjString *headerData, TString requestedPath)" << std::endl;
1043 return false;
1044 }
1045
1046 switch (tokens->GetEntries()) {
1047 case 2:
1048 ostr = dynamic_cast<TObjString*>(tokens->At(1));
1049 str = ostr->GetString();
1050 if (!str.Contains("SP:")) { // make sure that it is not a demand value token
1051 prop.SetDescription(str);
1052 }
1053 break;
1054 case 3:
1055 ostr = dynamic_cast<TObjString*>(tokens->At(2));
1056 str = ostr->GetString();
1057 break;
1058 default:
1059 break;
1060 }
1061
1062 if (tokens) {
1063 delete tokens;
1064 tokens = nullptr;
1065 }
1066
1067 // 2nd collect all the other properties, this is easier when first a potential description is removed
1068 idx1 = strValue.Last(';');
1069 if (idx1 > 0) {
1070 TString last("");
1071 for (Int_t i=idx1+2; i<strValue.Length(); i++)
1072 last += strValue[i];
1073 // check if last is <description> or SP: <demand>
1074 if (!last.Contains("SP:")) {
1075 str = "";
1076 for (Int_t i=0; i<idx1; i++)
1077 str += strValue[i];
1078 strValue = str;
1079 }
1080 }
1081
1082 tokens = strValue.Tokenize(" +;");
1083 if (tokens == nullptr) {
1084 std::cerr << std::endl << ">> **ERROR** Couldn't tokenize entry in Bool_t TMusrRunHeader::ExtractHeaderInformationData(TObjString *headerData, TString requestedPath)" << std::endl;
1085 return false;
1086 }
1087
1088 switch (tokens->GetEntries()) {
1089 case 2: // <val> <unit>
1090 ostr = dynamic_cast<TObjString*>(tokens->At(0));
1091 str = ostr->GetString();
1092 prop.SetValue(str.Atof());
1093 ostr = dynamic_cast<TObjString*>(tokens->At(1));
1094 str = ostr->GetString();
1095 prop.SetUnit(str);
1096 break;
1097 case 4: // <val> +- <err> <unit>, or <val> <unit>; SP: <demand>
1098 ostr = dynamic_cast<TObjString*>(tokens->At(0));
1099 str = ostr->GetString();
1100 prop.SetValue(str.Atof());
1101 ostr = dynamic_cast<TObjString*>(tokens->At(1));
1102 str = ostr->GetString();
1103 if (str == "-") { // <val> +- <err> <unit>
1104 ostr = dynamic_cast<TObjString*>(tokens->At(2));
1105 str = ostr->GetString();
1106 prop.SetError(str.Atof());
1107 ostr = dynamic_cast<TObjString*>(tokens->At(3));
1108 str = ostr->GetString();
1109 prop.SetUnit(str);
1110 } else { // <val> <unit>; SP: <demand>
1111 prop.SetUnit(str);
1112 ostr = dynamic_cast<TObjString*>(tokens->At(3));
1113 str = ostr->GetString();
1114 prop.SetDemand(str.Atof());
1115 }
1116 break;
1117 case 6: // <val> +- <err> <unit>; SP: <demand>
1118 ostr = dynamic_cast<TObjString*>(tokens->At(0));
1119 str = ostr->GetString();
1120 prop.SetValue(str.Atof());
1121 ostr = dynamic_cast<TObjString*>(tokens->At(2));
1122 str = ostr->GetString();
1123 prop.SetError(str.Atof());
1124 ostr = dynamic_cast<TObjString*>(tokens->At(3));
1125 str = ostr->GetString();
1126 prop.SetUnit(str);
1127 ostr = dynamic_cast<TObjString*>(tokens->At(5));
1128 str = ostr->GetString();
1129 prop.SetDemand(str.Atof());
1130 break;
1131 default:
1132 break;
1133 }
1134
1135 if (tokens) {
1136 delete tokens;
1137 tokens = nullptr;
1138 }
1139
1140 Set(pathName, prop);
1141 } else if (type == "TStringVector") {
1142 TStringVector svec;
1143 tokens = strValue.Tokenize(";");
1144 if (tokens == nullptr) {
1145 std::cerr << std::endl << ">> **ERROR** Couldn't tokenize entry in Bool_t TMusrRunHeader::ExtractHeaderInformationData(TObjString *headerData, TString requestedPath)" << std::endl;
1146 return false;
1147 }
1148 for (Int_t i=0; i<tokens->GetEntries(); i++) {
1149 ostr = dynamic_cast<TObjString*>(tokens->At(i));
1150 str = ostr->GetString();
1151 str.Remove(TString::kBoth, ' ');
1152 svec.push_back(str);
1153 }
1154 if (tokens) {
1155 delete tokens;
1156 tokens = nullptr;
1157 }
1158 Set(pathName, svec);
1159 } else if (type == "TIntVector") {
1160 TIntVector ivec;
1161 tokens = strValue.Tokenize(";");
1162 if (tokens == nullptr) {
1163 std::cerr << std::endl << ">> **ERROR** Couldn't tokenize entry in Bool_t TMusrRunHeader::ExtractHeaderInformationData(TObjString *headerData, TString requestedPath)" << std::endl;
1164 return false;
1165 }
1166 for (Int_t i=0; i<tokens->GetEntries(); i++) {
1167 ostr = dynamic_cast<TObjString*>(tokens->At(i));
1168 ivec.push_back(ostr->GetString().Atoi());
1169 }
1170 if (tokens) {
1171 delete tokens;
1172 tokens = nullptr;
1173 }
1174 Set(pathName, ivec);
1175 } else if (type == "TDoubleVector") {
1176 TDoubleVector dvec;
1177 tokens = strValue.Tokenize(";");
1178 if (tokens == nullptr) {
1179 std::cerr << std::endl << ">> **ERROR** Couldn't tokenize entry in Bool_t TMusrRunHeader::ExtractHeaderInformationData(TObjString *headerData, TString requestedPath)" << std::endl;
1180 return false;
1181 }
1182 for (Int_t i=0; i<tokens->GetEntries(); i++) {
1183 ostr = dynamic_cast<TObjString*>(tokens->At(i));
1184 dvec.push_back(ostr->GetString().Atof());
1185 }
1186 if (tokens) {
1187 delete tokens;
1188 tokens = nullptr;
1189 }
1190 Set(pathName, dvec);
1191 }
1192
1193 return true;
1194}
1195
1196//--------------------------------------------------------------------------
1197// ExtractHeaderInformation (public)
1198//--------------------------------------------------------------------------
1207Bool_t TMusrRunHeader::ExtractHeaderInformation(TObjArray *headerInfo, TString requestedPath)
1208{
1209 TString label(""), path(""), pathName(""), str(""), strValue(""), type("");
1210 TObjString *ostr = nullptr;
1211 TObjArray *tokens = nullptr;
1212 Ssiz_t idx1;
1213 Int_t intValue;
1214 Double_t dval;
1215
1216 // go through all entries of this header information from the MUSR-ROOT file
1217 for (Int_t i=0; i<headerInfo->GetEntries(); i++) {
1218 // check if entry is a TObjArray, i.e. a sub tree
1219 str = TString(headerInfo->At(i)->ClassName());
1220 if (str == "TObjArray") { // sub tree
1221 path = requestedPath + "/" + TString(headerInfo->At(i)->GetName());
1222 ExtractHeaderInformation(dynamic_cast<TObjArray*>(headerInfo->At(i)), path);
1223 } else { // handle all the rest, i.e. already data
1224 ostr = dynamic_cast<TObjString*>(headerInfo->At(i));
1225 if (!ExtractHeaderInformationData(ostr, requestedPath))
1226 return false;
1227 }
1228 }
1229
1230 return true;
1231}
1232
1233//--------------------------------------------------------------------------
1234// DumpHeader (public)
1235//--------------------------------------------------------------------------
1240{
1241 std::cout << std::endl << "***************************************";
1242 std::cout << std::endl << "header info of file : " << fFileName;
1243 std::cout << std::endl << "***************************************";
1244
1245 TString str(""), tstr(""), fmt(""), path(""), name(""), currentPath("");
1247
1248 for (UInt_t i=0; i<fPathNameOrder.size(); i++) {
1249 // print path if new
1250 SplitPathName(fPathNameOrder[i], path, name);
1251 if (path != currentPath) {
1252 currentPath = path;
1253 std::cout << std::endl << currentPath;
1254 }
1255
1256 // go through all objects and try to find it
1257 // 1st check TString
1258 for (UInt_t j=0; j<fStringObj.size(); j++) {
1259 if (fStringObj[j].GetPathName() == fPathNameOrder[i]) { // found correct object
1260 SplitPathName(fStringObj[j].GetPathName(), path, name);
1261 str.Form(" %03d - %s: %s -@%d", i, name.Data(), fStringObj[j].GetValue().Data(), MRH_TSTRING);
1262 std::cout << std::endl << str;
1263 }
1264 }
1265 // 2nd check Int_t
1266 for (UInt_t j=0; j<fIntObj.size(); j++) {
1267 if (fIntObj[j].GetPathName() == fPathNameOrder[i]) { // found correct object
1268 SplitPathName(fIntObj[j].GetPathName(), path, name);
1269 str.Form(" %03d - %s: %d -@%d", i, name.Data(), fIntObj[j].GetValue(), MRH_INT);
1270 std::cout << std::endl << str;
1271 }
1272 }
1273 // 3rd check Double_t
1274 for (UInt_t j=0; j<fDoubleObj.size(); j++) {
1275 if (fDoubleObj[j].GetPathName() == fPathNameOrder[i]) { // found correct object
1276 SplitPathName(fDoubleObj[j].GetPathName(), path, name);
1277 fmt.Form(" %%03d - %%s: %%.%dlf -@%%d", MRH_DOUBLE_PREC);
1278 str.Form(fmt, i, name.Data(), fDoubleObj[j].GetValue(), MRH_DOUBLE);
1279 std::cout << std::endl << str;
1280 }
1281 }
1282 // 4th check TMusrRunPhysicalQuantity
1283 for (UInt_t j=0; j<fMusrRunPhysQuantityObj.size(); j++) {
1284 if (fMusrRunPhysQuantityObj[j].GetPathName() == fPathNameOrder[i]) { // found correct object
1285 prop = fMusrRunPhysQuantityObj[j].GetValue();
1286 Int_t digit, digit_d;
1287 if ((prop.GetDemand() != MRH_UNDEFINED) && (prop.GetValue() != MRH_UNDEFINED) && (prop.GetError() != MRH_UNDEFINED) &&
1288 (prop.GetUnit() != "n/a")) { // <value> +- <error> <unit>; SP: <demand> [; <description>]
1289 digit = GetDecimalPlace(prop.GetError());
1290 digit_d = GetLeastSignificantDigit(prop.GetDemand());
1291 if (prop.GetDescription() != "n/a") {
1292 fmt.Form("%%s: %%.%dlf +- %%.%dlf %%s; SP: %%.%dlf; %%s", digit, digit, digit_d);
1293 tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetError(), prop.GetUnit().Data(), prop.GetDemand(), prop.GetDescription().Data());
1294 } else {
1295 fmt.Form("%%s: %%.%dlf +- %%.%dlf %%s; SP: %%.%dlf", digit, digit, digit_d);
1296 tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetError(), prop.GetUnit().Data(), prop.GetDemand());
1297 }
1298 } else if ((prop.GetDemand() == MRH_UNDEFINED) && (prop.GetValue() != MRH_UNDEFINED) && (prop.GetError() != MRH_UNDEFINED) &&
1299 (prop.GetUnit() != "n/a")) { // <value> +- <error> <unit> [; <description>]
1300 digit = GetDecimalPlace(prop.GetError());
1301 if (prop.GetDescription() != "n/a") {
1302 fmt.Form("%%s: %%.%dlf +- %%.%dlf %%s; %%s", digit, digit);
1303 tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetError(), prop.GetUnit().Data(), prop.GetDescription().Data());
1304 } else {
1305 fmt.Form("%%s: %%.%dlf +- %%.%dlf %%s", digit, digit);
1306 tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetError(), prop.GetUnit().Data());
1307 }
1308 } else if ((prop.GetDemand() == MRH_UNDEFINED) && (prop.GetValue() != MRH_UNDEFINED) && (prop.GetError() == MRH_UNDEFINED) &&
1309 (prop.GetUnit() != "n/a")) { // <value> <unit> [; <description>]
1310 digit = GetLeastSignificantDigit(prop.GetValue());
1311 if (prop.GetDescription() != "n/a") {
1312 fmt.Form("%%s: %%.%dlf %%s; %%s", digit);
1313 tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data(), prop.GetDescription().Data());
1314 } else {
1315 fmt.Form("%%s: %%.%dlf %%s", digit);
1316 tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data());
1317 }
1318 } else if ((prop.GetDemand() != MRH_UNDEFINED) && (prop.GetValue() != MRH_UNDEFINED) && (prop.GetError() == MRH_UNDEFINED) &&
1319 (prop.GetUnit() != "n/a")) { // <value> <unit>; SP: <demand> [; <description>]
1320 digit = GetLeastSignificantDigit(prop.GetValue());
1321 digit_d = GetLeastSignificantDigit(prop.GetDemand());
1322 if (prop.GetDescription() != "n/a") {
1323 fmt.Form("%%s: %%.%dlf %%s; SP: %%.%dlf; %%s", digit, digit_d);
1324 tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data(), prop.GetDemand(), prop.GetDescription().Data());
1325 } else {
1326 fmt.Form("%%s: %%.%dlf %%s; SP: %%.%dlf", digit, digit_d);
1327 tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data(), prop.GetDemand());
1328 }
1329 } else if (prop.GetValue() == MRH_UNDEFINED) { // <value> = n/a
1330 fmt.Form("%%s: %%s %%s");
1331 if ((prop.GetUnit() != "n/a"))
1332 tstr.Form(fmt, prop.GetLabel().Data(), "n/a", prop.GetUnit().Data());
1333 else
1334 tstr.Form(fmt, prop.GetLabel().Data(), "n/a", "n/a");
1335 }
1336 str.Form(" %03d - %s -@%d", i, tstr.Data(), MRH_TMUSR_RUN_PHYSICAL_QUANTITY);
1337 std::cout << std::endl << str;
1338 }
1339 }
1340 // 5th check TStringVector
1341 for (UInt_t j=0; j<fStringVectorObj.size(); j++) {
1342 if (fStringVectorObj[j].GetPathName() == fPathNameOrder[i]) { // found correct object
1343 SplitPathName(fStringVectorObj[j].GetPathName(), path, name);
1344 str.Form(" %03d - %s: ", i, name.Data());
1345 TStringVector vstr = fStringVectorObj[j].GetValue();
1346 for (UInt_t k=0; k<vstr.size()-1; k++)
1347 str += vstr[k] + "; ";
1348 str += vstr[vstr.size()-1];
1349 str += " -@";
1350 str += MRH_TSTRING_VECTOR;
1351 std::cout << std::endl << str;
1352 }
1353 }
1354 // 6th check TIntVector
1355 for (UInt_t j=0; j<fIntVectorObj.size(); j++) {
1356 if (fIntVectorObj[j].GetPathName() == fPathNameOrder[i]) { // found correct object
1357 SplitPathName(fIntVectorObj[j].GetPathName(), path, name);
1358 str.Form(" %03d - %s: ", i, name.Data());
1359 TIntVector vint = fIntVectorObj[j].GetValue();
1360 for (UInt_t k=0; k<vint.size()-1; k++) {
1361 str += vint[k];
1362 str += "; ";
1363 }
1364 str += vint[vint.size()-1];
1365 str += " -@";
1366 str += MRH_INT_VECTOR;
1367 std::cout << std::endl << str;
1368 }
1369 }
1370 // 7th check TDoubleVector
1371 for (UInt_t j=0; j<fDoubleVectorObj.size(); j++) {
1372 if (fDoubleVectorObj[j].GetPathName() == fPathNameOrder[i]) { // found correct object
1373 SplitPathName(fDoubleVectorObj[j].GetPathName(), path, name);
1374 str.Form(" %03d - %s: ", i, name.Data());
1375 TDoubleVector dvec = fDoubleVectorObj[j].GetValue();
1376 TString subStr("");
1377 fmt.Form("%%.%dlf", MRH_DOUBLE_PREC);
1378 for (UInt_t k=0; k<dvec.size()-1; k++) {
1379 subStr.Form(fmt, dvec[k]);
1380 str += subStr;
1381 str += "; ";
1382 }
1383 subStr.Form(fmt, dvec[dvec.size()-1]);
1384 str += subStr;
1385 str += " -@";
1386 str += MRH_DOUBLE_VECTOR;
1387 std::cout << std::endl << str;
1388 }
1389 }
1390 }
1391
1392 std::cout << std::endl;
1393}
1394
1395//--------------------------------------------------------------------------
1396// GetDecimalPlace (private)
1397//--------------------------------------------------------------------------
1408{
1409 UInt_t digit = 0;
1410
1411 if (val < 1.0) {
1412 UInt_t count=1;
1413 do {
1414 val *= 10.0;
1415 if (val > 1.0)
1416 digit = count;
1417 count++;
1418 } while ((digit == 0) && (count < 20));
1419 }
1420
1421 return digit;
1422}
1423
1424//--------------------------------------------------------------------------
1425// GetLeastSignificantDigit (private)
1426//--------------------------------------------------------------------------
1435{
1436 char cstr[1024];
1437 snprintf(cstr, sizeof(cstr), "%.10lf", val);
1438
1439 int i=0, j=0;
1440 for (i=strlen(cstr)-1; i>=0; i--) {
1441 if (cstr[i] != '0')
1442 break;
1443 }
1444
1445 for (j=strlen(cstr)-1; j>=0; j--) {
1446 if (cstr[j] == '.')
1447 break;
1448 }
1449 if (j==0) // no decimal point present, e.g. 321
1450 j=i;
1451
1452 return i-j;
1453}
1454
1455//--------------------------------------------------------------------------
1456// SplitPathName (private)
1457//--------------------------------------------------------------------------
1465void TMusrRunHeader::SplitPathName(TString pathName, TString &path, TString &name)
1466{
1467 path = TString("");
1468 name = TString("");
1469 Ssiz_t idx = pathName.Last('/');
1470
1471 for (Int_t i=0; i<idx; i++)
1472 path += pathName[i];
1473
1474 for (Int_t i=idx+1; i<pathName.Length(); i++)
1475 name += pathName[i];
1476}
1477
1478//--------------------------------------------------------------------------
1479// GetLabel (private)
1480//--------------------------------------------------------------------------
1488TString TMusrRunHeader::GetLabel(TString str)
1489{
1490 // get run header label
1491 // the string 'str' should have the structure
1492 // <number> - <runHeader label>: <runHeader string value> -@<encoded data type>
1493
1494 TString label = TString("n/a");
1495 Ssiz_t idx1 = str.First('-');
1496 Ssiz_t idx2 = str.First(':');
1497 if ((idx1 == -1) || (idx2 == -1)) {
1498 if (!fQuiet) {
1499 std::cerr << std::endl << ">> TMusrRunHeader::GetLabel(): **WARNING** str='" << str << "', seems not correctly encoded.";
1500 std::cerr << std::endl << ">> Will omit it." << std::endl;
1501 }
1502 return label;
1503 }
1504
1505 label = TString("");
1506 for (Int_t j=idx1+2; j<idx2; j++)
1507 label += str[j];
1508
1509 return label;
1510}
1511
1512//--------------------------------------------------------------------------
1513// GetStrValue (private)
1514//--------------------------------------------------------------------------
1523{
1524 // get run header string value
1525 // the string 'str' should have the structure
1526 // <number> - <runHeader label>: <runHeader string value> -@<encoded data type>
1527
1528 TString strValue = TString("n/a");
1529 Ssiz_t idx1 = str.First(':');
1530 Ssiz_t idx2 = str.Last('-');
1531 if ((idx1 == -1) || (idx2 == -1)) {
1532 if (!fQuiet) {
1533 std::cerr << std::endl << ">> TMusrRunHeader::GetStrValue(): **WARNING** str='" << str << "', seems not correctly encoded.";
1534 std::cerr << std::endl << ">> Will omit it." << std::endl;
1535 }
1536 return strValue;
1537 }
1538
1539 strValue = TString("");
1540 for (Int_t j=idx1+2; j<idx2-1; j++)
1541 strValue += str[j];
1542
1543 return strValue;
1544}
1545
1546//--------------------------------------------------------------------------
1547// GetType (private)
1548//--------------------------------------------------------------------------
1556TString TMusrRunHeader::GetType(TString str)
1557{
1558 TString result = "n/a";
1559
1560 // the string 'str' should have the structure
1561 // <number> - <runHeader label>: <runHeader string value> -@<encoded data type>
1562 Ssiz_t pos = str.Last('@');
1563
1564 if (pos == -1) { // i.e. NOT found
1565 if (!fQuiet) {
1566 std::cerr << std::endl << ">> TMusrRunHeader::GetType(): **WARNING** str=" << str << " seems to be an invalid MusrROOT run header string.";
1567 std::cerr << std::endl << ">> Will omit it." << std::endl;
1568 }
1569 return result;
1570 }
1571
1572 // filter out the encoded type declaration, i.e. -@<num>, where <num> is the encoded type
1573 TString typeStr(str);
1574 typeStr.Remove(0, pos+1);
1575 Int_t typeVal;
1576 if (!typeStr.IsDigit()) {
1577 std::cerr << std::endl << ">> TMusrRunHeader::GetType(): **ERROR** typeStr=" << typeStr << " is not supported." << std::endl;
1578 return result;
1579 }
1580
1581 typeVal = typeStr.Atoi();
1582
1583 switch (typeVal) {
1584 case MRH_TSTRING:
1585 result = "TString";
1586 break;
1587 case MRH_INT:
1588 result = "Int_t";
1589 break;
1590 case MRH_DOUBLE:
1591 result = "Double_t";
1592 break;
1594 result = "TMusrRunPhysicalQuantity";
1595 break;
1596 case MRH_TSTRING_VECTOR:
1597 result = "TStringVector";
1598 break;
1599 case MRH_INT_VECTOR:
1600 result = "TIntVector";
1601 break;
1602 case MRH_DOUBLE_VECTOR:
1603 result = "TDoubleVector";
1604 break;
1605 default:
1606 std::cerr << std::endl << ">> TMusrRunHeader::GetType(): **ERROR** found unsupport type encoded with: " << typeVal << "." << std::endl;
1607 break;
1608 }
1609
1610 return result;
1611}
1612
1613//--------------------------------------------------------------------------
1614// UpdateFolder (private)
1615//--------------------------------------------------------------------------
1624bool TMusrRunHeader::UpdateFolder(TObject *treeObj, TString path)
1625{
1626 if (path.First('/') == -1) // only value element left, hence nothing to be done
1627 return true;
1628
1629 TString str = GetFirst(path, '/');
1630
1631 TObject *obj = treeObj->FindObject(str);
1632
1633 // remove the first path element
1634 if (!RemoveFirst(path, '/')) {
1635 std::cerr << std::endl << ">> TMusrRunHeader::UpdateFolder(): **ERROR** couldn't tokenize path!!" << std::endl;
1636 return false;
1637 }
1638
1639 if (!obj) { // required object not present, create it
1640 TObjArray *oarray = new TObjArray();
1641 if (oarray == nullptr) {
1642 std::cerr << std::endl << ">> TMusrRunHeader::UpdateFolder(): **ERROR** couldn't create header structure!!" << std::endl;
1643 return false;
1644 }
1645 // set the name of the new TObjArray
1646 oarray->SetName(str);
1647
1648 if (!strcmp(treeObj->ClassName(), "TFolder"))
1649 (dynamic_cast<TFolder*>(treeObj))->Add(oarray);
1650 else // it is a TObjArray
1651 (dynamic_cast<TObjArray*>(treeObj))->AddLast(oarray);
1652
1653 return UpdateFolder(oarray, path);
1654 } else { // object present, hence check rest of the path
1655 return UpdateFolder(obj, path);
1656 }
1657}
1658
1659//--------------------------------------------------------------------------
1660// UpdateDirTree (private)
1661//--------------------------------------------------------------------------
1669bool TMusrRunHeader::UpdateDirTree(TDirectory *topdir)
1670{
1671 if (strcmp(topdir->GetName(), "RunHeader")) {
1672 std::cerr << std::endl << ">> TMusrRunHeader::UpdateDirTree(): **ERROR** top dir has to be named RunHeader, found '" << topdir->GetName() << "' !" << std::endl;
1673 return false;
1674 }
1675
1676 TDirectory *dir;
1677 TObjArray *tok = nullptr;
1678 TObjString *ostr = nullptr;
1679 TString tstr{""};
1680 TObject *obj;
1681 for (TString str : fPathNameOrder) { // loop through all path-names
1682 dir = topdir;
1683 if (tok != nullptr)
1684 delete tok;
1685 tok = str.Tokenize("/");
1686 for (UInt_t i=0; i<tok->GetEntries(); i++) {
1687 ostr = dynamic_cast<TObjString*>(tok->At(i));
1688 tstr = ostr->GetString();
1689 if (i != tok->GetEntries()-1) { // TDirectory
1690 if ((obj = topdir->FindObjectAny(tstr.Data())) == nullptr) { // TDirectory new
1691 TDirectory *ndir = dir->mkdir(tstr.Data());
1692 dir = ndir;
1693 } else { // TDirectory exists
1694 dir = dynamic_cast<TDirectory*>(obj);
1695 }
1696 }
1697 }
1698 }
1699
1700 return true;
1701}
1702
1703//--------------------------------------------------------------------------
1704// FindObject (private)
1705//--------------------------------------------------------------------------
1714TObject* TMusrRunHeader::FindObject(TObject *treeObj, TString path)
1715{
1716 Ssiz_t pos;
1717 TObject *obj=nullptr;
1718
1719 // make sure that treeObj is either TFolder or TObjArray
1720 if (strcmp(treeObj->ClassName(), "TFolder") && strcmp(treeObj->ClassName(), "TObjArray"))
1721 return obj;
1722
1723 pos = path.First('/');
1724 if (pos == -1) { // i.e. no sub-paths anymore
1725 obj = treeObj->FindObject(path);
1726 return obj;
1727 } else { // sub-paths present
1728 TString objName = GetFirst(path, '/'); // get first token of the path <objName0>/<objName1>/.../<objNameN>
1729 obj = treeObj->FindObject(objName);
1730 if (obj) { // object found, check for subPath object
1731 RemoveFirst(path, '/'); // remove first tokens of the path
1732 return FindObject(obj, path);
1733 } else { // object not found
1734 return obj;
1735 }
1736 }
1737}
1738
1739//--------------------------------------------------------------------------
1740// GetHeaderString (private)
1741//--------------------------------------------------------------------------
1750{
1751 TObjString tostr("n/a");
1752
1753 TString str(""), path(""), name(""), fmt(""), tstr("");
1755
1756 // go through all objects and try to find it
1757 // 1st check TString
1758 for (UInt_t j=0; j<fStringObj.size(); j++) {
1759 if (fStringObj[j].GetPathName() == fPathNameOrder[idx]) { // found correct object
1760 SplitPathName(fStringObj[j].GetPathName(), path, name);
1761 str.Form("%03d - %s: %s -@%d", idx, name.Data(), fStringObj[j].GetValue().Data(), MRH_TSTRING);
1762 tostr.SetString(str);
1763 }
1764 }
1765 // 2nd check Int_t
1766 for (UInt_t j=0; j<fIntObj.size(); j++) {
1767 if (fIntObj[j].GetPathName() == fPathNameOrder[idx]) { // found correct object
1768 SplitPathName(fIntObj[j].GetPathName(), path, name);
1769 str.Form("%03d - %s: %d -@%d", idx, name.Data(), fIntObj[j].GetValue(), MRH_INT);
1770 tostr.SetString(str);
1771 }
1772 }
1773 // 3rd check Double_t
1774 for (UInt_t j=0; j<fDoubleObj.size(); j++) {
1775 if (fDoubleObj[j].GetPathName() == fPathNameOrder[idx]) { // found correct object
1776 SplitPathName(fDoubleObj[j].GetPathName(), path, name);
1777 fmt.Form("%%03d - %%s: %%.%dlf -@%%d", MRH_DOUBLE_PREC);
1778 str.Form(fmt, idx, name.Data(), fDoubleObj[j].GetValue(), MRH_DOUBLE);
1779 tostr.SetString(str);
1780 }
1781 }
1782 // 4th check TMusrRunPhysicalQuantity
1783 for (UInt_t j=0; j<fMusrRunPhysQuantityObj.size(); j++) {
1784 if (fMusrRunPhysQuantityObj[j].GetPathName() == fPathNameOrder[idx]) { // found correct object
1785 prop = fMusrRunPhysQuantityObj[j].GetValue();
1786 Int_t digit, digit_d;
1787 if ((prop.GetDemand() != MRH_UNDEFINED) && (prop.GetValue() != MRH_UNDEFINED) && (prop.GetError() != MRH_UNDEFINED) &&
1788 (prop.GetUnit() != "n/a")) { // <value> +- <error> <unit>; SP: <demand> [; <description>]
1789 digit = GetDecimalPlace(prop.GetError());
1790 digit_d = GetLeastSignificantDigit(prop.GetDemand());
1791 if (prop.GetDescription() != "n/a") {
1792 fmt.Form("%%s: %%.%dlf +- %%.%dlf %%s; SP: %%.%dlf; %%s", digit, digit, digit_d);
1793
1794 tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetError(), prop.GetUnit().Data(), prop.GetDemand(), prop.GetDescription().Data());
1795 } else {
1796 fmt.Form("%%s: %%.%dlf +- %%.%dlf %%s; SP: %%.%dlf", digit, digit, digit_d);
1797 tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetError(), prop.GetUnit().Data(), prop.GetDemand());
1798 }
1799 } else if ((prop.GetDemand() == MRH_UNDEFINED) && (prop.GetValue() != MRH_UNDEFINED) && (prop.GetError() != MRH_UNDEFINED) &&
1800 (prop.GetUnit() != "n/a")) { // <value> +- <error> <unit> [; <description>]
1801 digit = GetDecimalPlace(prop.GetError());
1802 if (prop.GetDescription() != "n/a") {
1803 fmt.Form("%%s: %%.%dlf +- %%.%dlf %%s; %%s", digit, digit);
1804 tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetError(), prop.GetUnit().Data(), prop.GetDescription().Data());
1805 } else {
1806 fmt.Form("%%s: %%.%dlf +- %%.%dlf %%s", digit, digit);
1807 tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetError(), prop.GetUnit().Data());
1808 }
1809 } else if ((prop.GetDemand() == MRH_UNDEFINED) && (prop.GetValue() != MRH_UNDEFINED) && (prop.GetError() == MRH_UNDEFINED) &&
1810 (prop.GetUnit() != "n/a")) { // <value> <unit> [; <description>]
1811 digit = GetLeastSignificantDigit(prop.GetValue());
1812 if (prop.GetDescription() != "n/a") {
1813 fmt.Form("%%s: %%.%dlf %%s; %%s", digit);
1814 tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data(), prop.GetDescription().Data());
1815 } else {
1816 fmt.Form("%%s: %%.%dlf %%s", digit);
1817 tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data());
1818 }
1819 } else if ((prop.GetDemand() != MRH_UNDEFINED) && (prop.GetValue() != MRH_UNDEFINED) && (prop.GetError() == MRH_UNDEFINED) &&
1820 (prop.GetUnit() != "n/a")) { // <value> <unit>; SP: <demand> [; <description>]
1821 digit = GetLeastSignificantDigit(prop.GetValue());
1822 digit_d = GetLeastSignificantDigit(prop.GetDemand());
1823 if (prop.GetDescription() != "n/a") {
1824 fmt.Form("%%s: %%.%dlf %%s; SP: %%.%dlf; %%s", digit, digit_d);
1825 tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data(), prop.GetDemand(), prop.GetDescription().Data());
1826 } else {
1827 fmt.Form("%%s: %%.%dlf %%s; SP: %%.%dlf", digit, digit_d);
1828 tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data(), prop.GetDemand());
1829 }
1830 } else if (prop.GetValue() == MRH_UNDEFINED) {
1831 fmt.Form("%%s: %%.1e %%s");
1832 tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data());
1833 }
1834 str.Form("%03d - %s -@%d", idx, tstr.Data(), MRH_TMUSR_RUN_PHYSICAL_QUANTITY);
1835 tostr.SetString(str);
1836 }
1837 }
1838 // 5th check TStringVector
1839 for (UInt_t j=0; j<fStringVectorObj.size(); j++) {
1840 if (fStringVectorObj[j].GetPathName() == fPathNameOrder[idx]) { // found correct object
1841 SplitPathName(fStringVectorObj[j].GetPathName(), path, name);
1842 str.Form("%03d - %s: ", idx, name.Data());
1843 TStringVector vstr = fStringVectorObj[j].GetValue();
1844 for (UInt_t k=0; k<vstr.size()-1; k++)
1845 str += vstr[k] + "; ";
1846 str += vstr[vstr.size()-1];
1847 str += " -@";
1848 str += MRH_TSTRING_VECTOR;
1849 tostr.SetString(str);
1850 }
1851 }
1852 // 6th check TIntVector
1853 for (UInt_t j=0; j<fIntVectorObj.size(); j++) {
1854 if (fIntVectorObj[j].GetPathName() == fPathNameOrder[idx]) { // found correct object
1855 SplitPathName(fIntVectorObj[j].GetPathName(), path, name);
1856 str.Form("%03d - %s: ", idx, name.Data());
1857 TIntVector vint = fIntVectorObj[j].GetValue();
1858 for (UInt_t k=0; k<vint.size()-1; k++) {
1859 str += vint[k];
1860 str += "; ";
1861 }
1862 str += vint[vint.size()-1];
1863 str += " -@";
1864 str += MRH_INT_VECTOR;
1865 tostr.SetString(str);
1866 }
1867 }
1868 // 7th check TDoubleVector
1869 for (UInt_t j=0; j<fDoubleVectorObj.size(); j++) {
1870 if (fDoubleVectorObj[j].GetPathName() == fPathNameOrder[idx]) { // found correct object
1871 SplitPathName(fDoubleVectorObj[j].GetPathName(), path, name);
1872 str.Form("%03d - %s: ", idx, name.Data());
1873 TDoubleVector dvec = fDoubleVectorObj[j].GetValue();
1874 TString subStr("");
1875 fmt.Form("%%.%dlf", MRH_DOUBLE_PREC);
1876 for (UInt_t k=0; k<dvec.size()-1; k++) {
1877 subStr.Form(fmt, dvec[k]);
1878 str += subStr;
1879 str += "; ";
1880 }
1881 subStr.Form(fmt, dvec[dvec.size()-1]);
1882 str += subStr;
1883 str += " -@";
1884 str += MRH_DOUBLE_VECTOR;
1885 tostr.SetString(str);
1886 }
1887 }
1888
1889 return tostr;
1890}
1891
1892//--------------------------------------------------------------------------
1893// RemoveFirst (private)
1894//--------------------------------------------------------------------------
1905bool TMusrRunHeader::RemoveFirst(TString &str, const char splitter)
1906{
1907 Ssiz_t idx = str.First(splitter);
1908 if (idx == -1)
1909 return false;
1910
1911 str.Remove(0, idx+1);
1912
1913 return true;
1914}
1915
1916//--------------------------------------------------------------------------
1917// GetFirst (private)
1918//--------------------------------------------------------------------------
1932TString TMusrRunHeader::GetFirst(TString &str, const char splitter)
1933{
1934 TString result = str;
1935
1936 Ssiz_t idx = str.First(splitter);
1937 if (idx != -1)
1938 result.Remove(idx, str.Length());
1939
1940 return result;
1941}
1942
1943// end ---------------------------------------------------------------------
ClassImp(TMusrRunPhysicalQuantity) TMusrRunPhysicalQuantity
#define MRH_TSTRING
#define MRH_DOUBLE_VECTOR
std::vector< Int_t > TIntVector
#define MRH_DOUBLE
#define MRH_TMUSR_RUN_PHYSICAL_QUANTITY
#define MRH_UNDEFINED
#define MRH_INT_VECTOR
#define MRH_TSTRING_VECTOR
#define MRH_INT
#define MRH_DOUBLE_PREC
std::vector< TString > TStringVector
std::vector< Double_t > TDoubleVector
std::vector< TMusrRunObject< Double_t > > fDoubleObj
virtual TString GetType(TString str)
virtual TString GetFirst(TString &str, const char splitter)
std::vector< TMusrRunObject< TDoubleVector > > fDoubleVectorObj
std::vector< TMusrRunObject< TIntVector > > fIntVectorObj
std::vector< TMusrRunObject< Int_t > > fIntObj
virtual void Set(TString pathName, TString value)
virtual void Init(TString str="n/a")
TMusrRunHeader(bool quiet=false)
std::vector< TMusrRunObject< TStringVector > > fStringVectorObj
virtual TObject * FindObject(TObject *treeObj, TString path)
virtual void Get(TString pathName, TString &value, Bool_t &ok)
virtual void DumpHeader()
virtual UInt_t GetLeastSignificantDigit(Double_t val) const
std::vector< TMusrRunObject< TMusrRunPhysicalQuantity > > fMusrRunPhysQuantityObj
virtual UInt_t GetDecimalPlace(Double_t val)
virtual Bool_t ExtractHeaderInformation(TObjArray *headerInfo, TString path)
virtual bool RemoveFirst(TString &str, const char splitter)
virtual Bool_t FillFolder(TFolder *folder)
virtual bool UpdateDirTree(TDirectory *topdir)
virtual TObjString GetHeaderString(UInt_t idx)
virtual Bool_t ExtractHeaderInformationData(TObjString *headerData, TString path)
virtual TString GetTypeOfPath(TString pathName)
virtual void SplitPathName(TString pathName, TString &path, TString &name)
virtual void CleanUp()
std::vector< TMusrRunObject< TString > > fStringObj
virtual TString GetStrValue(TString str)
std::vector< TString > fPathNameOrder
keeps the path-name as they were created in ordered to keep ordering
virtual Bool_t ExtractAll(TFolder *folder)
virtual TString GetLabel(TString str)
virtual ~TMusrRunHeader()
virtual bool UpdateFolder(TObject *treeObj, TString path)
virtual Bool_t FillDirectory(TDirectory *dir)
virtual Double_t GetDemand() const
TString fUnit
unit of the physical quantity
virtual Double_t GetError() const
virtual void SetDemand(Double_t val)
virtual TString GetLabel() const
virtual void SetDescription(TString &str)
virtual Double_t GetValue() const
Double_t fDemand
demand value of the physical quantity, e.g. temperature setpoint
TString fLabel
property label, like ’Sample Temperature’ etc.
virtual void Set(TString label, Double_t demand, Double_t value, Double_t error, TString unit, TString description=TString("n/a"))
virtual void SetError(Double_t err)
virtual void SetUnit(TString &unit)
Double_t fValue
measured value of the physical quantity
virtual void SetValue(Double_t val)
virtual void SetLabel(TString &label)
TString fDescription
a more detailed description of the physical quantity
Double_t fError
estimated error (standard deviation) of the measured value
virtual TString GetDescription() const
virtual TString GetUnit() const