diff --git a/src/tests/PsiRoot/TPsiRunHeader.cpp b/src/tests/PsiRoot/TPsiRunHeader.cpp index fa1d5dc4..48baf852 100644 --- a/src/tests/PsiRoot/TPsiRunHeader.cpp +++ b/src/tests/PsiRoot/TPsiRunHeader.cpp @@ -65,9 +65,11 @@ ClassImp(TPsiRunProperty) TPsiRunProperty::TPsiRunProperty() { fLabel = "n/a"; + fDemand = 0.0; fValue = 0.0; fError = 0.0; fUnit = "n/a"; + fDescription = "n/a"; } //-------------------------------------------------------------------------- @@ -81,9 +83,13 @@ TPsiRunProperty::TPsiRunProperty() * \param error * \param unit */ -TPsiRunProperty::TPsiRunProperty(TString &label, Double_t value, Double_t error, TString &unit) : - fLabel(label), fValue(value), fError(error), fUnit(unit) +TPsiRunProperty::TPsiRunProperty(TString &label, Double_t demand, Double_t value, Double_t error, TString &unit, TString &description) : + fLabel(label), fDemand(demand), fValue(value), fError(error), fUnit(unit) { + if (description.IsWhitespace()) + fDescription = "n/a"; + else + fDescription = description; } //-------------------------------------------------------------------------- @@ -132,6 +138,30 @@ TPsiRunHeader::~TPsiRunHeader() fHeader.Delete(); } +//-------------------------------------------------------------------------- +// GetProperty +//-------------------------------------------------------------------------- +/** + *

Searches the property given by 'name'. If it is found, this property is + * returned, otherwise 0 is returned. + * + * \param name property name to look for. + */ +TPsiRunProperty* TPsiRunHeader::GetProperty(TString name) +{ + UInt_t i=0; + + for (i=0; iGetEntries(); i++) { - ostr = dynamic_cast(runHeader->At(i)); - str = ostr->GetString(); - - name = TString(""); - unit = TString(""); - - // 1st get the name - idx = str.Index("-"); - str.Remove(0, idx+2); - idx = str.Index(":"); - str.Remove(idx, str.Length()); - name = str; - - // 2nd get the value - str = ostr->GetString(); - idx = str.Index(":"); - str.Remove(0, idx+2); - idx = str.Index("+-"); - str.Remove(idx, str.Length()); - if (!str.IsFloat()) { - cerr << endl << ">> TPsiRunHeader::ExtractHeaderInformation(..) **ERROR** in TPsiRunProperty:"; - cerr << endl << ">> found " << ostr->GetString().Data() << ", which has an invalid format." << endl << endl; + if (DecodePhyscialPorperty(dynamic_cast(runHeader->At(i)), prop)) { + AddProperty(prop); + } else { return false; } - dval = str.Atof(); - - // 3rd get the error, and unit - str = ostr->GetString(); - idx = str.Index("+-"); - str.Remove(0, idx+3); - memset(cstr, 0, sizeof(cstr)); - status = sscanf(str.Data(), "%lf %s", &derr, cstr); - if (status < 2) { - cerr << endl << ">> TPsiRunHeader::ExtractHeaderInformation(..) **ERROR** in TPsiRunProperty:"; - cerr << endl << ">> found " << ostr->GetString().Data() << ", which has an invalid format." << endl << endl; - return false; - } - if (strlen(cstr) > 0) - unit = TString(cstr); - - AddProperty(name, dval, derr, unit); } return true; @@ -359,9 +354,9 @@ void TPsiRunHeader::AddProperty(TPsiRunProperty &property) * \param error * \param unit */ -void TPsiRunHeader::AddProperty(TString name, Double_t value, Double_t error, TString unit) +void TPsiRunHeader::AddProperty(TString name, Double_t demand, Double_t value, Double_t error, TString unit, TString description) { - TPsiRunProperty property(name, value, error, unit); + TPsiRunProperty property(name, demand, value, error, unit, description); fProperties.push_back(property); } @@ -408,9 +403,15 @@ void TPsiRunHeader::DumpHeader() const cout << endl << setw(name_width) << left << "Orientation" << setw(old_width) << ": " << GetOrientation().Data(); for (UInt_t i=0; iModified(kTRUE); } +//-------------------------------------------------------------------------- +// DecodePhyscialPorperty (private) +//-------------------------------------------------------------------------- +/** + *

+ * + * \param ostr + * \param prop + */ +Bool_t TPsiRunHeader::DecodePhyscialPorperty(TObjString *oprop, TPsiRunProperty &prop) +{ + TObjArray *tokens = oprop->GetString().Tokenize("-:"); + TObjArray *tokens1 = 0; + TObjString *ostr = 0; + TString str(""); + + if (tokens == 0) { + cerr << endl << ">> **ERROR** Couldn't tokenize physical property string '" << ostr->GetString().Data() << "' (1)." << endl; + return false; + } + + // get property name + ostr = dynamic_cast(tokens->At(1)); + str = ostr->GetString(); + str.Remove(TString::kLeading, ' '); + prop.SetLabel(str); + + if (tokens) { + delete tokens; + tokens = 0; + } + + // get measured value + tokens = oprop->GetString().Tokenize(":"); + if (tokens == 0) { + cerr << endl << ">> **ERROR** Couldn't tokenize physical property string '" << ostr->GetString().Data() << "' (2)." << endl; + return false; + } + ostr = dynamic_cast(tokens->At(1)); + str = ostr->GetString(); + tokens1 = str.Tokenize(" ;"); + if (tokens1 == 0) { + cerr << endl << ">> **ERROR** Couldn't tokenize physical property string '" << ostr->GetString().Data() << "' (3)." << endl; + if (tokens) { + delete tokens; + tokens = 0; + } + return false; + } + if (tokens1->GetEntries() < 4) { + cerr << endl << ">> **ERROR** not enough tokens from physical property string '" << ostr->GetString().Data() << "' (4)." << endl; + if (tokens) { + delete tokens; + tokens = 0; + } + return false; + } + + // get measured value + ostr = dynamic_cast(tokens1->At(0)); + if (ostr->GetString().IsFloat()) { + prop.SetValue(ostr->GetString().Atof()); + } else { + cerr << endl << ">> **ERROR** unexpected measured value. Found " << ostr->GetString().Data() << ", expected float." << endl; + if (tokens) { + delete tokens; + } + return false; + } + + // get estimated err + ostr = dynamic_cast(tokens1->At(2)); + if (ostr->GetString().IsFloat()) { + prop.SetError(ostr->GetString().Atof()); + } else { + cerr << endl << ">> **ERROR** unexpected estimated error. Found " << ostr->GetString().Data() << ", expected float." << endl; + if (tokens) { + delete tokens; + } + return false; + } + + // get unit + ostr = dynamic_cast(tokens1->At(3)); + str = ostr->GetString(); + str.Remove(TString::kLeading, ' '); + prop.SetUnit(str); + + if (tokens1) { + delete tokens1; + tokens1 = 0; + } + + ostr = dynamic_cast(tokens->At(2)); + str = ostr->GetString(); + tokens1 = str.Tokenize(";"); + if (tokens1 == 0) { + cerr << endl << ">> **ERROR** Couldn't tokenize physical property string '" << ostr->GetString().Data() << "' (4)." << endl; + if (tokens) { + delete tokens; + tokens = 0; + } + return false; + } + + // get demand value + ostr = dynamic_cast(tokens1->At(0)); + if (ostr->GetString().IsFloat()) { + prop.SetDemand(ostr->GetString().Atof()); + } else { + cerr << endl << ">> **ERROR** unexpected demand value. Found " << ostr->GetString().Data() << ", expected float." << endl; + if (tokens) { + delete tokens; + } + return false; + } + + if (tokens1->GetEntries() > 1) { // with description + ostr = dynamic_cast(tokens1->At(1)); + str = ostr->GetString(); + str.Remove(TString::kLeading, ' '); + prop.SetDescription(str); + } + + + if (tokens1) { + delete tokens1; + } + if (tokens) { + delete tokens; + } + + return true; +} + //-------------------------------------------------------------------------- // GetDecimalPlace (private) //-------------------------------------------------------------------------- @@ -464,3 +600,32 @@ UInt_t TPsiRunHeader::GetDecimalPlace(Double_t val) return digit; } + +//-------------------------------------------------------------------------- +// GetLeastSignificantDigit (private) +//-------------------------------------------------------------------------- +/** + *

returns the number of significant digits + * + * \param val value from which the lowest significant digit shall be determined + */ +UInt_t TPsiRunHeader::GetLeastSignificantDigit(Double_t val) const +{ + char cstr[1024]; + sprintf(cstr, "%lf", val); + + int i=0, j=0; + for (i=strlen(cstr)-1; i>=0; i--) { + if (cstr[i] != '0') + break; + } + + for (j=strlen(cstr)-1; j>=0; j--) { + if (cstr[j] == '.') + break; + } + if (j==0) // no decimal point present, e.g. 321 + j=i; + + return i-j; +} diff --git a/src/tests/PsiRoot/TPsiRunHeader.h b/src/tests/PsiRoot/TPsiRunHeader.h index 1a7680a8..d3147145 100644 --- a/src/tests/PsiRoot/TPsiRunHeader.h +++ b/src/tests/PsiRoot/TPsiRunHeader.h @@ -40,26 +40,33 @@ class TPsiRunProperty : public TObject { public: TPsiRunProperty(); - TPsiRunProperty(TString &name, Double_t value, Double_t error, TString &unit); + TPsiRunProperty(TString &name, Double_t demand, Double_t value, Double_t error, TString &unit, TString &description); virtual ~TPsiRunProperty(); virtual TString GetLabel() const { return fLabel; } + virtual Double_t GetDemand() const { return fDemand; } virtual Double_t GetValue() const { return fValue; } virtual Double_t GetError() const { return fError; } virtual TString GetUnit() const { return fUnit; } + virtual TString GetDescription() const { return fDescription; } virtual void SetLabel(TString &label) { fLabel = label; } virtual void SetLabel(const char *label) { fLabel = label; } + virtual void SetDemand(Double_t val) { fDemand = val; } virtual void SetValue(Double_t val) { fValue = val; } virtual void SetError(Double_t err) { fError = err; } virtual void SetUnit(TString &unit) { fUnit = unit.Data(); } virtual void SetUnit(const char *unit) { fUnit = unit; } + virtual void SetDescription(TString &str) { fDescription = str.Data(); } + virtual void SetDescription(const char *str) { fDescription = str; } private: - TString fLabel; - Double_t fValue; - Double_t fError; - TString fUnit; + TString fLabel; ///< property label, like ’Sample Temperature’ etc. + Double_t fDemand; ///< demand value of the property, e.g. temperature setpoint + Double_t fValue; ///< measured value of the property + Double_t fError; ///< estimated error (standard deviation) of the measured property value + TString fUnit; ///< unit of the property + TString fDescription; ///< a more detailed description of the property ClassDef(TPsiRunProperty, 1) }; @@ -78,6 +85,7 @@ public: virtual TString GetSetup() const { return fSetup; } virtual TString GetSample() const { return fSample; } virtual TString GetOrientation() const { return fOrientation; } + virtual TPsiRunProperty* GetProperty(TString name); virtual vector *GetProperties() { return &fProperties; } virtual TObjArray *GetHeader(); @@ -91,7 +99,7 @@ public: virtual void SetSample(TString sample) { fSample = sample; } virtual void SetOrientation(TString orientation) { fOrientation = orientation; } virtual void AddProperty(TPsiRunProperty &property); - virtual void AddProperty(TString name, Double_t value, Double_t error, TString unit); + virtual void AddProperty(TString name, Double_t demand, Double_t value, Double_t error, TString unit, TString desciption=TString("")); virtual void DumpHeader() const; @@ -110,7 +118,10 @@ private: TObjArray fHeader; /// header as TObjString array for dumping into a ROOT file - UInt_t GetDecimalPlace(Double_t val); + virtual Bool_t DecodePhyscialPorperty(TObjString *ostr, TPsiRunProperty &prop); + + virtual UInt_t GetDecimalPlace(Double_t val); + virtual UInt_t GetLeastSignificantDigit(Double_t val) const; ClassDef(TPsiRunHeader, 1) }; diff --git a/src/tests/PsiRoot/psi_runHeader_test.cpp b/src/tests/PsiRoot/psi_runHeader_test.cpp index d3e3a9e3..b8a367da 100644 --- a/src/tests/PsiRoot/psi_runHeader_test.cpp +++ b/src/tests/PsiRoot/psi_runHeader_test.cpp @@ -63,12 +63,12 @@ int main(int argc, char *argv[]) header->SetSample("Eu2CuO4 MOD thin film"); header->SetOrientation("c-axis perp to spin"); - header->AddProperty("T0", 30.01, 0.05, "K"); - header->AddProperty("T1", 30.03, 0.03, "K"); - header->AddProperty("Field", 3.00003, 0.0003, "T"); - header->AddProperty("BigError", 13.2, 1.2, "Something"); - header->AddProperty("ThisIsAVeryLongPropertyName", 3.03, 0.03, "SI-Unit"); - header->AddProperty("This Is A Property With Spaces", 3.03, 0.03, "SI-Unit"); + header->AddProperty("Sample Temperature", 30.0, 30.01, 0.05, "K"); + header->AddProperty("T1", 30.0, 30.003, 0.003, "K", "sample stick temperature"); + header->AddProperty("Field", 3.0, 3.0003, 0.000025, "T"); + header->AddProperty("BigError", 12.5, 13.2, 1.2, "Something", "Explain it"); + header->AddProperty("ThisIsAVeryLongPropertyName", 3.001, 3.03, 0.03, "SI-Unit", "another interesting property"); + header->AddProperty("This Is A Property With Spaces", 3.0, 3.03, 0.03, "SI-Unit", "yet another interesting property"); TFile *f = new TFile(argv[1], "RECREATE", "psi_runHeader_test"); if (f->IsZombie()) { @@ -77,16 +77,16 @@ int main(int argc, char *argv[]) } // root file header related things -/* TFolder *runInfo = gROOT->GetRootFolder()->AddFolder("RunInfo", "PSI RunInfo"); gROOT->GetListOfBrowsables()->Add(runInfo, "RunInfo"); runInfo->Add(header->GetHeader()); runInfo->Write(); -*/ +/* f->mkdir("RunInfo"); f->cd("RunInfo"); header->GetHeader()->Write(); +*/ f->Close();