Forked from
atlas / athena
121783 commits behind the upstream repository.
-
Will Leight authored
MuonRecoValidationTool was retrieving the MuonTruthSummaryTool whether or not it was running on MC, using the default values it returns when running on data. This less-than-ideal behavior is no longer feasible now that the MuonTruthSummaryTool declares in its initialization that it will be retrieving some truth containers. Therefore I added a configurable isMC flag to MuonRecoValidationTool, which now retrieves the MuonTruthSummaryTool only if it is running on MC and disables it otherwise. I also added isMC protection to all cases in the code where the MuonTruthSummaryTool is called, and updated the configuration to set the flag correctly. Probably the MuonRecoValidationTool should be reworked a bit so that it handles this in a more logical fashion, but this is outside the scope of this MR. Former-commit-id: c43313bd
Will Leight authoredMuonRecoValidationTool was retrieving the MuonTruthSummaryTool whether or not it was running on MC, using the default values it returns when running on data. This less-than-ideal behavior is no longer feasible now that the MuonTruthSummaryTool declares in its initialization that it will be retrieving some truth containers. Therefore I added a configurable isMC flag to MuonRecoValidationTool, which now retrieves the MuonTruthSummaryTool only if it is running on MC and disables it otherwise. I also added isMC protection to all cases in the code where the MuonTruthSummaryTool is called, and updated the configuration to set the flag correctly. Probably the MuonRecoValidationTool should be reworked a bit so that it handles this in a more logical fashion, but this is outside the scope of this MR. Former-commit-id: c43313bd
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
MuonTruthSummaryTool.cxx 13.36 KiB
/*
Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
*/
#include "MuonTruthSummaryTool.h"
#include "MuonSegment/MuonSegment.h"
#include "TrkTrack/Track.h"
#include "TrkMeasurementBase/MeasurementBase.h"
#include "HepMC/GenParticle.h"
#include <iostream>
#include "TTree.h"
#include "GaudiKernel/ITHistSvc.h"
namespace Muon {
/** Constructor **/
MuonTruthSummaryTool::MuonTruthSummaryTool(const std::string& t, const std::string& n, const IInterface* p) :
AthAlgTool(t,n,p),
m_idHelper("Muon::MuonIdHelperTool/MuonIdHelperTool"),
m_helper("Muon::MuonEDMHelperTool/MuonEDMHelperTool"),
m_printer("Muon::MuonEDMPrinterTool/MuonEDMPrinterTool"),
m_incidentSvc("IncidentSvc",n),
m_wasInit(false),
m_truthHitsTotal(0),
m_tree(0),
m_thistSvc(0),
m_writeTree(false),
m_level(0)
{
declareInterface<IMuonTruthSummaryTool>(this);
declareProperty("WriteNtuple", m_writeTree);
declareProperty("NtupleTreeName", m_treeName = "MuonTruthSummaryTree");
declareProperty("HistStream", m_histStream = "Summary");
declareProperty("SelectedPdgId", m_selectedPdgId = 13, "Should be positive as absolute value is used" );
declareProperty("UseNSW", m_useNSW=false);
}
StatusCode MuonTruthSummaryTool::initialize()
{
ATH_MSG_VERBOSE("Initializing ...");
if (m_idHelper.retrieve().isFailure()) {
msg(MSG::FATAL) << "Could not get " << m_idHelper << endmsg;
return StatusCode::FAILURE;
}
if (m_printer.retrieve().isFailure()) {
msg(MSG::FATAL) << "Could not get " << m_printer << endmsg;
return StatusCode::FAILURE;
}
if (m_helper.retrieve().isFailure()) {
msg(MSG::FATAL) << "Could not get " << m_helper << endmsg;
return StatusCode::FAILURE;
}
// call handle in case of EndEvent
if( m_incidentSvc.retrieve().isFailure() ) {
ATH_MSG_ERROR("Could not get " << m_incidentSvc);
return StatusCode::FAILURE;
}
m_incidentSvc->addListener( this, std::string("EndEvent"));
if (m_writeTree){
if(service("THistSvc", m_thistSvc).isFailure()) {
ATH_MSG_FATAL("Unable to retrieve THistSvc");
return StatusCode::FAILURE;
}
m_tree = new TTree(m_treeName.c_str(), "Ntuple of MuonTruthSummary");
static unsigned int numLevels=3;// Hardcoding to 3 levels for the moment.
std::string treePathAndName ("/");
treePathAndName+=m_histStream;
treePathAndName+="/";
treePathAndName+=m_treeName;
if(m_thistSvc->regTree(treePathAndName.c_str(), m_tree).isFailure()) {
ATH_MSG_FATAL("Unable to register " << m_tree->GetName());
return StatusCode::FAILURE;
} else {
ATH_MSG_VERBOSE("Registered tree as "<<treePathAndName);
}
initChamberVariables(numLevels);
}
if( m_selectedPdgId < 0 ) {
ATH_MSG_WARNING("SelectedPdgId should be positive, taking the absolute value");
m_selectedPdgId = abs(m_selectedPdgId);
}
if(m_useNSW){
m_TruthNames.emplace_back("MM_TruthMap");
m_TruthNames.emplace_back("STGC_TruthMap");
}
else m_TruthNames.emplace_back("CSC_TruthMap");
ATH_CHECK(m_TruthNames.initialize());
return StatusCode::SUCCESS;
}
StatusCode MuonTruthSummaryTool::finalize() {
ATH_MSG_INFO("Of "<<m_truthHitsTotal<<" truth hits in total...");
for (auto level : m_lossesPerLevel){
ATH_MSG_INFO(level.second<<" \ttruth hits lost at level :"<<level.first);
}
return StatusCode::SUCCESS;
}
void MuonTruthSummaryTool::clear() {
m_wasInit = false;
m_truthHits.clear();
m_truthDataPerLevel.clear();
}
void MuonTruthSummaryTool::init() const {
getTruth();
m_wasInit = true;
ATH_MSG_DEBUG(" Total collected muon truth hits " << m_truthHits.size() );
}
void MuonTruthSummaryTool::getTruth() const {
for(SG::ReadHandle<PRD_MultiTruthCollection>& col : m_TruthNames.makeHandles()){
if(!col.isValid() || !col.isPresent()) continue;
ATH_MSG_DEBUG( "PRD_MultiTruthCollection " << col.key() << " found");
PRD_MultiTruthCollection::const_iterator it = col->begin();
PRD_MultiTruthCollection::const_iterator it_end = col->end();
for( ;it!=it_end;++it ){
const HepMcParticleLink& link = it->second;
if( link.cptr() &&
(abs(link.cptr()->pdg_id()) == m_selectedPdgId || abs(link.cptr()->pdg_id()) == 13 ) ) {
m_truthHits[it->first] = link.cptr()->barcode();
m_pdgIdLookupFromBarcode[link.cptr()->barcode()]=link.cptr()->pdg_id();
}
}
}
}
int MuonTruthSummaryTool::getPdgId( int barcode ) const {
if( !m_wasInit) init();
auto pos = m_pdgIdLookupFromBarcode.find(barcode);
if( pos == m_pdgIdLookupFromBarcode.end() ) return 0;
return pos->second;
}
int MuonTruthSummaryTool::getBarcode( const Identifier& id ) const {
if( !m_wasInit) init();
auto pos = m_truthHits.find(id);
if( pos == m_truthHits.end() ) return -1;
return pos->second;
}
void MuonTruthSummaryTool::add( const Identifier& id, int level ) {
if( !m_wasInit) init();
if( m_truthHits.count(id) ) m_truthDataPerLevel[level].insert(id);
}
void MuonTruthSummaryTool::add( const MuonSegment& seg, int level ) {
add(seg.containedMeasurements(),level);
}
void MuonTruthSummaryTool::add( const Trk::Track& track, int level ) {
const DataVector<const Trk::MeasurementBase>* meas = track.measurementsOnTrack();
if( meas ) add(meas->stdcont(),level);
}
void MuonTruthSummaryTool::add( const std::vector<const Trk::MeasurementBase*>& measurements, int level ) {
for( std::vector<const Trk::MeasurementBase*>::const_iterator it = measurements.begin();it!=measurements.end();++it ){
Identifier id = m_helper->getIdentifier(**it);
if( id.is_valid() && m_idHelper->isMuon(id) ) add(id,level);
}
}
std::string MuonTruthSummaryTool::printSummary() {
if( m_truthHits.empty() ) return "Event without truth hits";
if( m_truthDataPerLevel.empty() ) return "No hits added";
ATH_MSG_DEBUG( "Have " << m_truthHits.size() << " truth hits and "<< m_truthDataPerLevel.size()<<" levels filled." );
std::set<Identifier> truthHits;
for( auto it = m_truthHits.begin();it!=m_truthHits.end();++it ) truthHits.insert(it->first);
m_truthHitsTotal+=truthHits.size();
std::ostringstream sout;
sout << " Summarizing: truth hits " << truthHits.size() << " levels filled " << m_truthDataPerLevel.size()<<std::endl;
std::map<int,std::set<Identifier> >::const_iterator it = m_truthDataPerLevel.begin();
std::map<int,std::set<Identifier> >::const_iterator it_end = m_truthDataPerLevel.end();
for( ;it!=it_end;++it ){
m_level=it->first-1;
if (m_writeTree) clearChamberVariables( m_level );
sout << " Comparing truth to level " << m_level << std::endl << printSummary( truthHits, it->second );
m_lossesPerLevel[it->first]+=(truthHits.size()-it->second.size());
}
if (m_writeTree) {
std::cout<<"About to try to fill try tree "<<m_tree->GetName()<<std::endl;
std::cout<<"m_numChambers size = "<<m_numChambers.size()<<", val [0] = "<<m_numChambers[0]<<std::endl;
m_tree->Fill();
}
return sout.str();
}
std::string MuonTruthSummaryTool::printSummary( const std::set<Identifier>& truth, const std::set<Identifier>& found ) {
std::ostringstream sout;
if( truth.size() != found.size() ){
sout << " Some truth hits not found: truth " << truth.size() << " found " << found.size() << std::endl;
std::vector<Identifier> result(truth.size()-found.size());
std::vector<Identifier>::iterator pos = std::set_difference(truth.begin(),truth.end(),found.begin(),found.end(),result.begin());
result.resize(pos-result.begin());
int nmm = 0;
std::map<Identifier, unsigned int> chambers; // Store counts per chamber Id
unsigned int hitNum=0;
for( std::vector<Identifier>::iterator it=result.begin();it!=result.end();++it ){
sout << hitNum++<<":\t" << m_idHelper->toString(*it) << std::endl;
if(m_idHelper->isMM(*it) ) ++nmm;
chambers[m_idHelper->chamberId(*it)]++;
}
if( nmm > 4 ) sout << " possible missing MM segment : " << nmm << std::endl;
sout << std::endl<<"++++ Chamber summaries:"<<std::endl;
for (auto chamber : chambers ){
sout << "Chamber "<<m_idHelper->toStringChamber(chamber.first)<<"\t has "<<chamber.second<<" missing truth hits"<<std::endl;
if (m_writeTree) fillChamberVariables(chamber.first, chamber.second);
}
}else{
sout << " All hits found: truth " << truth.size() << " found " << found.size() << std::endl;
}
return sout.str();
}
void MuonTruthSummaryTool::initChamberVariables(const unsigned int levels){
if (!m_tree) {
ATH_MSG_WARNING("Trying to write ntuple, but tree is zero. Setting WriteNtuple to False");
m_writeTree=false;
}
m_numChambers.resize(levels);
m_numMissedHits.resize(levels);
m_missedHitTechnologyIndex.resize(levels);
m_missedHitStationPhi.resize(levels);
m_missedHitStationSector.resize(levels);
m_missedHitStationEta.resize(levels);
// m_missedHitR.resize(levels);
// m_missedHitZ.resize(levels);
// m_missedHitStationName.resize(levels);
m_missedHitStationNameIndex.resize(levels);
for (unsigned int level =0 ; level<levels ; level++) {
m_numChambers[level] = 0;
m_numMissedHits[level] = new std::vector<uint8_t>;
m_missedHitTechnologyIndex[level] = new std::vector<uint8_t>;
m_missedHitStationPhi[level] = new std::vector<int>;
m_missedHitStationSector[level] = new std::vector<int>;
m_missedHitStationEta[level] = new std::vector<int>;
// m_missedHitR[level] = new std::vector<float>;
// m_missedHitZ[level] = new std::vector<float>;
// m_missedHitStationName[level] = new std::vector<std::string>;
m_missedHitStationNameIndex[level] = new std::vector<int>;
std::string name = "numMissedHitsForLevel"+std::to_string(level);
std::string leafThing = name + std::string("/i");
// std::cout<<"m_numChambers["<<level<<"] = "<<m_numChambers[level]<<std::endl;
m_tree->Branch(name.c_str(), &m_numChambers[level], leafThing.c_str());
name = "numMissedHitsForLevel"+std::to_string(level);
m_tree->Branch(name.c_str(), &m_numMissedHits[level]);
name = "TechnologyIndexForLevel"+std::to_string(level);
m_tree->Branch(name.c_str(), &m_missedHitTechnologyIndex[level]);
name = "MissedHitStationPhiForLevel"+std::to_string(level);
m_tree->Branch(name.c_str(), &m_missedHitStationPhi[level]);
name = "MissedHitStationSectorForLevel"+std::to_string(level);
m_tree->Branch(name.c_str(), &m_missedHitStationSector[level]);
name = "MissedHitStationEtaForLevel"+std::to_string(level);
m_tree->Branch(name.c_str(), &(m_missedHitStationEta[level]));
// name = "MissedHitRForLevel"+std::to_string(level);
// m_tree->Branch(name.c_str(), &(m_missedHitR[level]));
// name = "MissedHitZForLevel"+std::to_string(level);
// m_tree->Branch(name.c_str(), &(m_missedHitZ[level]));
// name = "MissedHitStationName for level "+std::to_string(level);
// m_tree->Branch(name.c_str(), &m_missedHitStationName[level]);
name = "MissedHitStationNameIndexForLevel"+std::to_string(level);
m_tree->Branch(name.c_str(), &m_missedHitStationNameIndex[level]);
}
}
void MuonTruthSummaryTool::clearChamberVariables( const unsigned int level){
ATH_MSG_DEBUG("clearChamberVariables: Level = "<<level+1);
m_numChambers[level] = 0;
m_numMissedHits[level]->clear();
m_missedHitTechnologyIndex[level]->clear();
m_missedHitStationPhi[level]->clear();
m_missedHitStationSector[level]->clear();
m_missedHitStationEta[level]->clear();
// m_missedHitR[level]->clear();
// m_missedHitZ[level]->clear();
// m_missedHitStationName[level]->clear();
m_missedHitStationNameIndex[level]->clear();
}
void MuonTruthSummaryTool::fillChamberVariables(const Identifier& chamberId, const unsigned int numMissedHits){
ATH_MSG_DEBUG("fillChamberVariables: Level = "<<(m_level+1)<<" \t chamber = "<<m_idHelper->toStringChamber(chamberId)<<" numMissedHits="<<numMissedHits );
m_numChambers[m_level]++;
m_numMissedHits[m_level]->push_back(numMissedHits);
m_missedHitTechnologyIndex[m_level]->push_back( m_idHelper->technologyIndex(chamberId) );
m_missedHitStationPhi[m_level] ->push_back( m_idHelper->stationPhi(chamberId) );
m_missedHitStationSector[m_level] ->push_back( m_idHelper->sector(chamberId) );
m_missedHitStationEta[m_level] ->push_back( m_idHelper->stationEta(chamberId) );
// m_missedHitR[m_level] ->push_back( m_idHelper->stationEta(chamberId) ); // Need to do R/Z elsewhere...
// m_missedHitZ[m_level] ->push_back( m_idHelper->stationEta(chamberId) );
// // m_missedHitStationName[m_level] ->push_back( m_idHelper->chamberNameString(chamberId) );
m_missedHitStationNameIndex[m_level] ->push_back( m_idHelper->stationIndex(chamberId) );
}
void MuonTruthSummaryTool::handle(const Incident& inc) {
// Only clear cache for EndEvent incident
if (inc.type() == "EndEvent") {
ATH_MSG_DEBUG( printSummary() );
clear();
}
}
}