musrfit  1.9.2
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-2023 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 
47 
48 //--------------------------------------------------------------------------
49 // Constructor
50 //--------------------------------------------------------------------------
55 {
56  fLabel = "n/a";
57  fDemand = MRH_UNDEFINED;
58  fValue = MRH_UNDEFINED;
59  fError = MRH_UNDEFINED;
60  fUnit = "n/a";
61  fDescription = "n/a";
62 }
63 
64 //--------------------------------------------------------------------------
65 // Constructor
66 //--------------------------------------------------------------------------
77 TMusrRunPhysicalQuantity::TMusrRunPhysicalQuantity(TString label, Double_t demand, Double_t value, Double_t error, TString unit, TString description) :
78  TObject(), fLabel(label), fDemand(demand), fValue(value), fError(error), fUnit(unit)
79 {
80  if (description.IsWhitespace())
81  fDescription = "n/a";
82  else
83  fDescription = description;
84 }
85 
86 //--------------------------------------------------------------------------
87 // Constructor
88 //--------------------------------------------------------------------------
98 TMusrRunPhysicalQuantity::TMusrRunPhysicalQuantity(TString label, Double_t demand, Double_t value, TString unit, TString description) :
99  TObject(), fLabel(label), fDemand(demand), fValue(value), fUnit(unit)
100 {
102  if (description.IsWhitespace())
103  fDescription = "n/a";
104  else
105  fDescription = description;
106 }
107 
108 //--------------------------------------------------------------------------
109 // Constructor
110 //--------------------------------------------------------------------------
119 TMusrRunPhysicalQuantity::TMusrRunPhysicalQuantity(TString label, Double_t value, TString unit, TString description) :
120  TObject(), fLabel(label), fValue(value), fUnit(unit)
121 {
124  if (description.IsWhitespace())
125  fDescription = "n/a";
126  else
127  fDescription = description;
128 }
129 
130 //--------------------------------------------------------------------------
131 // Set (public)
132 //--------------------------------------------------------------------------
143 void TMusrRunPhysicalQuantity::Set(TString label, Double_t demand, Double_t value, Double_t error, TString unit, TString description)
144 {
145  fLabel = label;
146  fDemand = demand;
147  fValue = value;
148  fError = error;
149  fUnit = unit;
150  if (description.IsWhitespace())
151  fDescription = "n/a";
152  else
153  fDescription = description;
154 }
155 
156 //--------------------------------------------------------------------------
157 // Set (public)
158 //--------------------------------------------------------------------------
168 void TMusrRunPhysicalQuantity::Set(TString label, Double_t demand, Double_t value, TString unit, TString description)
169 {
170  fLabel = label;
171  fDemand = demand;
172  fValue = value;
174  fUnit = unit;
175  if (description.IsWhitespace())
176  fDescription = "n/a";
177  else
178  fDescription = description;
179 }
180 
181 //--------------------------------------------------------------------------
182 // Set (public)
183 //--------------------------------------------------------------------------
192 void TMusrRunPhysicalQuantity::Set(TString label, Double_t value, TString unit, TString description)
193 {
194  fLabel = label;
196  fValue = value;
198  fUnit = unit;
199  if (description.IsWhitespace())
200  fDescription = "n/a";
201  else
202  fDescription = description;
203 }
204 
205 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
206 
208 
209 //--------------------------------------------------------------------------
210 // Constructor
211 //--------------------------------------------------------------------------
217 TMusrRunHeader::TMusrRunHeader(bool quiet) : TObject(), fQuiet(quiet)
218 {
219  Init();
220 }
221 
222 //--------------------------------------------------------------------------
223 // Constructor
224 //--------------------------------------------------------------------------
231 TMusrRunHeader::TMusrRunHeader(const char *fileName, bool quiet) : TObject()
232 {
233  fQuiet = quiet;
234  Init(TString(fileName));
235 }
236 
237 //--------------------------------------------------------------------------
238 // Init (private)
239 //--------------------------------------------------------------------------
245 void TMusrRunHeader::Init(TString fileName)
246 {
248 
249  fFileName = fileName;
250  fVersion = TString("git-sha: dae9ef0ffba4");
251  Set("RunInfo/Version", fVersion);
252  Set("RunInfo/Generic Validator URL", "http://lmu.web.psi.ch/facilities/software/MusrRoot/validation/MusrRoot.xsd");
253  Set("RunInfo/Specific Validator URL", "n/a");
254  Set("RunInfo/Generator", "n/a");
255  Set("RunInfo/Proposal Number", -1);
256  Set("RunInfo/Main Proposer", "n/a");
257  Set("RunInfo/File Name", "n/a");
258  Set("RunInfo/Run Title", "n/a");
259  Set("RunInfo/Run Number", -1);
260  Set("RunInfo/Run Start Time", "1970-01-01 00:00:00");
261  Set("RunInfo/Run Stop Time", "1970-01-01 00:00:00");
262  prop.Set("Run Duration", 0.0, "sec");
263  Set("RunInfo/Run Duration", prop);
264  Set("RunInfo/Laboratory", "n/a");
265  Set("RunInfo/Instrument", "n/a");
266  prop.Set("Muon Beam Momentum", 0.0, "MeV/c");
267  Set("RunInfo/Muon Beam Momentum", prop);
268  Set("RunInfo/Muon Species", "n/a");
269  Set("RunInfo/Muon Source", "n/a");
270  Set("RunInfo/Setup", "n/a");
271  Set("RunInfo/Comment", "n/a");
272  Set("RunInfo/Sample Name", "n/a");
273  prop.Set("Sample Temperature", 0.0, "K");
274  Set("RunInfo/Sample Temperature", prop);
275  prop.Set("Sample Magnetic Field", 1000.0, "T");
276  Set("RunInfo/Sample Magnetic Field", prop);
277  Set("RunInfo/No of Histos", 0);
278  prop.Set("Time Resolution", 0.0, "ns");
279  Set("RunInfo/Time Resolution", prop);
280  std::vector<int> ivec;
281  ivec.push_back(0);
282  Set("RunInfo/RedGreen Offsets", ivec);
283 
284  Set("DetectorInfo/Detector001/Name", "n/a");
285  Set("DetectorInfo/Detector001/Histo Number", 0);
286  Set("DetectorInfo/Detector001/Histo Length", 0);
287  Set("DetectorInfo/Detector001/Time Zero Bin", static_cast<Double_t>(0.0));
288  Set("DetectorInfo/Detector001/First Good Bin", 0);
289  Set("DetectorInfo/Detector001/Last Good Bin", 0);
290 
291  Set("SampleEnvironmentInfo/Cryo", "n/a");
292 
293  Set("MagneticFieldEnvironmentInfo/Magnet Name", "n/a");
294 
295  Set("BeamlineInfo/Name", "n/a");
296 }
297 
298 //--------------------------------------------------------------------------
299 // Destructor
300 //--------------------------------------------------------------------------
305 {
306  CleanUp();
307 }
308 
309 //--------------------------------------------------------------------------
310 // CleanUp (private)
311 //--------------------------------------------------------------------------
316 {
317  fStringObj.clear();
318  fIntObj.clear();
319  fDoubleObj.clear();
320  fMusrRunPhysQuantityObj.clear();
321  fStringVectorObj.clear();
322  fIntVectorObj.clear();
323  fDoubleVectorObj.clear();
324 
325  fPathNameOrder.clear();
326 }
327 
328 //--------------------------------------------------------------------------
329 // FillFolder (public)
330 //--------------------------------------------------------------------------
338 Bool_t TMusrRunHeader::FillFolder(TFolder *folder)
339 {
340  TObjArray *oarray;
341  TObjString ostr, *p_ostr;
342  TString path, name, str;
343  Ssiz_t pos=0;
344  bool found=false;
345 
346  if (folder == nullptr) {
347  std::cerr << std::endl << ">> TMusrRunHeader::FillFolder(): **ERROR** folder == 0!!" << std::endl;
348  return false;
349  }
350 
351  folder->SetOwner(); // folder takes ownership of all added objects! This means that the folder object does the cleanup
352 
353  // update/generate tree structure in folder
354  for (UInt_t i=0; i<fPathNameOrder.size(); i++) {
355  path=fPathNameOrder[i];
356 
357  if (!UpdateFolder(folder, path))
358  return false;
359  }
360 
361  // update/generate tree content
362  for (UInt_t i=0; i<fPathNameOrder.size(); i++) {
363  path=fPathNameOrder[i];
364  pos = path.Last('/');
365  if (pos == -1) {
366  std::cerr << std::endl << ">> TMusrRunHeader::FillFolder(): **ERROR** somethig is wrong with the path=" << path << " !!" << std::endl;
367  return false;
368  }
369  path.Remove(pos); // remove the value from the path
370 
371  oarray = dynamic_cast<TObjArray*>(FindObject(folder, path));
372  if (!oarray) {
373  std::cerr << std::endl << ">> TMusrRunHeader::FillFolder(): **ERROR** couldn't create header structure!!" << std::endl;
374  return false;
375  }
376 
377  // check if <value> is already found in oarray
378  ostr = GetHeaderString(i); // encode the string for the MusrRoot file
379  name = ostr.GetString(); // convert to TString
380  str = GetFirst(name, ':'); // get the first part of the encoded string, i.e. <nnn> - <name>
381  found = false;
382  for (Int_t j=0; j<oarray->GetEntriesFast(); j++) {
383  p_ostr = dynamic_cast<TObjString*>(oarray->At(j));
384  if (p_ostr->GetString().BeginsWith(str)) { // present hence replace
385  oarray->AddAt(ostr.Clone(), j);
386  found = true;
387  break;
388  }
389  }
390  if (!found) {
391  oarray->AddLast(ostr.Clone());
392  }
393  }
394 
395  return true;
396 }
397 
398 //--------------------------------------------------------------------------
399 // GetTypeOfPath (public)
400 //--------------------------------------------------------------------------
408 TString TMusrRunHeader::GetTypeOfPath(TString pathName)
409 {
410  TString type("undef");
411 
412  // find pathName
413  for (Int_t i=0; i<fStringObj.size(); i++) {
414  if (fStringObj[i].GetPathName() == pathName) {
415  type = fStringObj[i].GetType();
416  return type;
417  }
418  }
419  for (Int_t i=0; i<fIntObj.size(); i++) {
420  if (fIntObj[i].GetPathName() == pathName) {
421  type = fIntObj[i].GetType();
422  return type;
423  }
424  }
425  for (Int_t i=0; i<fDoubleObj.size(); i++) {
426  if (fDoubleObj[i].GetPathName() == pathName) {
427  type = fDoubleObj[i].GetType();
428  return type;
429  }
430  }
431  for (Int_t i=0; i<fMusrRunPhysQuantityObj.size(); i++) {
432  if (fMusrRunPhysQuantityObj[i].GetPathName() == pathName) {
433  type = fMusrRunPhysQuantityObj[i].GetType();
434  return type;
435  }
436  }
437  for (Int_t i=0; i<fStringVectorObj.size(); i++) {
438  if (fStringVectorObj[i].GetPathName() == pathName) {
439  type = fStringVectorObj[i].GetType();
440  return type;
441  }
442  }
443  for (Int_t i=0; i<fIntVectorObj.size(); i++) {
444  if (fIntVectorObj[i].GetPathName() == pathName) {
445  type = fIntVectorObj[i].GetType();
446  return type;
447  }
448  }
449  for (Int_t i=0; i<fDoubleVectorObj.size(); i++) {
450  if (fDoubleVectorObj[i].GetPathName() == pathName) {
451  type = fDoubleVectorObj[i].GetType();
452  return type;
453  }
454  }
455 
456 
457  return type;
458 }
459 
460 //--------------------------------------------------------------------------
461 // Get (public)
462 //--------------------------------------------------------------------------
470 void TMusrRunHeader::Get(TString pathName, TString &value, Bool_t &ok)
471 {
472  ok = false;
473 
474  for (UInt_t i=0; i<fStringObj.size(); i++) {
475  if (fStringObj[i].GetPathName() == pathName) {
476  value = fStringObj[i].GetValue();
477  ok = true;
478  }
479  }
480 }
481 
482 //--------------------------------------------------------------------------
483 // Get (public)
484 //--------------------------------------------------------------------------
492 void TMusrRunHeader::Get(TString pathName, Int_t &value, Bool_t &ok)
493 {
494  ok = false;
495 
496  for (UInt_t i=0; i<fIntObj.size(); i++) {
497  if (fIntObj[i].GetPathName() == pathName) {
498  value = fIntObj[i].GetValue();
499  ok = true;
500  }
501  }
502 }
503 
504 //--------------------------------------------------------------------------
505 // Get (public)
506 //--------------------------------------------------------------------------
514 void TMusrRunHeader::Get(TString pathName, Double_t &value, Bool_t &ok)
515 {
516  ok = false;
517 
518  for (UInt_t i=0; i<fDoubleObj.size(); i++) {
519  if (fDoubleObj[i].GetPathName() == pathName) {
520  value = fDoubleObj[i].GetValue();
521  ok = true;
522  }
523  }
524 }
525 
526 //--------------------------------------------------------------------------
527 // Get (public)
528 //--------------------------------------------------------------------------
536 void TMusrRunHeader::Get(TString pathName, TMusrRunPhysicalQuantity &value, Bool_t &ok)
537 {
538  ok = false;
539 
540  for (UInt_t i=0; i<fMusrRunPhysQuantityObj.size(); i++) {
541  if (fMusrRunPhysQuantityObj[i].GetPathName() == pathName) {
542  value = fMusrRunPhysQuantityObj[i].GetValue();
543  ok = true;
544  }
545  }
546 }
547 
548 //--------------------------------------------------------------------------
549 // Get (public)
550 //--------------------------------------------------------------------------
558 void TMusrRunHeader::Get(TString pathName, TStringVector &value, Bool_t &ok)
559 {
560  ok = false;
561 
562  for (UInt_t i=0; i<fStringVectorObj.size(); i++) {
563  if (fStringVectorObj[i].GetPathName() == pathName) {
564  value = fStringVectorObj[i].GetValue();
565  ok = true;
566  }
567  }
568 }
569 
570 //--------------------------------------------------------------------------
571 // Get (public)
572 //--------------------------------------------------------------------------
580 void TMusrRunHeader::Get(TString pathName, TIntVector &value, Bool_t &ok)
581 {
582  ok = false;
583 
584  for (UInt_t i=0; i<fIntVectorObj.size(); i++) {
585  if (fIntVectorObj[i].GetPathName() == pathName) {
586  value = fIntVectorObj[i].GetValue();
587  ok = true;
588  }
589  }
590 }
591 
592 //--------------------------------------------------------------------------
593 // Get (public)
594 //--------------------------------------------------------------------------
602 void TMusrRunHeader::Get(TString pathName, TDoubleVector &value, Bool_t &ok)
603 {
604  ok = false;
605 
606  for (UInt_t i=0; i<fDoubleVectorObj.size(); i++) {
607  if (fDoubleVectorObj[i].GetPathName() == pathName) {
608  value = fDoubleVectorObj[i].GetValue();
609  ok = true;
610  }
611  }
612 }
613 
614 //--------------------------------------------------------------------------
615 // Set (public)
616 //--------------------------------------------------------------------------
623 void TMusrRunHeader::Set(TString pathName, TString value)
624 {
625  // check if pathName is already set, if not add it as a new entry, otherwise replace it
626  UInt_t i=0;
627  for (i=0; i<fStringObj.size(); i++) {
628  if (!fStringObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
629  if (!fQuiet)
630  std::cerr << std::endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << std::endl;
631  fStringObj[i].SetType("TString");
632  fStringObj[i].SetValue(value);
633  break;
634  }
635  }
636 
637  // if not found in the previous loop, it is a new object
638  if (i == fStringObj.size()) {
639  // feed object
640  TMusrRunObject<TString> obj(pathName, "TString", value);
641  fStringObj.push_back(obj);
642 
643  // feed path-name to keep track of the order
644  fPathNameOrder.push_back(pathName);
645  }
646 }
647 
648 //--------------------------------------------------------------------------
649 // Set (public)
650 //--------------------------------------------------------------------------
657 void TMusrRunHeader::Set(TString pathName, Int_t value)
658 {
659  // check if pathName is already set, if not add it as a new entry, otherwise replace it
660  UInt_t i=0;
661  for (i=0; i<fIntObj.size(); i++) {
662  if (!fIntObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
663  if (!fQuiet)
664  std::cerr << std::endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << std::endl;
665  fIntObj[i].SetType("Int_t");
666  fIntObj[i].SetValue(value);
667  break;
668  }
669  }
670 
671  // if not found in the previous loop, it is a new object
672  if (i == fIntObj.size()) {
673  // feed object
674  TMusrRunObject<Int_t> obj(pathName, "Int_t", value);
675  fIntObj.push_back(obj);
676 
677  // feed path-name to keep track of the order
678  fPathNameOrder.push_back(pathName);
679  }
680 }
681 
682 //--------------------------------------------------------------------------
683 // Set (public)
684 //--------------------------------------------------------------------------
691 void TMusrRunHeader::Set(TString pathName, Double_t value)
692 {
693  // check if pathName is already set, if not add it as a new entry, otherwise replace it
694  UInt_t i=0;
695  for (i=0; i<fDoubleObj.size(); i++) {
696  if (!fDoubleObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
697  if (!fQuiet)
698  std::cerr << std::endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << std::endl;
699  fDoubleObj[i].SetType("Double_t");
700  fDoubleObj[i].SetValue(value);
701  break;
702  }
703  }
704 
705  // if not found in the previous loop, it is a new object
706  if (i == fDoubleObj.size()) {
707  // feed object
708  TMusrRunObject<Double_t> obj(pathName, "Double_t", value);
709  fDoubleObj.push_back(obj);
710 
711  // feed path-name to keep track of the order
712  fPathNameOrder.push_back(pathName);
713  }
714 }
715 
716 //--------------------------------------------------------------------------
717 // Set (public)
718 //--------------------------------------------------------------------------
725 void TMusrRunHeader::Set(TString pathName, TMusrRunPhysicalQuantity value)
726 {
727  // check if pathName is already set, if not add it as a new entry, otherwise replace it
728  UInt_t i=0;
729  for (i=0; i<fMusrRunPhysQuantityObj.size(); i++) {
730  if (!fMusrRunPhysQuantityObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
731  if (!fQuiet)
732  std::cerr << std::endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << std::endl;
733  fMusrRunPhysQuantityObj[i].SetType("TMusrRunHeader");
734  fMusrRunPhysQuantityObj[i].SetValue(value);
735  break;
736  }
737  }
738 
739  // if not found in the previous loop, it is a new object
740  if (i == fMusrRunPhysQuantityObj.size()) {
741  // feed object
742  TMusrRunObject<TMusrRunPhysicalQuantity> obj(pathName, "TMusrRunPhysicalQuantity", value);
743  fMusrRunPhysQuantityObj.push_back(obj);
744 
745  // feed path-name to keep track of the order
746  fPathNameOrder.push_back(pathName);
747  }
748 }
749 
750 //--------------------------------------------------------------------------
751 // Set (public)
752 //--------------------------------------------------------------------------
759 void TMusrRunHeader::Set(TString pathName, TStringVector value)
760 {
761  // check if pathName is already set, if not add it as a new entry, otherwise replace it
762  UInt_t i=0;
763  for (i=0; i<fStringVectorObj.size(); i++) {
764  if (!fStringVectorObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
765  if (!fQuiet)
766  std::cerr << std::endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << std::endl;
767  fStringVectorObj[i].SetType("TStringVector");
768  fStringVectorObj[i].SetValue(value);
769  break;
770  }
771  }
772 
773  // if not found in the previous loop, it is a new object
774  if (i == fStringVectorObj.size()) {
775  // feed object
776  TMusrRunObject<TStringVector> obj(pathName, "TStringVector", value);
777  fStringVectorObj.push_back(obj);
778 
779  // feed path-name to keep track of the order
780  fPathNameOrder.push_back(pathName);
781  }
782 }
783 
784 //--------------------------------------------------------------------------
785 // Set (public)
786 //--------------------------------------------------------------------------
793 void TMusrRunHeader::Set(TString pathName, TIntVector value)
794 {
795  // check if pathName is already set, if not add it as a new entry, otherwise replace it
796  UInt_t i=0;
797  for (i=0; i<fIntVectorObj.size(); i++) {
798  if (!fIntVectorObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
799  if (!fQuiet)
800  std::cerr << std::endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << std::endl;
801  fIntVectorObj[i].SetType("TIntVector");
802  fIntVectorObj[i].SetValue(value);
803  break;
804  }
805  }
806 
807  // if not found in the previous loop, it is a new object
808  if (i == fIntVectorObj.size()) {
809  // feed object
810  TMusrRunObject<TIntVector> obj(pathName, "TIntVector", value);
811  fIntVectorObj.push_back(obj);
812 
813  // feed path-name to keep track of the order
814  fPathNameOrder.push_back(pathName);
815  }
816 }
817 
818 //--------------------------------------------------------------------------
819 // Set (public)
820 //--------------------------------------------------------------------------
827 void TMusrRunHeader::Set(TString pathName, TDoubleVector value)
828 {
829  // check if pathName is already set, if not add it as a new entry, otherwise replace it
830  UInt_t i=0;
831  for (i=0; i<fDoubleVectorObj.size(); i++) {
832  if (!fDoubleVectorObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
833  if (!fQuiet)
834  std::cerr << std::endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << std::endl;
835  fDoubleVectorObj[i].SetType("TDoubleVector");
836  fDoubleVectorObj[i].SetValue(value);
837  break;
838  }
839  }
840 
841  // if not found in the previous loop, it is a new object
842  if (i == fDoubleVectorObj.size()) {
843  // feed object
844  TMusrRunObject<TDoubleVector> obj(pathName, "TDoubleVector", value);
845  fDoubleVectorObj.push_back(obj);
846 
847  // feed path-name to keep track of the order
848  fPathNameOrder.push_back(pathName);
849  }
850 }
851 
852 
853 //--------------------------------------------------------------------------
854 // ExtractAll (public)
855 //--------------------------------------------------------------------------
862 Bool_t TMusrRunHeader::ExtractAll(TFolder *folder)
863 {
864  TIter next(folder->GetListOfFolders());
865  TObjArray* entry;
866 
867  // clean up all internal structures - just in case this is called multiple times
868  CleanUp();
869 
870  while ((entry = dynamic_cast<TObjArray*>(next()))) {
871  ExtractHeaderInformation(entry, entry->GetName());
872  }
873  return true;
874 }
875 
876 //--------------------------------------------------------------------------
877 // ExtractHeaderInformation (public)
878 //--------------------------------------------------------------------------
885 Bool_t TMusrRunHeader::ExtractHeaderInformation(TObjArray *headerInfo, TString requestedPath)
886 {
887  TString label(""), path(""), pathName(""), str(""), strValue(""), type("");
888  TObjString *ostr = nullptr;
889  TObjArray *tokens = nullptr;
890  Ssiz_t idx1;
891  Int_t intValue;
892  Double_t dval;
893 
894  // go through all entries of this header information from the MUSR-ROOT file
895  for (Int_t i=0; i<headerInfo->GetEntries(); i++) {
896  // check if entry is a TObjArray, i.e. a sub tree
897  str = TString(headerInfo->At(i)->ClassName());
898  if (str == "TObjArray") { // sub tree
899  path = requestedPath + "/" + TString(headerInfo->At(i)->GetName());
900  ExtractHeaderInformation(dynamic_cast<TObjArray*>(headerInfo->At(i)), path);
901  } else { // handle all the rest, i.e. already data
902 
903  ostr = dynamic_cast<TObjString*>(headerInfo->At(i));
904  str = ostr->GetString();
905 
906  // get the run header label
907  label = GetLabel(str);
908  if (label == "n/a") // not a TMusrRunHeader object, hence ignore it
909  continue;
910 
911  // get the run header 'value'
912  strValue = GetStrValue(str);
913 
914  // construct path name
915  pathName = requestedPath + TString("/") + label;
916 
917  // get type from map
918  type = GetType(str);
919  if (type == "n/a") // not a TMusrRunHeader object, hence ignore it
920  continue;
921 
922  if (type == "TString") {
923  Set(pathName, strValue);
924  } else if (type == "Int_t") {
925  intValue = strValue.Atoi();
926  Set(pathName, intValue);
927  } else if (type == "Double_t") {
928  dval = strValue.Atof();
929  Set(pathName, dval);
930  } else if (type == "TMusrRunPhysicalQuantity") {
932  prop.SetLabel(label);
933 
934  // 1st get the description if present
935  tokens = strValue.Tokenize(";");
936  if (tokens == nullptr) {
937  std::cerr << std::endl << ">> **ERROR** Couldn't tokenize entry in Bool_t TMusrRunHeader::ExtractHeaderInformation(TObjArray *headerInfo, TString requestedPath)" << std::endl;
938  return false;
939  }
940 
941  switch (tokens->GetEntries()) {
942  case 2:
943  ostr = dynamic_cast<TObjString*>(tokens->At(1));
944  str = ostr->GetString();
945  if (!str.Contains("SP:")) { // make sure that it is not a demand value token
946  prop.SetDescription(str);
947  }
948  break;
949  case 3:
950  ostr = dynamic_cast<TObjString*>(tokens->At(2));
951  str = ostr->GetString();
952  break;
953  default:
954  break;
955  }
956 
957  if (tokens) {
958  delete tokens;
959  tokens = nullptr;
960  }
961 
962  // 2nd collect all the other properties, this is easier when first a potential description is removed
963  idx1 = strValue.Last(';');
964  if (idx1 > 0) {
965  TString last("");
966  for (Int_t i=idx1+2; i<strValue.Length(); i++)
967  last += strValue[i];
968  // check if last is <description> or SP: <demand>
969  if (!last.Contains("SP:")) {
970  str = "";
971  for (Int_t i=0; i<idx1; i++)
972  str += strValue[i];
973  strValue = str;
974  }
975  }
976 
977  tokens = strValue.Tokenize(" +;");
978  if (tokens == nullptr) {
979  std::cerr << std::endl << ">> **ERROR** Couldn't tokenize entry in Bool_t TMusrRunHeader::ExtractHeaderInformation(TObjArray *headerInfo, TString requestedPath)" << std::endl;
980  return false;
981  }
982 
983  switch (tokens->GetEntries()) {
984  case 2: // <val> <unit>
985  ostr = dynamic_cast<TObjString*>(tokens->At(0));
986  str = ostr->GetString();
987  prop.SetValue(str.Atof());
988  ostr = dynamic_cast<TObjString*>(tokens->At(1));
989  str = ostr->GetString();
990  prop.SetUnit(str);
991  break;
992  case 4: // <val> +- <err> <unit>, or <val> <unit>; SP: <demand>
993  ostr = dynamic_cast<TObjString*>(tokens->At(0));
994  str = ostr->GetString();
995  prop.SetValue(str.Atof());
996  ostr = dynamic_cast<TObjString*>(tokens->At(1));
997  str = ostr->GetString();
998  if (str == "-") { // <val> +- <err> <unit>
999  ostr = dynamic_cast<TObjString*>(tokens->At(2));
1000  str = ostr->GetString();
1001  prop.SetError(str.Atof());
1002  ostr = dynamic_cast<TObjString*>(tokens->At(3));
1003  str = ostr->GetString();
1004  prop.SetUnit(str);
1005  } else { // <val> <unit>; SP: <demand>
1006  prop.SetUnit(str);
1007  ostr = dynamic_cast<TObjString*>(tokens->At(3));
1008  str = ostr->GetString();
1009  prop.SetDemand(str.Atof());
1010  }
1011  break;
1012  case 6: // <val> +- <err> <unit>; SP: <demand>
1013  ostr = dynamic_cast<TObjString*>(tokens->At(0));
1014  str = ostr->GetString();
1015  prop.SetValue(str.Atof());
1016  ostr = dynamic_cast<TObjString*>(tokens->At(2));
1017  str = ostr->GetString();
1018  prop.SetError(str.Atof());
1019  ostr = dynamic_cast<TObjString*>(tokens->At(3));
1020  str = ostr->GetString();
1021  prop.SetUnit(str);
1022  ostr = dynamic_cast<TObjString*>(tokens->At(5));
1023  str = ostr->GetString();
1024  prop.SetDemand(str.Atof());
1025  break;
1026  default:
1027  break;
1028  }
1029 
1030  if (tokens) {
1031  delete tokens;
1032  tokens = nullptr;
1033  }
1034 
1035  Set(pathName, prop);
1036  } else if (type == "TStringVector") {
1037  TStringVector svec;
1038  tokens = strValue.Tokenize(";");
1039  if (tokens == nullptr) {
1040  std::cerr << std::endl << ">> **ERROR** Couldn't tokenize entry in Bool_t TMusrRunHeader::ExtractHeaderInformation(TObjArray *headerInfo, TString requestedPath)" << std::endl;
1041  return false;
1042  }
1043  for (Int_t i=0; i<tokens->GetEntries(); i++) {
1044  ostr = dynamic_cast<TObjString*>(tokens->At(i));
1045  str = ostr->GetString();
1046  str.Remove(TString::kBoth, ' ');
1047  svec.push_back(str);
1048  }
1049  if (tokens) {
1050  delete tokens;
1051  tokens = nullptr;
1052  }
1053  Set(pathName, svec);
1054  } else if (type == "TIntVector") {
1055  TIntVector ivec;
1056  tokens = strValue.Tokenize(";");
1057  if (tokens == nullptr) {
1058  std::cerr << std::endl << ">> **ERROR** Couldn't tokenize entry in Bool_t TMusrRunHeader::ExtractHeaderInformation(TObjArray *headerInfo, TString requestedPath)" << std::endl;
1059  return false;
1060  }
1061  for (Int_t i=0; i<tokens->GetEntries(); i++) {
1062  ostr = dynamic_cast<TObjString*>(tokens->At(i));
1063  ivec.push_back(ostr->GetString().Atoi());
1064  }
1065  if (tokens) {
1066  delete tokens;
1067  tokens = nullptr;
1068  }
1069  Set(pathName, ivec);
1070  } else if (type == "TDoubleVector") {
1071  TDoubleVector dvec;
1072  tokens = strValue.Tokenize(";");
1073  if (tokens == nullptr) {
1074  std::cerr << std::endl << ">> **ERROR** Couldn't tokenize entry in Bool_t TMusrRunHeader::ExtractHeaderInformation(TObjArray *headerInfo, TString requestedPath)" << std::endl;
1075  return false;
1076  }
1077  for (Int_t i=0; i<tokens->GetEntries(); i++) {
1078  ostr = dynamic_cast<TObjString*>(tokens->At(i));
1079  dvec.push_back(ostr->GetString().Atoi());
1080  }
1081  if (tokens) {
1082  delete tokens;
1083  tokens = nullptr;
1084  }
1085  Set(pathName, dvec);
1086  }
1087  }
1088  }
1089 
1090  return true;
1091 }
1092 
1093 //--------------------------------------------------------------------------
1094 // DumpHeader (public)
1095 //--------------------------------------------------------------------------
1100 {
1101  std::cout << std::endl << "***************************************";
1102  std::cout << std::endl << "header info of file : " << fFileName;
1103  std::cout << std::endl << "***************************************";
1104 
1105  TString str(""), tstr(""), fmt(""), path(""), name(""), currentPath("");
1107 
1108  for (UInt_t i=0; i<fPathNameOrder.size(); i++) {
1109  // print path if new
1110  SplitPathName(fPathNameOrder[i], path, name);
1111  if (path != currentPath) {
1112  currentPath = path;
1113  std::cout << std::endl << currentPath;
1114  }
1115 
1116  // go through all objects and try to find it
1117  // 1st check TString
1118  for (UInt_t j=0; j<fStringObj.size(); j++) {
1119  if (fStringObj[j].GetPathName() == fPathNameOrder[i]) { // found correct object
1120  SplitPathName(fStringObj[j].GetPathName(), path, name);
1121  str.Form(" %03d - %s: %s -@%d", i, name.Data(), fStringObj[j].GetValue().Data(), MRH_TSTRING);
1122  std::cout << std::endl << str;
1123  }
1124  }
1125  // 2nd check Int_t
1126  for (UInt_t j=0; j<fIntObj.size(); j++) {
1127  if (fIntObj[j].GetPathName() == fPathNameOrder[i]) { // found correct object
1128  SplitPathName(fIntObj[j].GetPathName(), path, name);
1129  str.Form(" %03d - %s: %d -@%d", i, name.Data(), fIntObj[j].GetValue(), MRH_INT);
1130  std::cout << std::endl << str;
1131  }
1132  }
1133  // 3rd check Double_t
1134  for (UInt_t j=0; j<fDoubleObj.size(); j++) {
1135  if (fDoubleObj[j].GetPathName() == fPathNameOrder[i]) { // found correct object
1136  SplitPathName(fDoubleObj[j].GetPathName(), path, name);
1137  fmt.Form(" %%03d - %%s: %%.%dlf -@%%d", MRH_DOUBLE_PREC);
1138  str.Form(fmt, i, name.Data(), fDoubleObj[j].GetValue(), MRH_DOUBLE);
1139  std::cout << std::endl << str;
1140  }
1141  }
1142  // 4th check TMusrRunPhysicalQuantity
1143  for (UInt_t j=0; j<fMusrRunPhysQuantityObj.size(); j++) {
1144  if (fMusrRunPhysQuantityObj[j].GetPathName() == fPathNameOrder[i]) { // found correct object
1145  prop = fMusrRunPhysQuantityObj[j].GetValue();
1146  Int_t digit, digit_d;
1147  if ((prop.GetDemand() != MRH_UNDEFINED) && (prop.GetValue() != MRH_UNDEFINED) && (prop.GetError() != MRH_UNDEFINED) &&
1148  (prop.GetUnit() != "n/a")) { // <value> +- <error> <unit>; SP: <demand> [; <description>]
1149  digit = GetDecimalPlace(prop.GetError());
1150  digit_d = GetLeastSignificantDigit(prop.GetDemand());
1151  if (prop.GetDescription() != "n/a") {
1152  fmt.Form("%%s: %%.%dlf +- %%.%dlf %%s; SP: %%.%dlf; %%s", digit, digit, digit_d);
1153 
1154  tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetError(), prop.GetUnit().Data(), prop.GetDemand(), prop.GetDescription().Data());
1155  } else {
1156  fmt.Form("%%s: %%.%dlf +- %%.%dlf %%s; SP: %%.%dlf", digit, digit, digit_d);
1157  tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetError(), prop.GetUnit().Data(), prop.GetDemand());
1158  }
1159  } else if ((prop.GetDemand() == MRH_UNDEFINED) && (prop.GetValue() != MRH_UNDEFINED) && (prop.GetError() != MRH_UNDEFINED) &&
1160  (prop.GetUnit() != "n/a")) { // <value> +- <error> <unit> [; <description>]
1161  digit = GetDecimalPlace(prop.GetError());
1162  if (prop.GetDescription() != "n/a") {
1163  fmt.Form("%%s: %%.%dlf +- %%.%dlf %%s; %%s", digit, digit);
1164  tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetError(), prop.GetUnit().Data(), prop.GetDescription().Data());
1165  } else {
1166  fmt.Form("%%s: %%.%dlf +- %%.%dlf %%s", digit, digit);
1167  tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetError(), prop.GetUnit().Data());
1168  }
1169  } else if ((prop.GetDemand() == MRH_UNDEFINED) && (prop.GetValue() != MRH_UNDEFINED) && (prop.GetError() == MRH_UNDEFINED) &&
1170  (prop.GetUnit() != "n/a")) { // <value> <unit> [; <description>]
1171  digit = GetLeastSignificantDigit(prop.GetValue());
1172  if (prop.GetDescription() != "n/a") {
1173  fmt.Form("%%s: %%.%dlf %%s; %%s", digit);
1174  tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data(), prop.GetDescription().Data());
1175  } else {
1176  fmt.Form("%%s: %%.%dlf %%s", digit);
1177  tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data());
1178  }
1179  } else if ((prop.GetDemand() != MRH_UNDEFINED) && (prop.GetValue() != MRH_UNDEFINED) && (prop.GetError() == MRH_UNDEFINED) &&
1180  (prop.GetUnit() != "n/a")) { // <value> <unit>; SP: <demand> [; <description>]
1181  digit = GetLeastSignificantDigit(prop.GetValue());
1182  digit_d = GetLeastSignificantDigit(prop.GetDemand());
1183  if (prop.GetDescription() != "n/a") {
1184  fmt.Form("%%s: %%.%dlf %%s; SP: %%.%dlf; %%s", digit, digit_d);
1185  tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data(), prop.GetDemand(), prop.GetDescription().Data());
1186  } else {
1187  fmt.Form("%%s: %%.%dlf %%s; SP: %%.%dlf", digit, digit_d);
1188  tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data(), prop.GetDemand());
1189  }
1190  }
1191  str.Form(" %03d - %s -@%d", i, tstr.Data(), MRH_TMUSR_RUN_PHYSICAL_QUANTITY);
1192  std::cout << std::endl << str;
1193  }
1194  }
1195  // 5th check TStringVector
1196  for (UInt_t j=0; j<fStringVectorObj.size(); j++) {
1197  if (fStringVectorObj[j].GetPathName() == fPathNameOrder[i]) { // found correct object
1198  SplitPathName(fStringVectorObj[j].GetPathName(), path, name);
1199  str.Form(" %03d - %s: ", i, name.Data());
1200  TStringVector vstr = fStringVectorObj[j].GetValue();
1201  for (UInt_t k=0; k<vstr.size()-1; k++)
1202  str += vstr[k] + "; ";
1203  str += vstr[vstr.size()-1];
1204  str += " -@";
1205  str += MRH_TSTRING_VECTOR;
1206  std::cout << std::endl << str;
1207  }
1208  }
1209  // 6th check TIntVector
1210  for (UInt_t j=0; j<fIntVectorObj.size(); j++) {
1211  if (fIntVectorObj[j].GetPathName() == fPathNameOrder[i]) { // found correct object
1212  SplitPathName(fIntVectorObj[j].GetPathName(), path, name);
1213  str.Form(" %03d - %s: ", i, name.Data());
1214  TIntVector vint = fIntVectorObj[j].GetValue();
1215  for (UInt_t k=0; k<vint.size()-1; k++) {
1216  str += vint[k];
1217  str += "; ";
1218  }
1219  str += vint[vint.size()-1];
1220  str += " -@";
1221  str += MRH_INT_VECTOR;
1222  std::cout << std::endl << str;
1223  }
1224  }
1225  // 7th check TDoubleVector
1226  for (UInt_t j=0; j<fDoubleVectorObj.size(); j++) {
1227  if (fDoubleVectorObj[j].GetPathName() == fPathNameOrder[i]) { // found correct object
1228  SplitPathName(fDoubleVectorObj[j].GetPathName(), path, name);
1229  str.Form(" %03d - %s: ", i, name.Data());
1230  TDoubleVector dvec = fDoubleVectorObj[j].GetValue();
1231  TString subStr("");
1232  fmt.Form("%%.%dlf", MRH_DOUBLE_PREC);
1233  for (UInt_t k=0; k<dvec.size()-1; k++) {
1234  subStr.Form(fmt, dvec[k]);
1235  str += subStr;
1236  str += "; ";
1237  }
1238  subStr.Form(fmt, dvec.size()-1);
1239  str += subStr;
1240  str += " -@";
1241  str += MRH_DOUBLE_VECTOR;
1242  std::cout << std::endl << str;
1243  }
1244  }
1245  }
1246 
1247  std::cout << std::endl;
1248 }
1249 
1250 //--------------------------------------------------------------------------
1251 // DrawHeader (public)
1252 //--------------------------------------------------------------------------
1257 {
1258  std::unique_ptr<TPaveText> pt;
1259  std::unique_ptr<TCanvas> ca;
1260 
1261  ca = std::make_unique<TCanvas>("MusrRoot RunHeader","MusrRoot RunHeader", 147,37,699,527);
1262  ca->Range(0., 0., 100., 100.);
1263 
1264  pt = std::make_unique<TPaveText>(10.,10.,90.,90.,"br");
1265  pt->SetFillColor(19);
1266  pt->SetTextAlign(12);
1267 
1268  pt->Draw();
1269 
1270  ca->Modified(kTRUE);
1271 }
1272 
1273 //--------------------------------------------------------------------------
1274 // GetDecimalPlace (private)
1275 //--------------------------------------------------------------------------
1283 {
1284  UInt_t digit = 0;
1285 
1286  if (val < 1.0) {
1287  UInt_t count=1;
1288  do {
1289  val *= 10.0;
1290  if (val > 1.0)
1291  digit = count;
1292  count++;
1293  } while ((digit == 0) && (count < 20));
1294  }
1295 
1296  return digit;
1297 }
1298 
1299 //--------------------------------------------------------------------------
1300 // GetLeastSignificantDigit (private)
1301 //--------------------------------------------------------------------------
1308 {
1309  char cstr[1024];
1310  snprintf(cstr, sizeof(cstr), "%.10lf", val);
1311 
1312  int i=0, j=0;
1313  for (i=strlen(cstr)-1; i>=0; i--) {
1314  if (cstr[i] != '0')
1315  break;
1316  }
1317 
1318  for (j=strlen(cstr)-1; j>=0; j--) {
1319  if (cstr[j] == '.')
1320  break;
1321  }
1322  if (j==0) // no decimal point present, e.g. 321
1323  j=i;
1324 
1325  return i-j;
1326 }
1327 
1328 //--------------------------------------------------------------------------
1329 // SplitPathName (private)
1330 //--------------------------------------------------------------------------
1338 void TMusrRunHeader::SplitPathName(TString pathName, TString &path, TString &name)
1339 {
1340  path = TString("");
1341  name = TString("");
1342  Ssiz_t idx = pathName.Last('/');
1343 
1344  for (Int_t i=0; i<idx; i++)
1345  path += pathName[i];
1346 
1347  for (Int_t i=idx+1; i<pathName.Length(); i++)
1348  name += pathName[i];
1349 }
1350 
1351 //--------------------------------------------------------------------------
1352 // GetLabel (private)
1353 //--------------------------------------------------------------------------
1359 TString TMusrRunHeader::GetLabel(TString str)
1360 {
1361  // get run header label
1362  // the string 'str' should have the structure
1363  // <number> - <runHeader label>: <runHeader string value> -@<encoded data type>
1364 
1365  TString label = TString("n/a");
1366  Ssiz_t idx1 = str.First('-');
1367  Ssiz_t idx2 = str.First(':');
1368  if ((idx1 == -1) || (idx2 == -1)) {
1369  if (!fQuiet) {
1370  std::cerr << std::endl << ">> TMusrRunHeader::GetLabel(): **WARNING** str='" << str << "', seems not correctly encoded.";
1371  std::cerr << std::endl << ">> Will omit it." << std::endl;
1372  }
1373  return label;
1374  }
1375 
1376  label = TString("");
1377  for (Int_t j=idx1+2; j<idx2; j++)
1378  label += str[j];
1379 
1380  return label;
1381 }
1382 
1383 //--------------------------------------------------------------------------
1384 // GetStrValue (private)
1385 //--------------------------------------------------------------------------
1391 TString TMusrRunHeader::GetStrValue(TString str)
1392 {
1393  // get run header string value
1394  // the string 'str' should have the structure
1395  // <number> - <runHeader label>: <runHeader string value> -@<encoded data type>
1396 
1397  TString strValue = TString("n/a");
1398  Ssiz_t idx1 = str.First(':');
1399  Ssiz_t idx2 = str.Last('-');
1400  if ((idx1 == -1) || (idx2 == -1)) {
1401  if (!fQuiet) {
1402  std::cerr << std::endl << ">> TMusrRunHeader::GetStrValue(): **WARNING** str='" << str << "', seems not correctly encoded.";
1403  std::cerr << std::endl << ">> Will omit it." << std::endl;
1404  }
1405  return strValue;
1406  }
1407 
1408  strValue = TString("");
1409  for (Int_t j=idx1+2; j<idx2-1; j++)
1410  strValue += str[j];
1411 
1412  return strValue;
1413 }
1414 
1415 //--------------------------------------------------------------------------
1416 // GetType (private)
1417 //--------------------------------------------------------------------------
1423 TString TMusrRunHeader::GetType(TString str)
1424 {
1425  TString result = "n/a";
1426 
1427  // the string 'str' should have the structure
1428  // <number> - <runHeader label>: <runHeader string value> -@<encoded data type>
1429  Ssiz_t pos = str.Last('@');
1430 
1431  if (pos == -1) { // i.e. NOT found
1432  if (!fQuiet) {
1433  std::cerr << std::endl << ">> TMusrRunHeader::GetType(): **WARNING** str=" << str << " seems to be an invalid MusrROOT run header string.";
1434  std::cerr << std::endl << ">> Will omit it." << std::endl;
1435  }
1436  return result;
1437  }
1438 
1439  // filter out the encoded type declaration, i.e. -@<num>, where <num> is the encoded type
1440  TString typeStr(str);
1441  typeStr.Remove(0, pos+1);
1442  Int_t typeVal;
1443  if (!typeStr.IsDigit()) {
1444  std::cerr << std::endl << ">> TMusrRunHeader::GetType(): **ERROR** typeStr=" << typeStr << " is not supported." << std::endl;
1445  return result;
1446  }
1447 
1448  typeVal = typeStr.Atoi();
1449 
1450  switch (typeVal) {
1451  case MRH_TSTRING:
1452  result = "TString";
1453  break;
1454  case MRH_INT:
1455  result = "Int_t";
1456  break;
1457  case MRH_DOUBLE:
1458  result = "Double_t";
1459  break;
1461  result = "TMusrRunPhysicalQuantity";
1462  break;
1463  case MRH_TSTRING_VECTOR:
1464  result = "TStringVector";
1465  break;
1466  case MRH_INT_VECTOR:
1467  result = "TIntVector";
1468  break;
1469  case MRH_DOUBLE_VECTOR:
1470  result = "TDoubleVector";
1471  break;
1472  default:
1473  std::cerr << std::endl << ">> TMusrRunHeader::GetType(): **ERROR** found unsupport type encoded with: " << typeVal << "." << std::endl;
1474  break;
1475  }
1476 
1477  return result;
1478 }
1479 
1480 //--------------------------------------------------------------------------
1481 // UpdateFolder (private)
1482 //--------------------------------------------------------------------------
1493 bool TMusrRunHeader::UpdateFolder(TObject *treeObj, TString path)
1494 {
1495  if (path.First('/') == -1) // only value element left, hence nothing to be done
1496  return true;
1497 
1498  TString str = GetFirst(path, '/');
1499 
1500  TObject *obj = treeObj->FindObject(str);
1501 
1502  // remove the first path element
1503  if (!RemoveFirst(path, '/')) {
1504  std::cerr << std::endl << ">> TMusrRunHeader::UpdateFolder(): **ERROR** couldn't tokenize path!!" << std::endl;
1505  return false;
1506  }
1507 
1508  if (!obj) { // required object not present, create it
1509  TObjArray *oarray = new TObjArray();
1510  if (oarray == nullptr) {
1511  std::cerr << std::endl << ">> TMusrRunHeader::UpdateFolder(): **ERROR** couldn't create header structure!!" << std::endl;
1512  return false;
1513  }
1514  // set the name of the new TObjArray
1515  oarray->SetName(str);
1516 
1517  if (!strcmp(treeObj->ClassName(), "TFolder"))
1518  (dynamic_cast<TFolder*>(treeObj))->Add(oarray);
1519  else // it is a TObjArray
1520  (dynamic_cast<TObjArray*>(treeObj))->AddLast(oarray);
1521 
1522  return UpdateFolder(oarray, path);
1523  } else { // object present, hence check rest of the path
1524  return UpdateFolder(obj, path);
1525  }
1526 }
1527 
1528 //--------------------------------------------------------------------------
1529 // FindObject (private)
1530 //--------------------------------------------------------------------------
1541 TObject* TMusrRunHeader::FindObject(TObject *treeObj, TString path)
1542 {
1543  Ssiz_t pos;
1544  TObject *obj=nullptr;
1545 
1546  // make sure that treeObj is either TFolder or TObjArray
1547  if (strcmp(treeObj->ClassName(), "TFolder") && strcmp(treeObj->ClassName(), "TObjArray"))
1548  return obj;
1549 
1550  pos = path.First('/');
1551  if (pos == -1) { // i.e. no sub-paths anymore
1552  obj = treeObj->FindObject(path);
1553  return obj;
1554  } else { // sub-paths present
1555  TString objName = GetFirst(path, '/'); // get first token of the path <objName0>/<objName1>/.../<objNameN>
1556  obj = treeObj->FindObject(objName);
1557  if (obj) { // object found, check for subPath object
1558  RemoveFirst(path, '/'); // remove first tokens of the path
1559  return FindObject(obj, path);
1560  } else { // object not found
1561  return obj;
1562  }
1563  }
1564 }
1565 
1566 //--------------------------------------------------------------------------
1567 // GetHeaderString (private)
1568 //--------------------------------------------------------------------------
1574 TObjString TMusrRunHeader::GetHeaderString(UInt_t idx)
1575 {
1576  TObjString tostr("n/a");
1577 
1578  TString str(""), path(""), name(""), fmt(""), tstr("");
1580 
1581  // go through all objects and try to find it
1582  // 1st check TString
1583  for (UInt_t j=0; j<fStringObj.size(); j++) {
1584  if (fStringObj[j].GetPathName() == fPathNameOrder[idx]) { // found correct object
1585  SplitPathName(fStringObj[j].GetPathName(), path, name);
1586  str.Form("%03d - %s: %s -@%d", idx, name.Data(), fStringObj[j].GetValue().Data(), MRH_TSTRING);
1587  tostr.SetString(str);
1588  }
1589  }
1590  // 2nd check Int_t
1591  for (UInt_t j=0; j<fIntObj.size(); j++) {
1592  if (fIntObj[j].GetPathName() == fPathNameOrder[idx]) { // found correct object
1593  SplitPathName(fIntObj[j].GetPathName(), path, name);
1594  str.Form("%03d - %s: %d -@%d", idx, name.Data(), fIntObj[j].GetValue(), MRH_INT);
1595  tostr.SetString(str);
1596  }
1597  }
1598  // 3rd check Double_t
1599  for (UInt_t j=0; j<fDoubleObj.size(); j++) {
1600  if (fDoubleObj[j].GetPathName() == fPathNameOrder[idx]) { // found correct object
1601  SplitPathName(fDoubleObj[j].GetPathName(), path, name);
1602  fmt.Form("%%03d - %%s: %%.%dlf -@%%d", MRH_DOUBLE_PREC);
1603  str.Form(fmt, idx, name.Data(), fDoubleObj[j].GetValue(), MRH_DOUBLE);
1604  tostr.SetString(str);
1605  }
1606  }
1607  // 4th check TMusrRunPhysicalQuantity
1608  for (UInt_t j=0; j<fMusrRunPhysQuantityObj.size(); j++) {
1609  if (fMusrRunPhysQuantityObj[j].GetPathName() == fPathNameOrder[idx]) { // found correct object
1610  prop = fMusrRunPhysQuantityObj[j].GetValue();
1611  Int_t digit, digit_d;
1612  if ((prop.GetDemand() != MRH_UNDEFINED) && (prop.GetValue() != MRH_UNDEFINED) && (prop.GetError() != MRH_UNDEFINED) &&
1613  (prop.GetUnit() != "n/a")) { // <value> +- <error> <unit>; SP: <demand> [; <description>]
1614  digit = GetDecimalPlace(prop.GetError());
1615  digit_d = GetLeastSignificantDigit(prop.GetDemand());
1616  if (prop.GetDescription() != "n/a") {
1617  fmt.Form("%%s: %%.%dlf +- %%.%dlf %%s; SP: %%.%dlf; %%s", digit, digit, digit_d);
1618 
1619  tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetError(), prop.GetUnit().Data(), prop.GetDemand(), prop.GetDescription().Data());
1620  } else {
1621  fmt.Form("%%s: %%.%dlf +- %%.%dlf %%s; SP: %%.%dlf", digit, digit, digit_d);
1622  tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetError(), prop.GetUnit().Data(), prop.GetDemand());
1623  }
1624  } else if ((prop.GetDemand() == MRH_UNDEFINED) && (prop.GetValue() != MRH_UNDEFINED) && (prop.GetError() != MRH_UNDEFINED) &&
1625  (prop.GetUnit() != "n/a")) { // <value> +- <error> <unit> [; <description>]
1626  digit = GetDecimalPlace(prop.GetError());
1627  if (prop.GetDescription() != "n/a") {
1628  fmt.Form("%%s: %%.%dlf +- %%.%dlf %%s; %%s", digit, digit);
1629  tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetError(), prop.GetUnit().Data(), prop.GetDescription().Data());
1630  } else {
1631  fmt.Form("%%s: %%.%dlf +- %%.%dlf %%s", digit, digit);
1632  tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetError(), prop.GetUnit().Data());
1633  }
1634  } else if ((prop.GetDemand() == MRH_UNDEFINED) && (prop.GetValue() != MRH_UNDEFINED) && (prop.GetError() == MRH_UNDEFINED) &&
1635  (prop.GetUnit() != "n/a")) { // <value> <unit> [; <description>]
1636  digit = GetLeastSignificantDigit(prop.GetValue());
1637  if (prop.GetDescription() != "n/a") {
1638  fmt.Form("%%s: %%.%dlf %%s; %%s", digit);
1639  tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data(), prop.GetDescription().Data());
1640  } else {
1641  fmt.Form("%%s: %%.%dlf %%s", digit);
1642  tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data());
1643  }
1644  } else if ((prop.GetDemand() != MRH_UNDEFINED) && (prop.GetValue() != MRH_UNDEFINED) && (prop.GetError() == MRH_UNDEFINED) &&
1645  (prop.GetUnit() != "n/a")) { // <value> <unit>; SP: <demand> [; <description>]
1646  digit = GetLeastSignificantDigit(prop.GetValue());
1647  digit_d = GetLeastSignificantDigit(prop.GetDemand());
1648  if (prop.GetDescription() != "n/a") {
1649  fmt.Form("%%s: %%.%dlf %%s; SP: %%.%dlf; %%s", digit, digit_d);
1650  tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data(), prop.GetDemand(), prop.GetDescription().Data());
1651  } else {
1652  fmt.Form("%%s: %%.%dlf %%s; SP: %%.%dlf", digit, digit_d);
1653  tstr.Form(fmt, prop.GetLabel().Data(), prop.GetValue(), prop.GetUnit().Data(), prop.GetDemand());
1654  }
1655  }
1656  str.Form("%03d - %s -@%d", idx, tstr.Data(), MRH_TMUSR_RUN_PHYSICAL_QUANTITY);
1657  tostr.SetString(str);
1658  }
1659  }
1660  // 5th check TStringVector
1661  for (UInt_t j=0; j<fStringVectorObj.size(); j++) {
1662  if (fStringVectorObj[j].GetPathName() == fPathNameOrder[idx]) { // found correct object
1663  SplitPathName(fStringVectorObj[j].GetPathName(), path, name);
1664  str.Form("%03d - %s: ", idx, name.Data());
1665  TStringVector vstr = fStringVectorObj[j].GetValue();
1666  for (UInt_t k=0; k<vstr.size()-1; k++)
1667  str += vstr[k] + "; ";
1668  str += vstr[vstr.size()-1];
1669  str += " -@";
1670  str += MRH_TSTRING_VECTOR;
1671  tostr.SetString(str);
1672  }
1673  }
1674  // 6th check TIntVector
1675  for (UInt_t j=0; j<fIntVectorObj.size(); j++) {
1676  if (fIntVectorObj[j].GetPathName() == fPathNameOrder[idx]) { // found correct object
1677  SplitPathName(fIntVectorObj[j].GetPathName(), path, name);
1678  str.Form("%03d - %s: ", idx, name.Data());
1679  TIntVector vint = fIntVectorObj[j].GetValue();
1680  for (UInt_t k=0; k<vint.size()-1; k++) {
1681  str += vint[k];
1682  str += "; ";
1683  }
1684  str += vint[vint.size()-1];
1685  str += " -@";
1686  str += MRH_INT_VECTOR;
1687  tostr.SetString(str);
1688  }
1689  }
1690  // 7th check TDoubleVector
1691  for (UInt_t j=0; j<fDoubleVectorObj.size(); j++) {
1692  if (fDoubleVectorObj[j].GetPathName() == fPathNameOrder[idx]) { // found correct object
1693  SplitPathName(fDoubleVectorObj[j].GetPathName(), path, name);
1694  str.Form("%03d - %s: ", idx, name.Data());
1695  TDoubleVector dvec = fDoubleVectorObj[j].GetValue();
1696  TString subStr("");
1697  fmt.Form("%%.%dlf", MRH_DOUBLE_PREC);
1698  for (UInt_t k=0; k<dvec.size()-1; k++) {
1699  subStr.Form(fmt, dvec[k]);
1700  str += subStr;
1701  str += "; ";
1702  }
1703  subStr.Form(fmt, dvec[dvec.size()-1]);
1704  str += subStr;
1705  str += " -@";
1706  str += MRH_DOUBLE_VECTOR;
1707  tostr.SetString(str);
1708  }
1709  }
1710 
1711  return tostr;
1712 }
1713 
1714 //--------------------------------------------------------------------------
1715 // RemoveFirst (private)
1716 //--------------------------------------------------------------------------
1725 bool TMusrRunHeader::RemoveFirst(TString &str, const char splitter)
1726 {
1727  Ssiz_t idx = str.First(splitter);
1728  if (idx == -1)
1729  return false;
1730 
1731  str.Remove(0, idx+1);
1732 
1733  return true;
1734 }
1735 
1736 //--------------------------------------------------------------------------
1737 // GetFirst (private)
1738 //--------------------------------------------------------------------------
1752 TString TMusrRunHeader::GetFirst(TString &str, const char splitter)
1753 {
1754  TString result = str;
1755 
1756  Ssiz_t idx = str.First(splitter);
1757  if (idx != -1)
1758  result.Remove(idx, str.Length());
1759 
1760  return result;
1761 }
1762 
1763 // end ---------------------------------------------------------------------
virtual void DumpHeader()
std::vector< TString > fPathNameOrder
keeps the path-name as they were created in ordered to keep ordering
std::vector< TMusrRunObject< TStringVector > > fStringVectorObj
virtual Bool_t ExtractAll(TFolder *folder)
virtual void SetDemand(Double_t val)
virtual void Init(TString str="n/a")
std::vector< Int_t > TIntVector
virtual ~TMusrRunHeader()
#define MRH_TMUSR_RUN_PHYSICAL_QUANTITY
std::vector< Double_t > TDoubleVector
Double_t fError
estimated error (standard deviation) of the measured value
TMusrRunHeader(bool quiet=false)
TString fDescription
a more detailed description of the physical quantity
#define MRH_DOUBLE_PREC
virtual Double_t GetValue() const
std::vector< TMusrRunObject< TDoubleVector > > fDoubleVectorObj
virtual TObject * FindObject(TObject *treeObj, TString path)
virtual void SetError(Double_t err)
#define MRH_TSTRING_VECTOR
std::vector< TMusrRunObject< Int_t > > fIntObj
virtual void Set(TString pathName, TString value)
virtual Bool_t ExtractHeaderInformation(TObjArray *headerInfo, TString path)
std::vector< TMusrRunObject< TIntVector > > fIntVectorObj
virtual TString GetStrValue(TString str)
#define MRH_DOUBLE
virtual TString GetDescription() const
#define MRH_UNDEFINED
virtual TString GetTypeOfPath(TString pathName)
virtual void DrawHeader()
virtual void CleanUp()
TString fUnit
unit of the physical quantity
virtual void SetValue(Double_t val)
#define MRH_DOUBLE_VECTOR
virtual TString GetFirst(TString &str, const char splitter)
std::vector< TMusrRunObject< Double_t > > fDoubleObj
#define MRH_INT_VECTOR
std::vector< TString > TStringVector
virtual void SetUnit(TString &unit)
#define MRH_INT
virtual TString GetUnit() const
virtual void Get(TString pathName, TString &value, Bool_t &ok)
Double_t fValue
measured value of the physical quantity
virtual Double_t GetDemand() const
virtual TString GetLabel() const
virtual UInt_t GetDecimalPlace(Double_t val)
virtual void Set(TString label, Double_t demand, Double_t value, Double_t error, TString unit, TString description=TString("n/a"))
virtual TObjString GetHeaderString(UInt_t idx)
virtual Double_t GetError() const
virtual bool UpdateFolder(TObject *treeObj, TString path)
#define MRH_TSTRING
virtual void SetDescription(TString &str)
virtual UInt_t GetLeastSignificantDigit(Double_t val) const
virtual TString GetLabel(TString str)
virtual void SplitPathName(TString pathName, TString &path, TString &name)
std::vector< TMusrRunObject< TString > > fStringObj
TString fLabel
property label, like ’Sample Temperature’ etc.
virtual Bool_t FillFolder(TFolder *folder)
Double_t fDemand
demand value of the physical quantity, e.g. temperature setpoint
virtual void SetLabel(TString &label)
std::vector< TMusrRunObject< TMusrRunPhysicalQuantity > > fMusrRunPhysQuantityObj
virtual bool RemoveFirst(TString &str, const char splitter)
virtual TString GetType(TString str)
ClassImp(TMusrRunPhysicalQuantity) TMusrRunPhysicalQuantity