Code owners
Assign users and groups as approvers for specific file changes. Learn more.
THistSvc.icc 11.03 KiB
/***********************************************************************************\
* (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
* *
* This software is distributed under the terms of the Apache version 2 licence, *
* copied verbatim in the file "LICENSE". *
* *
* In applying this licence, CERN does not waive the privileges and immunities *
* granted to it by virtue of its status as an Intergovernmental Organization *
* or submit itself to any jurisdiction. *
\***********************************************************************************/
#ifndef GAUDISVC_THISTSVC_ICC
#define GAUDISVC_THISTSVC_ICC
#include <map>
#include <string>
#include "TFile.h"
#include "TObject.h"
#ifndef GAUDIKERNEL_MSGSTREAM_H
# include "GaudiKernel/MsgStream.h"
#endif
#include "GaudiKernel/System.h"
template <typename T>
StatusCode THistSvc::regHist_i( std::unique_ptr<T> hist, const std::string& id, bool shared ) {
THistID* hid = nullptr;
return regHist_i( std::move( hist ), id, shared, hid );
}
template <typename T>
StatusCode THistSvc::regHist_i( std::unique_ptr<T> hist_unique, const std::string& id, bool shared, THistID*& phid ) {
GlobalDirectoryRestore restore( m_svcMut );
phid = nullptr;
// It is sad that we lose propper memory management here
T* hist = nullptr;
if ( hist_unique.get() != nullptr ) { hist = hist_unique.release(); }
if ( msgLevel( MSG::DEBUG ) ) {
debug() << "regHist_i obj: " << hist << " id: " << id << " s: " << shared << endmsg;
}
std::string idr( id );
removeDoubleSlash( idr );
if ( idr.find( "/" ) == idr.length() ) {
error() << "Badly formed identifier \"" << idr << "\": "
<< "Must not end with a /" << endmsg;
delete hist;
return StatusCode::FAILURE;
}
TFile* f = nullptr;
std::string stream, name;
if ( !findStream( idr, stream, name, f ) ) {
error() << "Could not register id: \"" << idr << "\"" << endmsg;
delete hist;
return StatusCode::FAILURE;
}
std::string uid = "/" + stream + "/" + name;
uidMap_t::iterator uitr = m_uids.find( uid );
bool exists( false );
if ( uitr != m_uids.end() ) {
exists = true;
TObject* t1 = uitr->second->at( 0 ).obj;
if ( hist->Compare( t1 ) != 0 ) {
error() << "previously registered object with identifier \"" << uid << "\" does not compare to this one"
<< endmsg;
delete hist;
return StatusCode::FAILURE;
} else {
if ( msgLevel( MSG::DEBUG ) ) {
debug() << "previously registered id \"" << uid << "\": num " << uitr->second->size() << endmsg;
}
}
}
bool temp = false;
if ( !f ) {
temp = true;
if ( msgLevel( MSG::DEBUG ) ) { debug() << "Historgram with id \"" << idr << "\" is temporary" << endmsg; }
}
TObject* to = nullptr;
THistID hid;
// check to see if this hist is to be read in;
if ( !temp && m_files.find( stream )->second.second == READ ) {
if ( hist != 0 ) { warning() << "Registering id: \"" << idr << "\" with non zero pointer!" << endmsg; }
hist = readHist_i<T>( idr );
if ( hist == nullptr ) {
error() << "Unable to read in hist" << endmsg;
delete hist;
return StatusCode::FAILURE;
}
to = dynamic_cast<TObject*>( hist );
hid = THistID( uid, temp, to, f, m_files.find( stream )->second.second );
} else if ( !hist ) {
error() << "Unable to read in hist with id: \"" << idr << "\"" << endmsg;
delete hist;
return StatusCode::FAILURE;
} else {
to = dynamic_cast<TObject*>( hist );
if ( to == nullptr ) {
error() << "Could not dcast to TObject. id: \"" << idr << "\"" << endmsg;
delete hist;
return StatusCode::FAILURE;
}
auto oitr = m_tobjs.find( to );
if ( oitr != m_tobjs.end() ) {
error() << "already registered id: \"" << idr << "\" with identifier \""
<< oitr->second.first->at( oitr->second.second ).id << "\"" << endmsg;
delete hist;
return StatusCode::FAILURE;
}
const auto findF = m_files.find( stream );
hid = ( findF != m_files.end() ? THistID( uid, temp, to, f, findF->second.second ) : THistID( uid, temp, to, f ) );
hid.shared = shared;
TDirectory* dir = changeDir( hid );
if ( TTree* tree = dynamic_cast<TTree*>( hist ) ) {
tree->SetDirectory( dir );
} else if ( TH1* th1 = dynamic_cast<TH1*>( hist ) ) {
th1->SetDirectory( dir );
} else if ( TEfficiency* teff = dynamic_cast<TEfficiency*>( hist ) ) {
teff->SetDirectory( dir );
} else if ( dynamic_cast<TGraph*>( hist ) ) {
dir->Append( hist );
} else {
error() << "id: \"" << idr << "\" is not a TH, TTree, TGraph, or TEfficiency. Attaching it to current dir."
<< endmsg;
dir->Append( hist );
}
}
std::string fname;
if ( !f ) {
fname = "none";
} else {
fname = f->GetName();
}
if ( msgLevel( MSG::DEBUG ) ) {
debug() << "Registering" << ( shared ? " shared " : " " ) << System::typeinfoName( typeid( *hist ) ) << " title: \""
<< hist->GetTitle() << "\" id: \"" << uid
<< "\" dir: "
// << hist->GetDirectory()->GetPath() << " "
<< changeDir( hid )->GetPath() << " file: " << fname << endmsg;
}
// create a mutex for all shared histograms
if ( shared ) { hid.mutex = new histMut_t; }
if ( exists ) {
vhid_t* vi = uitr->second;
vi->push_back( hid );
phid = &( vi->back() );
m_tobjs.emplace( to, std::pair<vhid_t*, size_t>( vi, vi->size() - 1 ) );
} else {
vhid_t* vi = new vhid_t{hid};
m_hlist.emplace( m_hlist.end(), vi );
phid = &( vi->back() );
m_uids.emplace( uid, vi );
m_ids.emplace( name, vi );
m_tobjs.emplace( to, std::pair<vhid_t*, size_t>( vi, 0 ) );
}
if ( msgLevel( MSG::DEBUG ) ) { debug() << "regHist_i THistID: " << hid << endmsg;}
return StatusCode::SUCCESS;
}
template <typename T>
T* THistSvc::getHist_i( const std::string& id, const size_t& ind, bool quiet ) const {
// id starts with "/": unique
GlobalDirectoryRestore restore( m_svcMut );
T* hist = nullptr;
const THistID* hid = nullptr;
size_t num = findHistID( id, hid, ind );
if ( num == 0 ) {
// no matches found
if ( !quiet ) { error() << "could not locate Hist with id \"" << id << "\"" << endmsg; }
return nullptr;
} else if ( num > 1 ) {
if ( !quiet ) {
// return failure if trying to GET a single hist
error() << "Multiple matches with id \"" << id << "\"."
<< " Further specifications required." << endmsg;
return nullptr;
} else {
info() << "Found multiple matches with id \"" << id << "\"" << endmsg;
// return first match if just INQUIRING (i.e. != nullptr)
hist = dynamic_cast<T*>( hid->obj );
if ( hist == nullptr ) {
error() << "dcast failed, Hist id: \"" << id << "\"" << endmsg;
return nullptr;
}
}
} else {
hist = dynamic_cast<T*>( hid->obj );
if ( hist == nullptr ) {
error() << "dcast failed, Hist id: \"" << id << "\"" << endmsg;
return nullptr;
}
if ( msgLevel( MSG::VERBOSE) ) {
verbose() << "found unique Hist title: \"" << hist->GetTitle() << "\" id: \"" << id << "\"" << endmsg;
}
}
return hist;
}
template <typename T>
T* THistSvc::readHist_i( const std::string& id ) const {
GlobalDirectoryRestore restore( m_svcMut );
std::string idr( id );
removeDoubleSlash( idr );
std::string stream, rem, dir, fdir, bdir, fdir2;
TFile* file = nullptr;
if ( !findStream( idr, stream, rem, file ) ) { return nullptr; }
if ( !file ) {
error() << "no associated file found" << endmsg;
return nullptr;
}
file->cd( "/" );
fdir = idr;
bdir = stripDirectoryName( fdir );
fdir2 = fdir;
while ( ( dir = stripDirectoryName( fdir ) ) != "" ) {
if ( !gDirectory->GetKey( dir.c_str() ) ) {
error() << "Directory \"" << fdir2 << "\" doesnt exist in " << file->GetName() << endmsg;
return nullptr;
}
gDirectory->cd( dir.c_str() );
}
TObject* to = nullptr;
gDirectory->GetObject( fdir.c_str(), to );
if ( !to ) {
error() << "Could not get obj \"" << fdir << "\" in " << gDirectory->GetPath() << endmsg;
return nullptr;
}
T* hist = dynamic_cast<T*>( to );
if ( hist == nullptr ) {
error() << "Could not convert \"" << idr << "\" to a " << System::typeinfoName( typeid( *hist ) ) << " as is a "
<< to->IsA()->GetName() << endmsg;
return nullptr;
}
if ( msgLevel( MSG::DEBUG ) ) {
debug() << "Read in " << hist->IsA()->GetName() << " \"" << hist->GetName() << "\" from file " << file->GetName()
<< endmsg;
hist->Print();
}
return hist;
}
template <typename T>
LockedHandle<T> THistSvc::regShared_i( const std::string& id, std::unique_ptr<T> hist ) {
LockedHandle<T> lh( nullptr, nullptr );
const THistID* hid = nullptr;
if ( findHistID( id, hid ) == 0 ) {
T* phist = hist.get();
THistID* phid = nullptr;
if ( regHist_i( std::move( hist ), id, true, phid ).isSuccess() ) {
lh.set( phist, phid->mutex );
} else {
error() << "regSharedHist: unable to register shared hist with id \"" << id << "\"" << endmsg;
}
} else {
if ( !hid->shared ) {
error() << "regSharedHist: previously register Hist with id \"" << id << "\" was not marked shared" << endmsg;
}
if ( hist->Compare( hid->obj ) != 0 ) {
error() << "regSharedHist: Histogram " << id << " does not compare with " << hid << endmsg;
} else {
T* phist = dynamic_cast<T*>( hid->obj );
if ( phist == 0 ) {
error() << "regSharedHist: unable to dcast retrieved shared hist \"" << id << "\" of type "
<< hid->obj->IsA()->GetName() << " to requested type " << System::typeinfoName( typeid( T ) ) << endmsg;
} else {
lh.set( phist, hid->mutex );
delete hist.release();
}
}
}
return lh;
}
template <typename T>
LockedHandle<T> THistSvc::getShared_i( const std::string& name ) const {
GlobalDirectoryRestore restore( m_svcMut );
const THistID* hid = nullptr;
size_t i = findHistID( name, hid );
LockedHandle<T> hist( nullptr, nullptr );
if ( i == 1 ) {
if ( !hid->shared ) {
error() << "getSharedHist: found Hist with id \"" << name << "\", but it's not marked as shared" << endmsg;
return hist;
}
T* h1 = dynamic_cast<T*>( hid->obj );
hist = LockedHandle<T>( h1, hid->mutex );
if ( msgLevel( MSG::DEBUG ) ) {
debug() << "getSharedHist: found THistID: " << *hid << endmsg;
}
} else if ( i == 0 ) {
error() << "no histograms matching id \"" << name << "\" found" << endmsg;
} else {
info() << "multiple matches for id \"" << name << "\" found [" << i << "], probably from different streams"
<< endmsg;
}
return hist;
}
#endif // GAUDISVC_THISTSVC_ICC