handles now updating properly

This commit is contained in:
nemu
2012-03-13 07:47:00 +00:00
parent fb5c5541f1
commit 59df2224ba
6 changed files with 420 additions and 167 deletions

View File

@ -3,7 +3,7 @@
<xs:annotation> <xs:annotation>
<xs:documentation> <xs:documentation>
This XSD document describes the muSR file structure for CERN/ROOT based files. This XSD document describes the muSR file structure for CERN/ROOT based files.
In the following it will be called MusrROOT. In the following it will be called MusrRoot.
It is currently the default standard for writting muSR data files at the It is currently the default standard for writting muSR data files at the
Paul Scherrer Institute. Paul Scherrer Institute.
@ -55,7 +55,7 @@
<xs:simpleType name="histoName"> <xs:simpleType name="histoName">
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
<xs:pattern value="hDecay([0-9]){4}"/> <!-- this means hDecayXXX, where XXX are 3 digits --> <xs:pattern value="hDecay([0-9]){3,}"/> <!-- this means hDecayXXX, where XXX are 3 digits -->
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
@ -119,6 +119,7 @@
<xs:element name="Sample_Magnetic_Field" type="TMusrRunPhysicalQuantity"/> <xs:element name="Sample_Magnetic_Field" type="TMusrRunPhysicalQuantity"/>
<xs:element name="No_of_Histos" type="Int_t"/> <xs:element name="No_of_Histos" type="Int_t"/>
<xs:element name="Time_Resolution" type="TMusrRunPhysicalQuantity"/> <xs:element name="Time_Resolution" type="TMusrRunPhysicalQuantity"/>
<xs:element name="RedGreen_Offsets" type="TIntVector"/>
<xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded"/> <!-- here can go any additional stuff you like --> <xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded"/> <!-- here can go any additional stuff you like -->
</xs:sequence> </xs:sequence>
</xs:complexType> </xs:complexType>
@ -147,6 +148,12 @@
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
<xs:simpleType name="TIntVector">
<xs:restriction base="xs:string">
<xs:pattern value="TIntVector"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="sampleEnvironmentInfo"> <xs:complexType name="sampleEnvironmentInfo">
<xs:sequence> <xs:sequence>
<xs:element name="Cryo" type="TString"/> <xs:element name="Cryo" type="TString"/>

View File

@ -0,0 +1,221 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:annotation>
<xs:documentation>
This XSD document describes the muSR file structure of CERN/ROOT based files for LEM.
In the following it will be called MusrRootLEM.
It is an extension of MusrRoot.xsd and describes the additional LEM specific entries.
Author: Andreas Suter, andreas.suter@psi.ch
$Id$
</xs:documentation>
</xs:annotation>
<xs:element name="MusrRoot" type="musrRoot"/>
<xs:complexType name="musrRoot">
<xs:sequence>
<xs:element ref="histos"/>
<xs:element name="RunHeader" type="runHeaderFolder"/>
<xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded"/> <!-- here can go any additional stuff you like -->
</xs:sequence>
</xs:complexType>
<xs:element name="histos">
<xs:annotation>
<xs:documentation>
The histos folder is containing potentially various subfolders.
At least two subfolders, called DecayAnaModule, and SlowControlAnaModule,
which holds the muSR decay histograms, must be present.
</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="DecayAnaModule" type="decayHistoData"/>
<xs:element name="SCAnaModule" type="slowControlHistoData"/>
<xs:element name="TOFAnaModule" type="histoData"/>
<xs:element name="PileUpAnaModule" type="histoData"/>
<xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded"/> <!-- here can go any additional stuff you like -->
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="decayHistoData">
<xs:sequence>
<xs:element name="DecayHistoEntry" type="decayHistoEntry" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="decayHistoEntry">
<xs:sequence>
<xs:element name="HistoName" type="histoName"/>
<xs:element name="HistoType" type="histoType"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="histoName">
<xs:restriction base="xs:string">
<xs:pattern value="hDecay([0-9]){3,}"/> <!-- this means hDecayXXX, where XXX are 3 digits or more -->
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="histoType">
<xs:restriction base="xs:string">
<xs:pattern value="TH1F"></xs:pattern>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="slowControlHistoData">
<xs:sequence>
<xs:element name="SlowControlHistoEntry" type="slowControlHistoEntry" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="slowControlHistoEntry">
<xs:sequence>
<xs:element name="SlowControlName" type="xs:string"/>
<xs:element name="SlowControlType" type="slowControlType"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="slowControlType">
<xs:restriction base="xs:string">
<xs:pattern value="TH1F"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="runHeaderFolder">
<xs:sequence>
<xs:element name="RunInfo" type="runInfo"/>
<xs:element name="DetectorInfo" type="detectorInfo"/>
<xs:element name="SampleEnvironmentInfo" type="sampleEnvironmentInfo"/>
<xs:element name="MagneticFieldEnvironmentInfo" type="magneticFieldEnvironmentInfo"/>
<xs:element name="BeamlineInfo" type="beamlineInfo"/>
<xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded"/> <!-- here can go any additional stuff you like -->
</xs:sequence>
</xs:complexType>
<xs:complexType name="runInfo">
<xs:sequence>
<xs:element name="Version" type="TString"/>
<xs:element name="Generic_Validator_URL" type="TString"/>
<xs:element name="Specific_Validator_URL" type="TString"/>
<xs:element name="Generator" type="TString"/>
<xs:element name="File_Name" type="TString"/>
<xs:element name="Run_Title" type="TString"/>
<xs:element name="Run_Number" type="Int_t"/>
<xs:element name="Run_Start_Time" type="TString"/>
<xs:element name="Run_Stop_Time" type="TString"/>
<xs:element name="Run_Duration" type="TMusrRunPhysicalQuantity"/>
<xs:element name="Laboratory" type="TString"/>
<xs:element name="Instrument" type="TString"/>
<xs:element name="Muon_Beam_Momentum" type="TMusrRunPhysicalQuantity"/>
<xs:element name="Muon_Species" type="TString"/>
<xs:element name="Muon_Source" type="TString"/>
<xs:element name="Setup" type="TString"/>
<xs:element name="Comment" type="TString"/>
<xs:element name="Sample_Name" type="TString"/>
<xs:element name="Sample_Temperature" type="TMusrRunPhysicalQuantity"/>
<xs:element name="Sample_Magnetic_Field" type="TMusrRunPhysicalQuantity"/>
<xs:element name="No_of_Histos" type="Int_t"/>
<xs:element name="Time_Resolution" type="TMusrRunPhysicalQuantity"/>
<xs:element name="RedGreen_Offsets" type="TIntVector"/>
<xs:element name="Moderator" type="TString"/>
<xs:element name="Moderator_HV" type="TMusrRunPhysicalQuantity"/>
<xs:element name="Sample_HV" type="TMusrRunPhysicalQuantity"/>
<xs:element name="Implantation_Energy" type="TMusrRunPhysicalQuantity"/>
<xs:element name="Cuts" type="TString"/>
<xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded"/> <!-- here can go any additional stuff you like -->
</xs:sequence>
</xs:complexType>
<xs:simpleType name="Int_t">
<xs:restriction base="xs:string">
<xs:pattern value="Int_t"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="Double_t">
<xs:restriction base="xs:string">
<xs:pattern value="Double_t"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TString">
<xs:restriction base="xs:string">
<xs:pattern value="TString"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TMusrRunPhysicalQuantity">
<xs:restriction base="xs:string">
<xs:pattern value="TMusrRunPhysicalQuantity"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TIntVector">
<xs:restriction base="xs:string">
<xs:pattern value="TIntVector"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="sampleEnvironmentInfo">
<xs:sequence>
<xs:element name="Cryo" type="TString"/>
<xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded"/> <!-- here can go any additional stuff you like -->
</xs:sequence>
</xs:complexType>
<xs:complexType name="magneticFieldEnvironmentInfo">
<xs:sequence>
<xs:element name="Magnet_Name" type="TString"/>
<xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded"/> <!-- here can go any additional stuff you like -->
</xs:sequence>
</xs:complexType>
<xs:complexType name="detectorInfo">
<xs:sequence>
<xs:element name="Detector" type="detector" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="detector">
<xs:sequence>
<xs:element name="Name" type="TString"/>
<xs:element name="Histo_Number" type="Int_t"/>
<xs:element name="Histo_Length" type="Int_t"/>
<xs:element name="Time_Zero_Bin" type="Double_t"/>
<xs:element name="First_Good_Bin" type="Int_t"/>
<xs:element name="Last_Good_Bin" type="Int_t"/>
<xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded"/> <!-- here can go any additional stuff you like -->
</xs:sequence>
</xs:complexType>
<xs:complexType name="beamlineInfo">
<xs:sequence>
<xs:element name="Name" type="TString"/>
<xs:element name="Beamline_Settings" type="TString"/>
<xs:any processContents="skip" minOccurs="0" maxOccurs="unbounded"/> <!-- here can go any additional stuff you like -->
</xs:sequence>
</xs:complexType>
<xs:complexType name="histoData">
<xs:sequence>
<xs:element name="Entry" type="histoEntry" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="histoEntry">
<xs:sequence>
<xs:element name="Name" type="xs:string"/>
<xs:element name="Type" type="rootHistoType"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="rootHistoType">
<xs:restriction base="xs:string">
<xs:pattern value="TH([1-2])F"/> <!-- this means TH1F or TH2F -->
</xs:restriction>
</xs:simpleType>
</xs:schema>

View File

@ -213,8 +213,10 @@ ClassImp(TMusrRunHeader)
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** /**
* <p>Constructor. * <p>Constructor.
*
* \param quite if set to true, warnings will be omited. Default is false.
*/ */
TMusrRunHeader::TMusrRunHeader() TMusrRunHeader::TMusrRunHeader(bool quite) : fQuite(quite)
{ {
Init(); Init();
} }
@ -224,9 +226,13 @@ TMusrRunHeader::TMusrRunHeader()
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** /**
* <p>Constructor. * <p>Constructor.
*
* \param fileName file name of the MusrRoot file.
* \param quite if set to true, warnings will be omited. Default is false.
*/ */
TMusrRunHeader::TMusrRunHeader(const char *fileName) TMusrRunHeader::TMusrRunHeader(const char *fileName, bool quite)
{ {
fQuite = quite;
Init(TString(fileName)); Init(TString(fileName));
} }
@ -243,6 +249,11 @@ void TMusrRunHeader::Init(TString fileName)
fFileName = fileName; fFileName = fileName;
fVersion = TString("$Id$"); fVersion = TString("$Id$");
Set("RunInfo/Version", fVersion); Set("RunInfo/Version", fVersion);
Set("RunInfo/Generic Validator URL", "http://lmu.web.psi.ch/facilities/software/MusrRoot/validation/MusrRoot.xsd");
Set("DetectorInfo/Detector000/Name", "n/a");
Set("SampleEnvironmentInfo/Cryo", "n/a");
Set("MagneticFieldEnvironmentInfo/Magnet Name", "n/a");
Set("BeamlineInfo/Name", "n/a");
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@ -280,82 +291,67 @@ void TMusrRunHeader::CleanUp()
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** /**
* <p>Fills the RunHeader folder. This is needed to write it to a ROOT file. * <p>Fills the RunHeader folder. This is needed to write it to a ROOT file.
* It walks through all information and attaches it to folder. * It walks through all information and attaches it to the folder or replaces
* it, if it is already present.
* *
* \param folder to be filled * \param folder to be filled
*/ */
Bool_t TMusrRunHeader::FillFolder(TFolder *folder) Bool_t TMusrRunHeader::FillFolder(TFolder *folder)
{ {
TObjArray *oarray, *tokens; TObjArray *oarray;
vector<TObjArray*> content; TObjString ostr, *p_ostr;
TObjString ostr; TString path, name, str;
TString path, name, pathName; Ssiz_t pos=0;
bool found=false;
if (folder == 0) { if (folder == 0) {
cerr << endl << ">> TMusrRunHeader::FillFolder(): **ERROR** folder == 0!!" << endl; cerr << endl << ">> TMusrRunHeader::FillFolder(): **ERROR** folder == 0!!" << endl;
return false; return false;
} }
folder->SetOwner(); // folder takes ownership of all added objects! folder->SetOwner(); // folder takes ownership of all added objects! This means that the folder object does the cleanup
// update/generate tree structure in folder
for (UInt_t i=0; i<fPathNameOrder.size(); i++) { for (UInt_t i=0; i<fPathNameOrder.size(); i++) {
tokens = fPathNameOrder[i].Tokenize('/'); path=fPathNameOrder[i];
if (tokens == 0) {
cout << endl << ">> TMusrRunHeader::FillFolder(): **ERROR** couldn't tokenize string " << fPathNameOrder[i] << endl; if (!UpdateFolder(folder, path))
return false; return false;
} }
Int_t idx; // update/generate tree content
if (tokens->GetEntries() == 2) { // <path>/<value> for (UInt_t i=0; i<fPathNameOrder.size(); i++) {
path = ((TObjString*)tokens->At(0))->GetString(); path=fPathNameOrder[i];
idx = ObjectPresent(content, path); pos = path.Last('/');
if (idx == -1) { if (pos == -1) {
// add object array cerr << endl << ">> TMusrRunHeader::FillFolder(): **ERROR** somethig is wrong with the path=" << path << " !!" << endl;
oarray = new TObjArray(); return false;
oarray->SetName(path);
content.push_back(oarray);
idx = content.size()-1;
} }
// add value path.Remove(pos); // remove the value from the path
ostr = GetHeaderString(i);
content[idx]->AddLast(ostr.Clone()); oarray = (TObjArray*)FindObject(folder, path);
} else { // <path>/../<path>/<value> if (!oarray) {
path = ((TObjString*)tokens->At(0))->GetString(); cerr << endl << ">> TMusrRunHeader::FillFolder(): **ERROR** couldn't create header structure!!" << endl;
idx = ObjectPresent(content, path); return false;
if (idx == -1) {
// add object array
oarray = new TObjArray();
oarray->SetName(path);
content.push_back(oarray);
idx = content.size()-1;
} }
// add necessary sub object arrays // check if <value> is already found in oarray
pathName = fPathNameOrder[i]; ostr = GetHeaderString(i); // encode the string for the MusrRoot file
RemoveFirst(pathName, '/'); name = ostr.GetString(); // convert to TString
AddSubTrees(content[idx], pathName); str = GetFirst(name, ':'); // get the first part of the encoded string, i.e. <nnn> - <name>
found = false;
// get header string for (Int_t j=0; j<oarray->GetEntriesFast(); j++) {
ostr = GetHeaderString(i); p_ostr = (TObjString*) oarray->At(j);
if (p_ostr->GetString().BeginsWith(str)) { // present hence replace
// set object string on the right position within content oarray->AddAt(ostr.Clone(), j);
SetSubTreeObject(content[idx], ostr, i); found = true;
} break;
// clean up
if (tokens) {
delete tokens;
tokens = 0;
} }
} }
if (!found) {
// fill folder with all run header information oarray->AddLast(ostr.Clone());
for (UInt_t i=0; i<content.size(); i++) { }
folder->Add(content[i]);
} }
// clean up
content.clear();
return true; return true;
} }
@ -525,10 +521,11 @@ void TMusrRunHeader::GetValue(TString pathName, TDoubleVector &value, Bool_t &ok
*/ */
void TMusrRunHeader::Set(TString pathName, TString value) void TMusrRunHeader::Set(TString pathName, TString value)
{ {
// check if pathName is already set, and if not add it as a new entry // check if pathName is already set, if not add it as a new entry, otherwise replace it
UInt_t i=0; UInt_t i=0;
for (i=0; i<fStringObj.size(); i++) { for (i=0; i<fStringObj.size(); i++) {
if (!fStringObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) { if (!fStringObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
if (!fQuite)
cerr << endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << endl; cerr << endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << endl;
fStringObj[i].SetType("TString"); fStringObj[i].SetType("TString");
fStringObj[i].SetValue(value); fStringObj[i].SetValue(value);
@ -558,10 +555,11 @@ void TMusrRunHeader::Set(TString pathName, TString value)
*/ */
void TMusrRunHeader::Set(TString pathName, Int_t value) void TMusrRunHeader::Set(TString pathName, Int_t value)
{ {
// check if pathName is already set, and if not add it as a new entry // check if pathName is already set, if not add it as a new entry, otherwise replace it
UInt_t i=0; UInt_t i=0;
for (i=0; i<fIntObj.size(); i++) { for (i=0; i<fIntObj.size(); i++) {
if (!fIntObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) { if (!fIntObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
if (!fQuite)
cerr << endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << endl; cerr << endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << endl;
fIntObj[i].SetType("Int_t"); fIntObj[i].SetType("Int_t");
fIntObj[i].SetValue(value); fIntObj[i].SetValue(value);
@ -591,10 +589,11 @@ void TMusrRunHeader::Set(TString pathName, Int_t value)
*/ */
void TMusrRunHeader::Set(TString pathName, Double_t value) void TMusrRunHeader::Set(TString pathName, Double_t value)
{ {
// check if pathName is already set, and if not add it as a new entry // check if pathName is already set, if not add it as a new entry, otherwise replace it
UInt_t i=0; UInt_t i=0;
for (i=0; i<fDoubleObj.size(); i++) { for (i=0; i<fDoubleObj.size(); i++) {
if (!fDoubleObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) { if (!fDoubleObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
if (!fQuite)
cerr << endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << endl; cerr << endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << endl;
fDoubleObj[i].SetType("Double_t"); fDoubleObj[i].SetType("Double_t");
fDoubleObj[i].SetValue(value); fDoubleObj[i].SetValue(value);
@ -624,10 +623,11 @@ void TMusrRunHeader::Set(TString pathName, Double_t value)
*/ */
void TMusrRunHeader::Set(TString pathName, TMusrRunPhysicalQuantity value) void TMusrRunHeader::Set(TString pathName, TMusrRunPhysicalQuantity value)
{ {
// check if pathName is already set, and if not add it as a new entry // check if pathName is already set, if not add it as a new entry, otherwise replace it
UInt_t i=0; UInt_t i=0;
for (i=0; i<fMusrRunPhysQuantityObj.size(); i++) { for (i=0; i<fMusrRunPhysQuantityObj.size(); i++) {
if (!fMusrRunPhysQuantityObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) { if (!fMusrRunPhysQuantityObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
if (!fQuite)
cerr << endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << endl; cerr << endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << endl;
fMusrRunPhysQuantityObj[i].SetType("TMusrRunHeader"); fMusrRunPhysQuantityObj[i].SetType("TMusrRunHeader");
fMusrRunPhysQuantityObj[i].SetValue(value); fMusrRunPhysQuantityObj[i].SetValue(value);
@ -657,10 +657,11 @@ void TMusrRunHeader::Set(TString pathName, TMusrRunPhysicalQuantity value)
*/ */
void TMusrRunHeader::Set(TString pathName, TStringVector value) void TMusrRunHeader::Set(TString pathName, TStringVector value)
{ {
// check if pathName is already set, and if not add it as a new entry // check if pathName is already set, if not add it as a new entry, otherwise replace it
UInt_t i=0; UInt_t i=0;
for (i=0; i<fStringVectorObj.size(); i++) { for (i=0; i<fStringVectorObj.size(); i++) {
if (!fStringVectorObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) { if (!fStringVectorObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
if (!fQuite)
cerr << endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << endl; cerr << endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << endl;
fStringVectorObj[i].SetType("TStringVector"); fStringVectorObj[i].SetType("TStringVector");
fStringVectorObj[i].SetValue(value); fStringVectorObj[i].SetValue(value);
@ -690,10 +691,11 @@ void TMusrRunHeader::Set(TString pathName, TStringVector value)
*/ */
void TMusrRunHeader::Set(TString pathName, TIntVector value) void TMusrRunHeader::Set(TString pathName, TIntVector value)
{ {
// check if pathName is already set, and if not add it as a new entry // check if pathName is already set, if not add it as a new entry, otherwise replace it
UInt_t i=0; UInt_t i=0;
for (i=0; i<fIntVectorObj.size(); i++) { for (i=0; i<fIntVectorObj.size(); i++) {
if (!fIntVectorObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) { if (!fIntVectorObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
if (!fQuite)
cerr << endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << endl; cerr << endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << endl;
fIntVectorObj[i].SetType("TIntVector"); fIntVectorObj[i].SetType("TIntVector");
fIntVectorObj[i].SetValue(value); fIntVectorObj[i].SetValue(value);
@ -723,10 +725,11 @@ void TMusrRunHeader::Set(TString pathName, TIntVector value)
*/ */
void TMusrRunHeader::Set(TString pathName, TDoubleVector value) void TMusrRunHeader::Set(TString pathName, TDoubleVector value)
{ {
// check if pathName is already set, and if not add it as a new entry // check if pathName is already set, if not add it as a new entry, otherwise replace it
UInt_t i=0; UInt_t i=0;
for (i=0; i<fDoubleVectorObj.size(); i++) { for (i=0; i<fDoubleVectorObj.size(); i++) {
if (!fDoubleVectorObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) { if (!fDoubleVectorObj[i].GetPathName().CompareTo(pathName, TString::kIgnoreCase)) {
if (!fQuite)
cerr << endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << endl; cerr << endl << ">> **WARNING** " << pathName.Data() << " already exists, will replace it." << endl;
fDoubleVectorObj[i].SetType("TDoubleVector"); fDoubleVectorObj[i].SetType("TDoubleVector");
fDoubleVectorObj[i].SetValue(value); fDoubleVectorObj[i].SetValue(value);
@ -1365,23 +1368,89 @@ TString TMusrRunHeader::GetType(TString str)
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// ObjectPresent (private) // UpdateFolder (private)
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** /**
* <p> * <p>Update folder structure
* *
* \param content * <p><b>return:</b>
* \param path * - true if everything is all right
* - false otherwise
*
* \param treeObj to be updated
* \param path to be added within 'treeObj'
*/ */
Int_t TMusrRunHeader::ObjectPresent(vector<TObjArray*> &content, TString &path) bool TMusrRunHeader::UpdateFolder(TObject *treeObj, TString path)
{ {
for (UInt_t i=0; i<content.size(); i++) { if (path.First('/') == -1) // only value element left, hence nothing to be done
if (content[i]->GetName() == path) { return true;
return (Int_t)i;
} TString str = GetFirst(path, '/');
TObject *obj = treeObj->FindObject(str);
// remove the first path element
if (!RemoveFirst(path, '/')) {
cerr << endl << ">> TMusrRunHeader::FillFolder(): **ERROR** couldn't tokenize path!!" << endl;
return false;
} }
return -1; if (!obj) { // required object not present, create it
TObjArray *oarray = new TObjArray();
if (!oarray) {
cerr << endl << ">> TMusrRunHeader::FillFolder(): **ERROR** couldn't create header structure!!" << endl;
return false;
}
// set the name of the new TObjArray
oarray->SetName(str);
if (!strcmp(treeObj->ClassName(), "TFolder"))
((TFolder*)treeObj)->Add(oarray);
else // it is a TObjArray
((TObjArray*)treeObj)->AddLast(oarray);
return UpdateFolder(oarray, path);
} else { // object present, hence check rest of the path
return UpdateFolder(obj, path);
}
}
//--------------------------------------------------------------------------
// FindObject (private)
//--------------------------------------------------------------------------
/**
* <p>Check if 'path' is present in 'treeObj'
*
* <p><b>return:</b>
* - pointer to the 'path' object if present
* - otherwise return 0
*
* \param treeObj to be searched
* \param path searched for within 'treeObj'
*/
TObject* TMusrRunHeader::FindObject(TObject *treeObj, TString path)
{
Ssiz_t pos;
TObject *obj=0;
// make sure that treeObj is either TFolder or TObjArray
if (strcmp(treeObj->ClassName(), "TFolder") && strcmp(treeObj->ClassName(), "TObjArray"))
return obj;
pos = path.First('/');
if (pos == -1) { // i.e. no sub-paths anymore
obj = treeObj->FindObject(path);
return obj;
} else { // sub-paths present
TString objName = GetFirst(path, '/'); // get first token of the path <objName0>/<objName1>/.../<objNameN>
obj = treeObj->FindObject(objName);
if (obj) { // object found, check for subPath object
RemoveFirst(path, '/'); // remove first tokens of the path
return FindObject(obj, path);
} else { // object not found
return obj;
}
}
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@ -1536,22 +1605,36 @@ TObjString TMusrRunHeader::GetHeaderString(UInt_t idx)
// RemoveFirst (private) // RemoveFirst (private)
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** /**
* <p> * <p>Removes the first junk of a string up to 'splitter'. If 'splitter' is
* NOT present in the string, the string stays untouched and the routine
* returns false.
* *
* \param str * \param str string to be truncated
* \param splitter * \param splitter the start of the string up to the splitter character removed
*/ */
void TMusrRunHeader::RemoveFirst(TString &str, const char splitter) bool TMusrRunHeader::RemoveFirst(TString &str, const char splitter)
{ {
Ssiz_t idx = str.First(splitter); Ssiz_t idx = str.First(splitter);
if (idx == -1)
return false;
str.Remove(0, idx+1); str.Remove(0, idx+1);
return true;
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
// GetFirst (private) // GetFirst (private)
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/** /**
* <p> * <p>Assuming a string built like 'this/is/a/string:with:diffrent:splitters'.
* Using as splitter '/', this routine would return 'this', it means get from str
* everything up to the first occurance of splitter. If splitter would be ':'
* in this example, the return string would be 'this/is/a/string'.
*
* <p>If splitter is <b>not</b> present in str the original str is returned.
*
* <p><b>return:</b> first part of up to the splitter in struct
* *
* \param str * \param str
* \param splitter * \param splitter
@ -1561,71 +1644,10 @@ TString TMusrRunHeader::GetFirst(TString &str, const char splitter)
TString result = str; TString result = str;
Ssiz_t idx = str.First(splitter); Ssiz_t idx = str.First(splitter);
if (idx != -1)
result.Remove(idx, str.Length()); result.Remove(idx, str.Length());
return result; return result;
} }
//--------------------------------------------------------------------------
// AddSubTrees (private)
//--------------------------------------------------------------------------
/**
* <p>
*
* \param content
* \param pathName
*/
void TMusrRunHeader::AddSubTrees(TObjArray *content, TString pathName)
{
// check if element is already present
TString objName = GetFirst(pathName, '/');
if (!content->FindObject(objName.Data())) { // object array not present yet, add it
TObjArray *oarray = new TObjArray();
oarray->SetName(objName);
content->AddLast(oarray);
}
// check if more sub trees are needed
TObjArray *tok = pathName.Tokenize('/');
if (tok->GetEntries() > 2) { // still sub trees present
RemoveFirst(pathName, '/');
AddSubTrees((TObjArray*)content->FindObject(objName.Data()), pathName);
}
if (tok)
delete tok;
}
//--------------------------------------------------------------------------
// SetSubTreeObject (private)
//--------------------------------------------------------------------------
/**
* <p>
*
* \param content
* \param ostr
*/
void TMusrRunHeader::SetSubTreeObject(TObjArray *content, TObjString ostr, Int_t idx)
{
TObjArray *tok = fPathNameOrder[idx].Tokenize('/');
TObjArray *pos = content;
for (Int_t i=1; i<tok->GetEntries()-1; i++) {
pos = (TObjArray*)pos->FindObject(((TObjString*)tok->At(i))->GetString()); // go down the proper tree
if (pos == 0) {
cerr << endl << "TMusrRunHeader::SetSubTreeObject(): **ERROR** couldn't reach requested path: " << fPathNameOrder[idx];
if (tok)
delete tok;
return;
}
}
TObjString *value = new TObjString();
value = (TObjString*)ostr.Clone();
pos->AddLast(value);
if (tok)
delete tok;
}
// end --------------------------------------------------------------------- // end ---------------------------------------------------------------------

View File

@ -32,6 +32,9 @@
#ifndef TMUSRRUNHEADER_H #ifndef TMUSRRUNHEADER_H
#define TMUSRRUNHEADER_H #define TMUSRRUNHEADER_H
#include <vector>
using namespace std;
#include <TDatime.h> #include <TDatime.h>
#include <TObject.h> #include <TObject.h>
#include <TQObject.h> #include <TQObject.h>
@ -122,8 +125,8 @@ private:
class TMusrRunHeader : public TObject class TMusrRunHeader : public TObject
{ {
public: public:
TMusrRunHeader(); TMusrRunHeader(bool quite=false);
TMusrRunHeader(const char *fileName); TMusrRunHeader(const char *fileName, bool quite=false);
virtual ~TMusrRunHeader(); virtual ~TMusrRunHeader();
virtual TString GetFileName() { return fFileName; } virtual TString GetFileName() { return fFileName; }
@ -155,6 +158,7 @@ public:
virtual void DrawHeader(); virtual void DrawHeader();
private: private:
bool fQuite;
TString fFileName; TString fFileName;
TString fVersion; TString fVersion;
@ -166,7 +170,7 @@ private:
vector< TMusrRunObject<TIntVector> > fIntVectorObj; vector< TMusrRunObject<TIntVector> > fIntVectorObj;
vector< TMusrRunObject<TDoubleVector> > fDoubleVectorObj; vector< TMusrRunObject<TDoubleVector> > fDoubleVectorObj;
vector< TString > fPathNameOrder; ///< keeps the path-name as they or set and hence its ordering vector< TString > fPathNameOrder; ///< keeps the path-name as they were created in ordered to keep ordering
virtual void Init(TString str="n/a"); virtual void Init(TString str="n/a");
virtual void CleanUp(); virtual void CleanUp();
@ -179,13 +183,12 @@ private:
virtual TString GetStrValue(TString str); virtual TString GetStrValue(TString str);
virtual TString GetType(TString str); virtual TString GetType(TString str);
virtual Int_t ObjectPresent(vector<TObjArray*> &content, TString &path); virtual bool UpdateFolder(TObject *treeObj, TString path);
virtual TObject* FindObject(TObject *treeObj, TString path);
virtual TObjString GetHeaderString(UInt_t idx); virtual TObjString GetHeaderString(UInt_t idx);
virtual void RemoveFirst(TString &str, const char splitter); virtual bool RemoveFirst(TString &str, const char splitter);
virtual TString GetFirst(TString &str, const char splitter); virtual TString GetFirst(TString &str, const char splitter);
virtual void AddSubTrees(TObjArray *content, TString pathName);
virtual void SetSubTreeObject(TObjArray *content, TObjString ostr, Int_t idx);
ClassDef(TMusrRunHeader, 1) ClassDef(TMusrRunHeader, 1)
}; };

View File

@ -135,7 +135,6 @@ void dumpObjArray(TObjArray *obj, UInt_t offset)
xmlLabel = TString(obj->GetName()); xmlLabel = TString(obj->GetName());
if (xmlLabel.BeginsWith("Detector")) { if (xmlLabel.BeginsWith("Detector")) {
xmlLabel.Remove(0, 8); // remove 'Detector' xmlLabel.Remove(0, 8); // remove 'Detector'
cout << endl << "debug>> xmlLablel=" << xmlLabel;
if (xmlLabel.IsDigit()) if (xmlLabel.IsDigit())
xmlLabel = "Detector"; xmlLabel = "Detector";
else else
@ -309,6 +308,11 @@ void getLabel(TString entry, TString &label)
label.Remove(0, start+2); label.Remove(0, start+2);
label.Remove(end-start-2, label.Length()); label.Remove(end-start-2, label.Length());
// replace spaces through underscores label.ReplaceAll(' ', '_'); // replace spaces through underscores
label.ReplaceAll(' ', '_'); label.ReplaceAll('(', '_'); // replace '(' through underscores
label.ReplaceAll(')', '_'); // replace ')' through underscores
label.ReplaceAll('[', '_'); // replace '[' through underscores
label.ReplaceAll(']', '_'); // replace ']' through underscores
label.ReplaceAll('{', '_'); // replace '[' through underscores
label.ReplaceAll('}', '_'); // replace ']' through underscores
} }

View File

@ -220,10 +220,6 @@ int main(int argc, char *argv[])
} }
// root file header related things // root file header related things
/*
TFolder *runHeader = gROOT->GetRootFolder()->AddFolder("RunHeader", "MusrRoot Run Header Info");
gROOT->GetListOfBrowsables()->Add(runHeader, "RunHeader");
*/
TFolder *runHeader = new TFolder("RunHeader", "MusrRoot Run Header Info"); TFolder *runHeader = new TFolder("RunHeader", "MusrRoot Run Header Info");
if (header->FillFolder(runHeader)) { if (header->FillFolder(runHeader)) {