/* This file is part of MAUS: http://micewww.pp.rl.ac.uk:8080/projects/maus
*
* MAUS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MAUS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MAUS. If not, see .
*
*/
/*!
* \file rstream.h
*
* \author Alexander Richards, Imperial College London
* \date 06/01/2012
*
* This is the abstract base class for root file streaming. It defines some common
* functionality at this abstract level. Such functionality includes checking
* is a file is open. Initialising a root file and attaching externally defined
* variables/objects to branches. It also stores a collection of pointers to
* branch variables. This is necessary as when using root trees, pointers to
* variables may not go out of scope and be destroyed.
*
*/
#ifndef RSTREAM_H
#define RSTREAM_H 1
#include
#include
#include
#include
#include "Utils/Squeak.hh"
/*!
* \class rstream
*
* \brief Abstract base class for Root streaming
*
* This class is set up to be intuitive to users of the standard c++
* iostream library. A lot of common functionality is abstracted at this level
* to make the code more scalable and managable.
* \author Alexander Richards, Imperial College London
* \date 06/01/2012
*/
class rstream {
public:
/*!\brief Constructor
* \param char* the name of the root file to open
* \param char* the mode specifier to use when opening
* \param MsgStream::LEVEL the level of the logging output.
*/
rstream(const char*, const char*);
/*!\brief check if the file is open
* \return boolean value indicating the presence of an open file.
*/
virtual bool is_open();
// ! Destructor
virtual ~rstream();
// ! Close the file and cleanup, pure virtual function.
virtual void close() = 0;
/*!\brief set the currently active branch
* \param rstream& the stream to set the active branch of
* \param char* the name to use for the branch
* \return the rstream object from param 1
*/
static rstream& setBranch(rstream& rs, const char* name);
protected:
/*!
* \brief attach a branch to the non-pointer data type d
* Templated function to attach the currently defined branch to
* a data type T.
* \param T& The data type to attach to the branch.
* \return *this
*/
template rstream& attachBranch(T& d, bool, bool);
/*!
* \brief attach a branch to the pointer data type d
* Templated function to attach the currently defined branch to
* a data type T.
* \param T*& The data type to attach to the branch.
* \return *this
*/
template rstream& attachBranch(T* & d, bool, bool);
/*!\var TTree* m_tree
* \brief pointer to the working tree.
*/
TTree* m_tree;
/*!\var long m_evtCount
* \brief event counter.
*/
long m_evtCount;
/*!\var TFile* m_file
* \brief Pointer to the open file.
*/
TFile* m_file;
/*!\var char* m_branchName
* \brief The currently defined branch name.
*/
char* m_branchName;
/*!\var std::vector m_pointers
* \brief collection of pointers to data types.
*/
std::vector m_pointers;
};
// Member functions template definitions
// \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
// template implementation - Non pointer
// \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
template rstream& rstream::attachBranch(T& d,
bool doublePointer,
bool createNonExistentBranch) {
if (!strcmp(m_branchName, "")) {
MAUS::Squeak::mout(MAUS::Squeak::error)
<< "No branch name set"
<< std::endl;
MAUS::Squeak::mout(MAUS::Squeak::info)
<< "Setup a branch name before attaching a data object using << branchName(\"MyBranch\")"
<< std::endl;
strcpy(m_branchName, "");
return *this;
}
if (!m_tree->FindBranch(m_branchName) && !createNonExistentBranch) {
MAUS::Squeak::mout(MAUS::Squeak::error)
<< "Branch not found"
<< std::endl;
MAUS::Squeak::mout(MAUS::Squeak::info)
<< "Could not find the requested branch in the tree"
<< std::endl;
strcpy(m_branchName, "");
return *this;
}
m_pointers.push_back(&d);
T** data1 = 0;
T* data2 = 0;
if (doublePointer) {
data1 = reinterpret_cast(&m_pointers.back());
} else {
data2 = reinterpret_cast( m_pointers.back());
}
if (!m_tree->FindBranch(m_branchName)) {
if (doublePointer) {
m_tree->Branch(m_branchName, data1);
} else {
m_tree->Branch(m_branchName, data2);
}
} else {
if (doublePointer) {
m_tree->SetBranchAddress(m_branchName, data1);
} else {
m_tree->SetBranchAddress(m_branchName, data2);
}
}
// this has effect of forcing the user to use branchName("blah") before setting
// every variable as resets the branchname and will get above warning
strcpy(m_branchName, "");
return *this;
}
// \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
// template implementation - Pointer
// \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
template rstream& rstream::attachBranch(T* & d,
bool doublePointer,
bool createNonExistentBranch) {
if (!strcmp(m_branchName, "")) {
MAUS::Squeak::mout(MAUS::Squeak::error)
<< "No branch name set"
<< std::endl;
MAUS::Squeak::mout(MAUS::Squeak::info)
<< "Setup a branch name before attaching a data object using << branchName(\"MyBranch\")"
<< std::endl;
strcpy(m_branchName, "");
return *this;
}
if (!m_tree->FindBranch(m_branchName) && !createNonExistentBranch) {
MAUS::Squeak::mout(MAUS::Squeak::error)
<< "Branch not found"
<< std::endl;
MAUS::Squeak::mout(MAUS::Squeak::info)
<< "Could not find the requested branch in the tree"
<< std::endl;
strcpy(m_branchName, "");
return *this;
}
if (!m_tree->FindBranch(m_branchName)) {
if (doublePointer) {
m_tree->Branch(m_branchName, &d);
} else {
m_tree->Branch(m_branchName, d);
}
} else {
if (doublePointer) {
m_tree->SetBranchAddress(m_branchName, &d);
} else {
m_tree->SetBranchAddress(m_branchName, d);
}
}
// this has effect of forcing the user to use branchName("blah") before setting
// every variable as resets the branchname and will get above warning
strcpy(m_branchName, "");
return *this;
}
#endif