diff --git a/CaloFuture/CaloFutureMoniDst/CMakeLists.txt b/CaloFuture/CaloFutureMoniDst/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..b36c5af5a4f92372a9ca1169f3f54d73309fcfd4 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/CMakeLists.txt @@ -0,0 +1,33 @@ +################################################################################ +# Package: CaloFutureMoniDst +################################################################################ +gaudi_subdir(CaloFutureMoniDst v5r21) + +gaudi_depends_on_subdirs(Associators/MCAssociators + CaloFuture/CaloFutureInterfaces + Calo/CaloKernel + CaloFuture/CaloFutureUtils + Event/DAQEvent + Event/L0Event + Event/LinkerEvent + Event/PhysEvent + Event/TrackEvent + Kernel/Relations + Tr/TrackInterfaces) + +find_package(AIDA) +find_package(Boost) +find_package(GSL) +find_package(ROOT) + +include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS}) + +gaudi_add_module(CaloFutureMoniDst + src/*.cpp + INCLUDE_DIRS ROOT AIDA Boost GSL AIDA Associators/MCAssociators Calo/CaloKernel Tr/TrackInterfaces + LINK_LIBRARIES ROOT Boost GSL AIDA CaloFutureUtils DAQEventLib L0Event LinkerEvent PhysEvent TrackEvent RelationsLib) + +gaudi_install_python_modules() + +gaudi_env(SET CALOFUTUREMONIDSTOPTS \${CALOFUTUREMONIDSTROOT}/options) + diff --git a/CaloFuture/CaloFutureMoniDst/doc/release.notes b/CaloFuture/CaloFutureMoniDst/doc/release.notes new file mode 100755 index 0000000000000000000000000000000000000000..ba432fa316dbe9013ff978322b09f7614a4999b3 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/doc/release.notes @@ -0,0 +1,470 @@ +! ----------------------------------------------------------------------------- +! Package : CaloFuture/CaloFutureMoniDst +! Responsible : Olivier Deschamps odescham@in2p3.fr +! Purpose : CaloFuture monitoring of Dst tape +! ----------------------------------------------------------------------------- + +! 2016-08-16 - Olivier Deschamps + - implement counter() switch based on FutureCounterLevel tool + +! 2016-06-11 - Deschamps Olivier for J.-F. Marchand + - ResolvedPi0Monitor : add 2d histo for pi0 mass versus cell index + +!========================= CaloFutureMoniDst v5r21 2016-01-28 ========================= +! 2015-12-08 - Marco Cattaneo + - Fix untested StatusCodes exposed by previous fix + +! 2015-12-06 - Gerhard Raven + - replace explicit boost::assign::list_of with implicit std::initializer_list + +!========================= CaloFutureMoniDst v5r20 2015-11-23 ========================= +! 2015-11-06 - O. Deschamps + -fix clang warnings + +! 2015-10-22 - O. Deschamps + -initialize base-class (CaloFutureMoniAlg) everywhere + +!========================= CaloFutureMoniDst v5r19 2015-10-13 ========================= +! 2015-08-30 - Gerhard Raven + - remove DECLARE_ALGORITHM_FACTORY( CaloFutureMoniAlg ) and DECLARE_ALGORITHM_FACTORY( CaloFutureNtpBase ) + as these are not 'concrete' algorithms, but base classes from which one first must inherit + and implement execute before they are useful. + +! 2015-08-12 - Gerhard Raven + - remove #include of obsolete Gaudi headers + +!========================= CaloFutureMoniDst v5r18 2015-05-26 ========================= +! 2015-05-12 - Olivier Deschamps + - fix property naming in CaloFutureHypoMonitor + - update CaloFuturePi0Ntp & CaloFutureElectronNtp + +!========================= CaloFutureMoniDst v5r17 2014-05-13 ======================= +! 2014-05-06 - Marco Cattaneo + - CaloFutureMoniAlg.cpp: use setHistoTopDir in initialize() instead of + setProperty("HistoTopDir") in constructor. Removes need for debug() in + constructor + - CaloFutureEFlowAlg.cpp: remove unnecessary debug() in constructor + - Above two changes fix unprotected debug() warnings + +!========================= CaloFutureMoniDst v5r16 2014-03-18 ======================= +! 2014-03-06 - Olivier Deschamps + - python/Configuration.py : propagate OutputLevel value to calo sequences only when the property is explicity set + +!========================= CaloFutureMoniDst v5r15 2013-10-24 ======================= +! 2013-10-09 - Olivier Deschamps + - python/CaloFutureDAQ/Monitors.py & Configuration.py : possibility to set-up a configuration without active Spd/Prs (NoSpdPrs = <False> flag) + - src/ : protect monitoring algorithms against the upgrade configuration with no Spd/Prs + +!========================= CaloFutureMoniDst v5r14 2013-07-18 ======================= +! 2013-06-12 - Marco Cattaneo + - Fix gcc48 warning + - Change a global variable to local, fixes UNINIT_CTOR warning + - Remove empty finalize methods + +!========================= CaloFutureMoniDst v5r13 2012-11-28 ======================= +! 2012-11-22 - Marco Clemencic + - Added CMake configuration file. + - Modified requirements to simplify auto conversion to CMake. + +! 2012-10-08 - Marco Cattaneo + - In Configuration.py, remove setting of MeasureTime=true in sequencers, + should not be the default, and should in any case use TimingAuditor. + - Fix UNINIT_CTOR defects + - Fix trivial icc remarks + +! 2012-10-08 - Olivier Deschamps + - Fix coverity problems + +!========================= CaloFutureMoniDst v5r12 2012-06-25 ======================= +! 2012-05-13 - Olivier Deschamps + - fix CaloFutureAlignmentNtp + - update L0CaloFutureScale + +!========================= CaloFutureMoniDst v5r11 2012-05-02 ======================= +! 2012-04-17 - Olivier Deschamps + - new algorithm : L0CaloFutureScale to compare CaloFutureCluster/CaloFutureHypo/L0Cluster transverse + energy + +!========================= CaloFutureMoniDst v5r10 2012-04-13 ======================= +! 2012-04-05 - Olivier Deschamps + - Add eta->gg monitoring (re-use resolvedPi0 algorithm) + - SpdMonitor : set splitArea=true as the default for CaloFuture2Dview histos + +!========================= CaloFutureMoniDst v5r9 2011-09-06 ======================== +! 2011-09-03 - Olivier Deschamps + - fix CaloFutureAlignment.cpp + +!========================= CaloFutureMoniDst v5r8 2011-07-27 ======================== +! 2011-07-22 - Marco Cattaneo + - Create debug() messages only when output level requires it, + also using UNLIKELY macro + - Replace all endreq by endmsg + +!========================= CaloFutureMoniDst v5r7 2011-02-25 ======================== +! 2011-02-07 - Olivier Deschamps + - update tupling algorithms + +!========================= CaloFutureMoniDst v5r6 2011-01-17 ======================== +! 2010-10-07 - Olivier Deschamps + - New base class : CaloFutureNtpBase for tupling algorithms + - CaloFutureAlignmentNtp now inherits from CaloFutureNtpBase + @TODO : make other XXNtp algorithm to inherit from the base class + +!========================= CaloFutureMoniDst v5r5 2010-10-28 ======================== +! 2010-10-07 - Olivier Deschamps + - Fix windows warning + +! 2010-10-01 - Rob Lambert + - Fix windows warning, converting double to int + +! 2010-09-30 - Marco Cattaneo + - Undo part of previous fix, which was causing a relations table to not be + loaded, causing the algorithm to throw ane exception. This was masking the + finalization crash, that is still there.... + +! 2010-09-30 - Olivier Deschamps + - CaloFuturePhotonChecker : fix finalization crash + +! 2010-09-30 - Olivier Deschamps + - Improve CaloFuturePi0Ntp & CaloFutureElectronNtp + - add new ntp algorithm : CaloFutureAlignmentNtp + + +!========================== CaloFutureMoniDst v5r4 2010-09-29 ======================= +! 2010-09-27 - Marco Cattaneo + - Fix uninitialised member variables in CaloFuturePhotonChecker + +! 2010-09-01 - Olivier Deschamps + - fix compilation warning on windows + - improve CaloFutureHypoNtp + +! 2010-08-31 - Olivier Deschamps + - fix compilation warning on slc4 + +! 2010-08-27 - Olivier Deschamps + - new algorithm : CaloFutureHypoNtp + - CaloFutureHypoMonitor : new monitoring histogram Nhypo/Nclusters + +!========================== CaloFutureMoniDst v5r3 2010-06-22 ======================= +! 2010-06-05 - Rob Lambert + - Fixes for mistake in yesterday's commit + +! 2010-06-04 - Rob Lambert + - Fixes for windows warnings savannah 15808 + +!========================== CaloFutureMoniDst v5r2 2010-05-24 ======================= + +! 2010-05-24 - Rob Lambert + - fix for typo in CaloFuturePi0Ntp + + +! 2010-05-17 - Olivier Deschamps + - python/Monitor.py : activate missing monitoring histo for ResolvedPi0 monitoring + +!========================== CaloFutureMoniDst v5r1 2010-04-26 ======================= +! 2010-04-12 - Dmitry GOLUBKOV + - doc/release.notes : corrected the place of the second comment from 2010-04-12 + - Monitor.py : check if properties were already set before setting them + - cmt/requirements: version incremented to v5r1 + +!========================== CaloFutureMoniDst v5r0 2010-04-12 ======================= +! 2010-04-12 - Dmitry GOLUBKOV + - CaloFutureEMuPIDMon.cpp: fixed an unchecked StatusCode in the finalize() method + +! 2010-04-09 - Rob Lambert + - Fixed windows warnings in CaloFutureEMuPIDMon.cpp and CaloFuturePi0Checker.cpp + +! 2010-04-02 - Dmitry Golubkov + - CaloFutureEMuPIDMon.cpp: fixed an SLC5 warning: type qualifiers ignored on function return type + +! 2010-03-31 - Dmitry Golubkov + - following Vanya's suggestion remove completely CaloFutureEMuMonitor, CaloFutureEMuChecker + +! 2010-03-31 - Olivier Deschamps + - fix typo in CaloFuturePi0Monitor.cpp + +! 2010-03-29 - Dmitry Golubkov + - CaloFutureMoniDstConf : introduced Histograms slot and passed it to pidsMoni(), + test the value of Histograms in CaloFutureMoniDstConf.checkConfiguration() + - Monitor.py : add 'CaloFutureEMuMonitor/CaloFuturePIDMon' to the monitoring sequence only + if Histograms in ['OfflineFull', 'Expert'] + +! 2010-03-26 - Dmitry GOLUBKOV + - CaloFutureEMuPIDMon.{h,cpp}: a new simplified PID monitoring algorithm + - Monitor.py: added CaloFutureEMuPIDMon{Uncut,Soft,Hard} to the monitoring sequence + - CaloFuturePIDsMonitor.opts: added CaloFutureEMuPIDMon to the CaloFuturePIDsMon sequence (?) + - cmt/requirements: version increment to v4r6 + +!========================== CaloFutureMoniDst v4r5 2010-03-19 ======================= +! 2010-03-22 - Rob Lambert + - Fixed some windows warnings savannah 64668 + +! 2010-03-08 - Olivier Deschamps + - adapt CaloFuturePhotonChecker to change in CaloFuturePIDs + + @TODO : review checkers (use CaloFutureMCTools ...) + +! 2010-03-08 - Olivier Deschamps + - make use of CaloFutureAlgUtils to define context-dependent TES inputs + - add control counters + - CaloFutureMoniDstConf + - add missing ProtoElectronMonitor + - delegate the TES I/O to CaloFutureAlgUtils + + + - Usage : + + from Configurables import CaloFutureProcessor + from Configurables import CaloFutureMoniDst + CaloFutureProcessor(Context = 'Repro' , Sequence = recSeq ) + CaloFutureMoniDst(Context = 'Repro' , Sequence = moniSeq ) + + -> provides consistent CaloFutureReco + Monitoring sequences for 'Repro' context + + + +!========================== CaloFutureMoniDst v4r4 2010-02-15 ======================= + +! 2010-02-11 - Marco Cattaneo + - Replace dependency on DaVinciMCKernel with MCAssociators, to follow changes + in LHCB v29r1 + +! 2010-01-30 - Dmitry Golubkov + - CaloFutureEMuMonitor: add more histograms, crude windows based on rp6 of Dec 2009 data + - CaloFutureEMuChecker: move include Kernel/Particle2MCLinker.h from CaloFutureEMuMonitor.h + +! 2010-02-04 : Olivier Deschamps + - CaloFuturePi0Monitor : fix bad initialization of base class + - CaloFutureMoniAlg : init m_detData for non specific calo detector algo (default Ecal is assumed) + +! 2010-01-28 : Olivier Deschamps + - SpdMonitor : speed up processing - inherits from CaloFuture2Dview (Albert Puig) + - CalOEFlowAlg : code update from Aurélien. + Warning : new CaloFutureEFlow require MCEvent dependency (obtained through DaVinciMCKernel so far) + -> to do : split the MC 'checker' part of the code + + +!========================== CaloFutureMoniDst v4r3 2010-01-21 ======================= +! 2010-01-13 - Marco Cattaneo + - Follow Gaudi fix #61116: GaudiCommon::Exception now returns void + +! 2009-12-11 - Olivier Deschamps + - CaloFutureProtoElectronMonitor : make use of proto->info(PrsE) instead of CaloFutureHypo2CaloFuture tool. + +! 2009-12-11 - Olivier Deschamps + - CaloFutureMoniAlg : remove verbose line + - new algorithm CaloFutureProtoElectronMonitor + - CaloFuturePi0Monitor : add pi0 mass peak with Y-selection of clusters. + + +!========================== CaloFutureMoniDst v4r2 2009-12-11 ======================= +! 2009-12-01 - Olivier Deschamps + - CaloFutureMoniAlg : protection against non booked histograms in hfillX methods + +! 2009-11-30 - Olivier Deschamps + - CaloFutureMoniAlg : add saturation bin(s) by default for 1D histograms + + +!========================== CaloFutureMoniDst v4r1 2009-10-20 ======================= +! 2009-10-16 - Olivier Deschamps for Aurelien Martens + - Update in CaloFutureEFlowAlg + +! 2009-10-06 - Marco Cattaneo + - Add link to LHCb-INT-2009-022 note in CaloFutureEMuMonitor.h doxygen header + +! 2009-10-01 - Vanya BELYAEV + - CaloFutureMoniAlg.h : + minor fix for the recent modification in CaloFutureCellCode functions + +! 2009-09-14 - Olivier Deschamps + - CaloFuturePi0Monitor : + - selection of non-converted photons + - isolation criteria + - Add background subtracted histo + +! 2009-09-08 - Olivier Deschamps + - Add background histo in resolved pi0 monitor + - Fix problem with HashMap<const string, IHistogram*> removing const ! + +!========================== CaloFutureMoniDst v4r0 2009-09-07 ======================= +! 2009-09-07 - Dmitry GOLUBKOV + - CaloFutureEMuMonitor, CaloFutureEMuChecker: add proper calls to the base-class finalize() + - CaloFuturePIDsChecker.cpp : fix division by zero in divide() + +! 2009-09-01 - Vanya BELYAEV + - fix warnings in configurables + +! 2009-08-31 - Olivier Deschamps + - fix bug in CaloFutureMoniAlg (SplitAreas/m_split property/member already exists in inherited CaloFuture2DView) + +! 2009-08-11 - Vanya BELYAEV + + - futher polishing of configurables + + +! 2009-08-05 - Vanya BELYAEV + + - add proepr configurable + version incremen to v4r0 + +! 2009-07-30 - Dmitry GOLUBKOV + - CaloFutureEMuMonitor.cpp add protection when no charged ProtoParticle + - cmt/requirements version incremented to v3r10 + +!========================== CaloFutureMoniDst v3r9 2009-07-28 ======================= +! 2009-07-28 - Marco Cattaneo + - Remove obsolete file CaloFutureMoniDst_dll.cpp + - Remove not needed includes + - Clean up dependencies in requirements + +! 2009-07-24 - Chris Jones + - change std::map< std::string, XXX * > to + GaudiUtils::HashMap< const std::string, XXX * > for faster lookups. + +!========================== CaloFutureMoniDst v3r8 2009-06-17 ======================= +! 2009-06-05 - Olivier Deschamps + - change _snprintf() to std::string + +!========================== CaloFutureMoniDst v3r7 2009-06-03 ======================= +! 2009-06-03 - Marco Cattaneo + - Fix for windows, do not use fabs with int argument, use abs + - Use _snprintf, not snprintf on windows + +! 2009-05-22 - Marco Cattaneo + - Fix invalid matrix indices in computation of "shape" in CaloFuturePhotonChecker.cpp + +!========================== CaloFutureMoniDst v3r6 2009-05-08 ======================= +! 2009-05-05 - Olivier Deschamps for Aurelien Martens + - CaloFutureEFlowAlg.cpp : add protection + - CaloFutureEFlowAlg.opts : change default setting + +! 2009-04-24 - Marco Cattaneo + - Fix compilation warning for gcc43 + - Replace endreq by endmsg (obsolescent in Gaudi v21) + +! 2009-04-21 - Olivier Deschamps for Dmitry Goloubkov + - CaloFutureEMuMonitor/Checker.{cpp,h} : produce histogram (+analysis) of CaloFuturePID + +! 2009-04-20 - Olivier Deschamps for Aurelien Martens + - CaloFutureEFlowAlg.{cpp,h,opts} : produce histogram for 'Energy-Flow' calibration + method (Aurelien Martens) + +!========================== CaloFutureMoniDst v3r5 2009-03-10 ======================= +! 2009-03-06 - Olivier Deschamps + - set CaloFutureDQ.opt histo selection as default in CaloFutureMonitor.opts for Brunel + - new options : CaloFutureFullMonitoring.opts (to be added to produce the whole histo set) + +! 2009-02-20 - Olivier Deschamps + - Clean monitoring algorithms + - add protection against missing data inputs here and there + - new options : CaloFutureDQ.opts : selection of relevant monitoring histo for Data Quality stuff + - CaloFutureMoniAlg : new property 'splitAreas' allow to produce histo per area (all cpp adapted) + +!========================== CaloFutureMoniDst v3r4 2009-02-20 ======================= +! 2009-01-20 - Marco Cattaneo + - Migrate to LHCb::ParticlePropertySvc + +!========================== CaloFutureMoniDst v3r3 2008-11-21 ======================= +! 2008-11-06 - Marco Cattaneo + - Fix for gcc 4.3 + +! 2008-10-17 - Olivier Deschamps + - fix memory leak + +!========================== CaloFutureMoniDst v3r2 2008-10-02 ======================= +! 2008-09-23 - Marco Cattaneo + - Fix compilation warning + +! 2008-09-21 - Olivier Deschamps + - review histogram production & prepare XXXMonitor for real data. + - cleanup algorithm and options + +! 2008-09-18 - Marco Cattaneo + - Add #units directive to CaloFutureMonitor.opts, needed by Brunel pythonisation + +!========================== CaloFutureMoniDst v3r1 2008-07-02 ======================= +! 2008-06-26 - Juan PALACIOS + - cmt/requirements + . Increase version to v3r1 + - src/CaloFuturePhotonChecker.cpp + . Change all Gaudi::XYZLine and Gaudi::Line for Gaudi::Math::XYZLine and + Gaudi::Math::XYZLine respectively (adapting to Kernel/LHCbMath v3) + +!========================== CaloFutureMoniDst v3r0p2 2008-04-23 =================== +! 2008-04-23 - Marco Cattaneo + - Remove whitespace in options, needed for Python options parser + +!========================== CaloFutureMoniDst v3r0p1 2007-12-03 =================== +! 2007-12-03 - Marco Cattaneo + - Fix a compiler warning + +! 2007-11-22 - Olivier Deschamps + - fix in CaloFuturePhotonChecker.cpp + +!========================== CaloFutureMoniDst v3r0 2007-10-08 =================== +! 2007-09-24 - Olivier Deschamps + - fix against the PatricleID constructor from int made explicit + - fix SpdMonitor.cpp (Albert Puig) + - remove dependency on CaloFutureAssociator in requirements + - add dependency on DaVinciMCKernel in requirements + +! 2007-08-24 - Olivier Deschamps + - fix unchecked StatusCodes + +! 2007-08-22 - Albert Puig & Olivier Deschamps + - new SpdMonitor algorithm + +! 2007-07-25 - Konstantin Beloous & Olivier Deschamps + - Major release + - package updated for DC06 + - First step toward an online usage of the Monitoring part + - histograms production reviewed and improved + - some algorithm names have changed + - 2 types of algorithms : Monitor's (relying on data only) and Checker's (relying on MC) + - Monitors : CaloFutureDigit, CaloFutureCluster, CaloFutureHypo, ResolvedPi0 & PID's (CaloFutureClusterMatch, CaloFutureHypoMatch) + - driven by option/CaloFutureMonitor.opts + - Checkers : CaloFutureCluster, Photon, ResolvedPi0, CaloFuturePIDs + - driven by option/CaloFutureChecker.opts + +!========================== CaloFutureMoniDst v2r1 2005-12-08 =================== +! 2005-12-08 - Olivier Deschamps + - CaloFuturePIDsMonitor.cpp use Track::History == 'Cnv' Tracks only +!========================== CaloFutureMoniDst v2r0 2005-11-04 =================== +! 2005-11-04 - Olivier Deschamps + - Adapt to new Track Event Model (TrackEvent v1r4) + + modified file : + src/CaloFuturePIDsMonitor.cpp + src/CaloFuturePhotonMonitor.h/cpp + src/CaloFutureHypoMatchMonitor.cpp + src/CaloFutureClusterMatchMonitor.cpp + + - cmt/requirements + version increment to v2r0 + +!======================== CaloFutureMoniDst v1r2 2005-06-02 ========================= +! 2005-06-02 - Marco Cattaneo + - Adapt job options to change in phase name from BrunelMoni to Moni (for + monitoring without MC truth) and Check (for checking with MC truth) + +========================= CaloFutureMoniDst v1r1 2005-05-13 ========================= +! 2005-05-13 - Marco Cattaneo + - Fix ambiguous call to overloaded log10 function, for Windows + +! 2005-05-08 - Vanya BELYAEV + - eliminate all associators + - a lot of minor cosmetic changes + - cmt/requirements + version increment to v1r1 + +========================= CaloFutureMoniDst v1r0 2004-10-27 ========================= +! 2004-10-27 - Vanya BELYAEV + - tiny improvements in algorithms + + +! 2004-10-25 - Vanya BELYAEV + - the new package: the code is imported from CaloFuture/CaloFutureMonitor package + +! ----------------------------------------------------------------------------- +! The END +! ----------------------------------------------------------------------------- diff --git a/CaloFuture/CaloFutureMoniDst/options/Brunel.opts b/CaloFuture/CaloFutureMoniDst/options/Brunel.opts new file mode 100755 index 0000000000000000000000000000000000000000..1088c1db59b9cfc503da8950f1bc71e32bd02181 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/options/Brunel.opts @@ -0,0 +1,2 @@ +#include "$CALOFUTUREMONIDSTOPTS/CaloFutureMonitor.opts" +#include "$CALOFUTUREMONIDSTOPTS/CaloFutureChecker.opts" diff --git a/CaloFuture/CaloFutureMoniDst/options/CaloFuture2L0Mon.opts b/CaloFuture/CaloFutureMoniDst/options/CaloFuture2L0Mon.opts new file mode 100644 index 0000000000000000000000000000000000000000..9bb6affe018cbcc411c658ff7ccce5c591c7ef23 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/options/CaloFuture2L0Mon.opts @@ -0,0 +1,9 @@ +CaloFuture2L0Mon.Members += { + "L0CaloFutureScale/Photon2L0CaloFuture" + ,"L0CaloFutureScale/Electron2L0CaloFuture" + }; + +Photon2L0CaloFuture.EtFilter=200.*MeV; +Electron2L0CaloFuture.EtFilter=200.*MeV; +Photon2L0CaloFuture.SplitAreas=true; +Electron2L0CaloFuture.SplitAreas=true; diff --git a/CaloFuture/CaloFutureMoniDst/options/CaloFutureChecker.opts b/CaloFuture/CaloFutureMoniDst/options/CaloFutureChecker.opts new file mode 100755 index 0000000000000000000000000000000000000000..e64d360412600c87ad0d64d3ece4eb218924539a --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/options/CaloFutureChecker.opts @@ -0,0 +1,23 @@ + + +CheckCALOFUTURESeq.Members += { "GaudiSequencer/CaloFutureRecoChecker" + ,"GaudiSequencer/CaloFuturePIDsChecker" +}; + +CaloFutureRecoChecker.Members += { "CaloFutureClusterChecker" + ,"CaloFuturePi0Checker" +}; + + +CaloFuturePIDsChecker.Members += { "CaloFuturePIDsChecker/PIDeEcalChecker", + "CaloFuturePIDsChecker/PIDePrsChecker" , + "CaloFuturePIDsChecker/PIDeHcalChecker", + "CaloFuturePIDsChecker/PIDeBremChecker", + "CaloFuturePIDsChecker/PIDmEcalChecker", + "CaloFuturePIDsChecker/PIDmHcalChecker", + "CaloFuturePhotonChecker"}; + + +#include "$CALOFUTUREMONIDSTOPTS/CaloFuturePhotonChecker.opts" +#include "$CALOFUTUREMONIDSTOPTS/CaloFuturePIDsChecker.opts" + diff --git a/CaloFuture/CaloFutureMoniDst/options/CaloFutureClusterMonitor.opts b/CaloFuture/CaloFutureMoniDst/options/CaloFutureClusterMonitor.opts new file mode 100755 index 0000000000000000000000000000000000000000..19aeace8fc3f656d1439819d83bceccd5915e220 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/options/CaloFutureClusterMonitor.opts @@ -0,0 +1,2 @@ +CaloFutureClusterMon.Members += { "CaloFutureClusterMonitor/EcalClusterMon"}; +//EcalClusterMon.Input = "Rec/Calo/EcalClusters"; diff --git a/CaloFuture/CaloFutureMoniDst/options/CaloFutureDQ.opts b/CaloFuture/CaloFutureMoniDst/options/CaloFutureDQ.opts new file mode 100644 index 0000000000000000000000000000000000000000..2dd49866c4926aa62f42dca4ba3fdf32e40ac0e5 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/options/CaloFutureDQ.opts @@ -0,0 +1,15 @@ +EcalDigitMon.histoList = { "1" , "2" , "3" , "6" , "7" }; +HcalDigitMon.histoList = { "1" , "2" , "3" , "6" , "7" }; +PrsDigitMon.histoList = { "1" , "2" , "3" , "6" , "7" }; +SpdDigitMon.histoList = { "1" , "2" , "3" , "6" }; +EcalClusterMon.histoList = { "1" , "2" , "3" , "4" , "7" , "8" , "9" }; +ElectronMon.histoList = { "1" , "2" , "3" , "7" , "8" , "9" , "10" , "11" ,"14"}; +PhotonMon.histoList = { "1" , "2" , "3" , "7" , "8" , "9" , "10" , "11" ,"14"}; +SplitPhotonMon.histoList = { "1" , "2" , "3" , "7" , "8" , "9" , "10" , "11" }; +MergedPi0Mon.histoList = { "1" , "2" , "3" , "4" , "7" , "8" , "9" , "14" }; +ResolvedPi0Mon.histoList = { "1" , "2" , "3" , "4" , "5" , "6" , "7" , "8"}; +EtaMon.histoList = { "1" , "2" , "3" , "4" , "5" , "6" , "7" }; +EcalProtoPMon.histoList = { "All" }; +SpdMon.histoList = { "All" }; +Photon2L0CaloFuture.histoList = { "0" , "1" , "2" , "3" }; +Electron2L0CaloFuture.histoList = { "0" , "1" , "2" , "3" }; diff --git a/CaloFuture/CaloFutureMoniDst/options/CaloFutureDigitMonitor.opts b/CaloFuture/CaloFutureMoniDst/options/CaloFutureDigitMonitor.opts new file mode 100755 index 0000000000000000000000000000000000000000..8af84ebb5c00537428ec6fcb4dd794eab22d63ab --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/options/CaloFutureDigitMonitor.opts @@ -0,0 +1,14 @@ +CaloFutureDigitMon.Members += { "CaloFutureDigitMonitor/EcalDigitMon", + "CaloFutureDigitMonitor/HcalDigitMon", + "CaloFutureDigitMonitor/PrsDigitMon", + "CaloFutureDigitMonitor/SpdDigitMon" +}; + +//EcalDigitMon.EnergyFilter = 500.*MeV; +//HcalDigitMon.EnergyFilter = 500.*MeV; +//PrsDigitMon.EnergyFilter = 50.*MeV; + + +//EcalDigitMon.SplitAreas = true; +//EcalDigitMon.SplitAreas = true; +//EcalDigitMon.OutputLevel = 2; diff --git a/CaloFuture/CaloFutureMoniDst/options/CaloFutureFullMonitoring.opts b/CaloFuture/CaloFutureMoniDst/options/CaloFutureFullMonitoring.opts new file mode 100644 index 0000000000000000000000000000000000000000..d7bb9b62d5622a7ab46c69d5e5ba1577b021c583 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/options/CaloFutureFullMonitoring.opts @@ -0,0 +1,13 @@ +// Define the monitoring sequence +#include "$CALOFUTUREMONIDSTOPTS/CaloFutureMonitor.opts" +// force the complete histo set production +EcalDigitMon.histoList += { "All" }; +HcalDigitMon.histoList += { "All" }; +PrsDigitMon.histoList += { "All" }; +SpdDigitMon.histoList += { "All" }; +EcalClusterMon.histoList += { "All" }; +ElectronMon.histoList += { "All" }; +PhotonMon.histoList += { "All" }; +SplitPhotonMon.histoList += { "All" }; +MergedPi0Mon.histoList += { "All" }; +ResolvedPi0Mon.histoList += { "All" }; diff --git a/CaloFuture/CaloFutureMoniDst/options/CaloFutureHypoMonitor.opts b/CaloFuture/CaloFutureMoniDst/options/CaloFutureHypoMonitor.opts new file mode 100755 index 0000000000000000000000000000000000000000..ccc9d81bc807a701e2bbaf5dd305e328cd4ab127 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/options/CaloFutureHypoMonitor.opts @@ -0,0 +1,23 @@ +CaloFutureHypoMon.Members += { "CaloFutureHypoMonitor/ElectronMon" + ,"CaloFutureHypoMonitor/PhotonMon" + ,"CaloFutureHypoMonitor/SplitPhotonMon" + ,"CaloFutureHypoMonitor/MergedPi0Mon" + ,"CaloFuturePi0Monitor/ResolvedPi0Mon" + ,"CaloFuturePi0Monitor/EtaMon" +}; + +ResolvedPi0Mon.PhotonPtFilter = 200.*MeV; +ResolvedPi0Mon.IsolationFilter = 3; // temp +ResolvedPi0Mon.HistoMassMax = 250.; // temp + +// Eta->gg +EtaMon.PhotonMaxPtFilter=1000.*MeV; +EtaMon.HistoMassMin=400.*MeV; +EtaMon.HistoMassMax=700.*MeV; + + +// Moning of different Hypotheses +//ElectronMon.Input = "Rec/Calo/Electrons"; +//PhotonMon.Input = "Rec/Calo/Photons"; +//MergedPi0Mon.Input = "Rec/Calo/MergedPi0s"; +//SplitPhotonMon.Input = "Rec/Calo/SplitPhotons"; diff --git a/CaloFuture/CaloFutureMoniDst/options/CaloFutureMonitor.opts b/CaloFuture/CaloFutureMoniDst/options/CaloFutureMonitor.opts new file mode 100755 index 0000000000000000000000000000000000000000..1b043606f76c950c4264fd1825efecb9c498d0b4 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/options/CaloFutureMonitor.opts @@ -0,0 +1,27 @@ +// define the monitoring histo production sequence +MoniCALOFUTURESeq.Members += { "GaudiSequencer/CaloFutureDigitMon" + ,"GaudiSequencer/CaloFutureEFlowAlg" + ,"GaudiSequencer/CaloFutureClusterMon" + ,"GaudiSequencer/CaloFutureHypoMon" + ,"GaudiSequencer/CaloFutureProtoPMon" + ,"GaudiSequencer/CaloFuturePIDsMon" + ,"GaudiSequencer/CaloFuture2L0Mon" + ,"SpdMonitor/SpdMon" +}; + +#include "$CALOFUTUREMONIDSTOPTS/CaloFutureDigitMonitor.opts" +#include "$CALOFUTUREMONIDSTOPTS/CaloFutureClusterMonitor.opts" +#include "$CALOFUTUREMONIDSTOPTS/CaloFutureHypoMonitor.opts" +#include "$CALOFUTUREMONIDSTOPTS/CaloFutureProtoPMonitor.opts" +#include "$CALOFUTUREMONIDSTOPTS/SpdMonitor.opts" +#include "$CALOFUTUREMONIDSTOPTS/CaloFuturePIDsMonitor.opts" +#include "$CALOFUTUREMONIDSTOPTS/CaloFuture2L0Mon.opts" + +#include "$CALOFUTUREMONIDSTOPTS/EcalEFlowAlg.opts" +#include "$CALOFUTUREMONIDSTOPTS/HcalEFlowAlg.opts" +#include "$CALOFUTUREMONIDSTOPTS/PrsEFlowAlg.opts" + + +// define the subset of useful monitoring histos for DQ +#include "$CALOFUTUREMONIDSTOPTS/CaloFutureDQ.opts" + diff --git a/CaloFuture/CaloFutureMoniDst/options/CaloFuturePIDsChecker.opts b/CaloFuture/CaloFutureMoniDst/options/CaloFuturePIDsChecker.opts new file mode 100755 index 0000000000000000000000000000000000000000..4495723f4b93466d5ce9b3e52db61796e99e4634 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/options/CaloFuturePIDsChecker.opts @@ -0,0 +1,51 @@ +// Produce plot of efficiency versus tan(p/Normalisation) plot for track with : +// - type = TrackType +// - Acceptance == TrackAcceptance +// - DLL<input> > Cut +// - Associated MC-type = Particle, 0 (Ghost) and non-Particle + + +PIDeEcalChecker.Particle = 11 ; +PIDeEcalChecker.Input = "Rec/Calo/EcalPIDe" ; +PIDeEcalChecker.Normalization = 50.0 * GeV ; +PIDeEcalChecker.Cut = 0.0 ; +PIDeEcalChecker.TrackType = "Long" ; +PIDeEcalChecker.TrackAcceptance= "Rec/Calo/InAccEcal" ; + + +PIDePrsChecker.Particle = 11 ; +PIDePrsChecker.Input = "Rec/Calo/PrsPIDe" ; +PIDePrsChecker.Normalization = 50.0 * GeV ; +PIDePrsChecker.Cut = 0.0 ; +PIDePrsChecker.TrackType = "Long" ; +PIDePrsChecker.TrackAcceptance= "Rec/Calo/InAccPrs" ; + + +PIDeBremChecker.Particle = 11 ; +PIDeBremChecker.Input = "Rec/Calo/BremPIDe" ; +PIDeBremChecker.Normalization = 50.0 * GeV ; +PIDeBremChecker.Cut = 0. ; +PIDeBremChecker.TrackType = "Long" ; +PIDeBremChecker.TrackAcceptance= "Rec/Calo/InAccBrem" ; + +PIDeHcalChecker.Particle = 11 ; +PIDeHcalChecker.Input = "Rec/Calo/HcalPIDe" ; +PIDeHcalChecker.Normalization = 50.0 * GeV ; +PIDeHcalChecker.Cut = 0. ; +PIDeHcalChecker.TrackType = "Long" ; +PIDeHcalChecker.TrackAcceptance= "Rec/Calo/InAccHcal" ; + + +PIDmEcalChecker.Particle = 13 ; +PIDmEcalChecker.Input = "Rec/Calo/EcalPIDmu" ; +PIDmEcalChecker.Normalization = 25.0 * GeV ; +PIDmEcalChecker.Cut = 0. ; +PIDmEcalChecker.TrackType = "Long" ; +PIDmEcalChecker.TrackAcceptance= "Rec/Calo/InAccEcal" ; + +PIDmHcalChecker.Particle = 13 ; +PIDmHcalChecker.Input = "Rec/Calo/HcalPIDmu" ; +PIDmHcalChecker.Normalization = 25.0 * GeV ; +PIDmHcalChecker.Cut = 0. ; +PIDmHcalChecker.TrackType = "Long" ; +PIDmHcalChecker.TrackAcceptance= "Rec/Calo/InAccHcal" ; diff --git a/CaloFuture/CaloFutureMoniDst/options/CaloFuturePIDsMonitor.opts b/CaloFuture/CaloFutureMoniDst/options/CaloFuturePIDsMonitor.opts new file mode 100755 index 0000000000000000000000000000000000000000..9eb592b374d0c9c645ae26b307f174ff43a2f80d --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/options/CaloFuturePIDsMonitor.opts @@ -0,0 +1,12 @@ +CaloFuturePIDsMon.Members += { "CaloFutureClusterMatchMonitor/PhotonMatchMon" + ,"CaloFutureHypoMatchMonitor/ElectronMatchMon" + ,"CaloFutureHypoMatchMonitor/BremMatchMon" + ,"CaloFutureEMuPIDMon/CaloFutureEMuPIDMon"}; +// Monitoring of matching relation tables +//PhotonMatchMon.Input = "Rec/Calo/ClusterMatch"; +//PhotonMatchMon.Inputs = { "Rec/Calo/EcalClusters" }; +//ElectronMatchMon.Input = "Rec/Calo/ElectronMatch"; +//ElectronMatchMon.Inputs = { "Rec/Calo/Electrons" }; +//BremMatchMon.Input = "Rec/Calo/BremMatch" ; +//BremMatchMon.Inputs = { "Rec/Calo/Photons" } ; + diff --git a/CaloFuture/CaloFutureMoniDst/options/CaloFuturePhotonChecker.opts b/CaloFuture/CaloFutureMoniDst/options/CaloFuturePhotonChecker.opts new file mode 100755 index 0000000000000000000000000000000000000000..18b25408c7ee8fa658e98d249c5395df5d1910da --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/options/CaloFuturePhotonChecker.opts @@ -0,0 +1,20 @@ +CaloFuturePhotonChecker.Pdf = true ; + + +// Histogram Binning : +CaloFuturePhotonChecker.EPrsBin= + { + // Nbin , Xmin, Xmax + 50, 0., 200. // EPrs + }; +CaloFuturePhotonChecker.Chi2Bin= + { + // Nbin , Xmin, Xmax + 26, 0., 104. // Chi2(Tr) + }; +CaloFuturePhotonChecker.SeedBin= + { + // Nbin , Xmin, Xmax + 50, 0., 1. // Shower Shape + }; + diff --git a/CaloFuture/CaloFutureMoniDst/options/CaloFutureProtoPMonitor.opts b/CaloFuture/CaloFutureMoniDst/options/CaloFutureProtoPMonitor.opts new file mode 100644 index 0000000000000000000000000000000000000000..ded152e95b5e96c14d13ccabd18927d580ac1074 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/options/CaloFutureProtoPMonitor.opts @@ -0,0 +1,2 @@ +CaloFutureProtoPMon.Members += { "CaloFutureProtoElectronMonitor/EcalProtoElectronMon"}; + diff --git a/CaloFuture/CaloFutureMoniDst/options/EcalEFlowAlg.opts b/CaloFuture/CaloFutureMoniDst/options/EcalEFlowAlg.opts new file mode 100644 index 0000000000000000000000000000000000000000..0138a4a0e1a5b167bb03459978dc56223ba5f85b --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/options/EcalEFlowAlg.opts @@ -0,0 +1,20 @@ +CaloFutureEFlowAlg.Members += { "CaloFutureEFlowAlg/EcalEFlowAlgo"}; + +// define the subset of useful monitoring histos for EF +EcalEFlowAlgo.histoList = { "All" }; + +//define parameters +EcalEFlowAlgo.SplitAreas = false; +EcalEFlowAlgo.EtFilterMax = -999.; +EcalEFlowAlgo.EnergyFilterMax = -999; +EcalEFlowAlgo.ADCFilterMax = -999; +EcalEFlowAlgo.ADCFilterMin = -999; +EcalEFlowAlgo.EtFilterMin = -999.; +EcalEFlowAlgo.EnergyFilterMin = -999; +EcalEFlowAlgo.Simulation = false; +EcalEFlowAlgo.IgnoreTAE = true; +EcalEFlowAlgo.IgnoreNonBeamCrossing = true; +EcalEFlowAlgo.IgnoreNonPhysicsTrigger = false; +EcalEFlowAlgo.OneDimension = true; + +// EcalEFlowAlgo.Profile = true; diff --git a/CaloFuture/CaloFutureMoniDst/options/HcalEFlowAlg.opts b/CaloFuture/CaloFutureMoniDst/options/HcalEFlowAlg.opts new file mode 100644 index 0000000000000000000000000000000000000000..77d95f57a76270a2c40087dce29c4a2b146fc7d1 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/options/HcalEFlowAlg.opts @@ -0,0 +1,20 @@ +CaloFutureEFlowAlg.Members += { "CaloFutureEFlowAlg/HcalEFlowAlgo"}; + +// define the subset of useful monitoring histos for EF +HcalEFlowAlgo.histoList = { "All" }; + +//define parameters +HcalEFlowAlgo.SplitAreas = false; +HcalEFlowAlgo.EtFilterMax = -999.; +HcalEFlowAlgo.EnergyFilterMax = -999; +HcalEFlowAlgo.ADCFilterMax = -999; +HcalEFlowAlgo.ADCFilterMin = -999; +HcalEFlowAlgo.EtFilterMin = -999.; +HcalEFlowAlgo.EnergyFilterMin = -999; +HcalEFlowAlgo.Simulation = false; +HcalEFlowAlgo.IgnoreTAE = true; +HcalEFlowAlgo.IgnoreNonBeamCrossing = true; +HcalEFlowAlgo.IgnoreNonPhysicsTrigger = false; +HcalEFlowAlgo.OneDimension = true; + +// HcalEFlowAlgo.Profile = true; diff --git a/CaloFuture/CaloFutureMoniDst/options/PrsEFlowAlg.opts b/CaloFuture/CaloFutureMoniDst/options/PrsEFlowAlg.opts new file mode 100644 index 0000000000000000000000000000000000000000..47bd723de584e9f0badacaeffd330046ca9ae816 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/options/PrsEFlowAlg.opts @@ -0,0 +1,20 @@ +CaloFutureEFlowAlg.Members += { "CaloFutureEFlowAlg/PrsEFlowAlgo"}; + +// define the subset of useful monitoring histos for EF +PrsEFlowAlgo.histoList = { "All" }; + +//define parameters +PrsEFlowAlgo.SplitAreas = false; +PrsEFlowAlgo.EtFilterMax = -999.; +PrsEFlowAlgo.EnergyFilterMax = -999; +PrsEFlowAlgo.ADCFilterMax = -999; +PrsEFlowAlgo.ADCFilterMin = -999; +PrsEFlowAlgo.EtFilterMin = -999.; +PrsEFlowAlgo.EnergyFilterMin = -999; +PrsEFlowAlgo.Simulation = false; +PrsEFlowAlgo.IgnoreTAE = true; +PrsEFlowAlgo.IgnoreNonBeamCrossing = true; +PrsEFlowAlgo.IgnoreNonPhysicsTrigger = false; +PrsEFlowAlgo.OneDimension = true; + +// PrsEFlowAlgo.Profile = true; diff --git a/CaloFuture/CaloFutureMoniDst/options/SpdMonitor.opts b/CaloFuture/CaloFutureMoniDst/options/SpdMonitor.opts new file mode 100755 index 0000000000000000000000000000000000000000..6c1fde0a5abd82d8d27411462d362f215bcf919b --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/options/SpdMonitor.opts @@ -0,0 +1,2 @@ +//SpdMon.HistogramFlag = true; // default +//SpdMon.EcalThreshold = 700 ; // default diff --git a/CaloFuture/CaloFutureMoniDst/python/CaloFutureMoniDst/Configuration.py b/CaloFuture/CaloFutureMoniDst/python/CaloFutureMoniDst/Configuration.py new file mode 100755 index 0000000000000000000000000000000000000000..2849e921afd07d11ad9df21b5cd2ca0f8fe44116 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/python/CaloFutureMoniDst/Configuration.py @@ -0,0 +1,219 @@ +#!/usr/bin/env gaudirun.py +# ============================================================================= +## Configurable for CaloFuturerimeter Monitoring +# @author Vanya BELYAEV Ivan.Belyaev@nikhe.nl +# @date 2008-07-17 +# ============================================================================= +""" +Configurable for CaloFuturerimeter Monitoring +""" +# ============================================================================= +__author__ = "Vanya BELYAEV Ivan.Belyaev@nikhef.nl" +__version__ = "CVS tag $Name: $, version $Revision: 1.4 $" +# ============================================================================= +__all__ = ( + 'CaloFutureMoniDstConf', + ) +# ============================================================================= +from Gaudi.Configuration import * + +from LHCbKernel.Configuration import * + +from CaloKernel.ConfUtils import ( addAlgs , + printOnDemand , + prntCmp , + hltContext , + setTheProperty ) + +from CaloFutureMoniDst.Monitor import ( digitsMoni , + eflowMoni , + clustersMoni , + hyposMoni , + pi0sMoni , + pidsMoni , + protosMoni , + pidCheck , + recoCheck + ) + +# ============================================================================= +## @class CaloFutureMoniDstConf +# Configurable for CaloFuturerimeter Reconstruction +# @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl +# @date 2008-07-17 +class CaloFutureMoniDstConf(LHCbConfigurableUser): + """ + Class/Configurable to define the calorimeter monitoring + + """ + ## define the slots + __slots__ = { + "Context" : "Offline" # The context within which to run + , "MeasureTime" : False # Measure the time for sequencers + , "OutputLevel" : INFO # The global output level + , 'MonitorSequence' : None # The monitor's sequence + , 'CheckerSequence' : None # The checker's sequence + , 'MoniList' : [ 'Digits' , + 'EFlow' , + 'Clusters' , + 'Hypos' , + 'Pi0s' , + 'Protos' , + 'PIDs' + ] + , 'CheckList' : ['Reco','PIDs'] + , 'Histograms' : 'OfflineFull' # Default Histograms level + , 'NoSpdPrs' : False # Upgrade configuration without Prs/Spd + , 'Verbose' : False + } + + ## Default Histogram set + __known_histograms__ = [ "None", "Online", "OfflineExpress", "OfflineFull", "Expert" ] + + + ## configure monitoring of Digits + def digits ( self ) : + """ + Configure monitoring of Digits + + """ + cmp = digitsMoni ( self.getProp('Context') , self.getProp('NoSpdPrs')) + ## + return cmp + + + ## configure E-Flow monitoring + def eflow ( self ) : + """ + Configure E-Flow monitoring + """ + cmp = eflowMoni ( self.getProp('Context') ) + + return cmp + + ## configure Clusters monitoring + def clusters ( self ) : + """ + Configure Clusters monitoring + """ + cmp = clustersMoni ( self.getProp('Context') ) + + return cmp + + ## configure Hypos monitoring + def hypos ( self ) : + """ + Configure Hypos monitoring + """ + cmp = hyposMoni ( self.getProp('Context') ) + + return cmp + + ## configure pi0 monitoring + def pi0s ( self ) : + """ + Configure Pi0s monitoring + """ + cmp = pi0sMoni ( self.getProp('Context') ) + + return cmp + + ## configure pi0 monitoring + def protos ( self ) : + """ + Configure Protos monitoring + """ + cmp = protosMoni ( self.getProp('Context') ) + + return cmp + + + ## configure PID monitoring + def pids ( self ) : + """ + Configure PIDs monitoring + """ + cmp = pidsMoni ( self.getProp('Context'), self.getProp("Histograms") ) + + return cmp + + + #--- configure the checkers + def pidChecker ( self ) : + cmp = pidCheck( self.getProp('Context'), self.getProp("NoSpdPrs") ) + return cmp + def recoChecker ( self ) : + cmp = recoCheck( self.getProp('Context')) + return cmp + + + + ## Check the configuration + def checkConfiguration ( self ) : + """ + Check the configuration + """ + + if self.getProp( 'Histograms' ) not in self.__known_histograms__: + raise RuntimeError("Unknown Histograms option '%s'" % self.getProp( 'Histograms' )) + + + def printConf(self) : + if self.getProp('NoSpdPrs') : + log.info("CaloFutureMoniDstConf : upgrade configuration without Spd/Prs") + if self.getProp('Verbose') : + log.info( self ) + + + ## CaloFuturerimeter Monitoring Configuration + def applyConf ( self ) : + """ + CaloFuturerimeter Monitor Configuration + """ + log.info ('CaloFutureMoniConf: Apply CaloFuture Monitoring Configuration ') + + self.printConf() + + self.checkConfiguration() + + + #----- MONITORS + monList = self.MoniList + seq = [] + if 'Digits' in monList : addAlgs ( seq , self.digits () ) + if 'EFlow' in monList : addAlgs ( seq , self.eflow () ) + if 'Clusters' in monList : addAlgs ( seq , self.clusters () ) + if 'Hypos' in monList : addAlgs ( seq , self.hypos () ) + if 'Pi0s' in monList : addAlgs ( seq , self.pi0s () ) + if 'Protos' in monList : addAlgs ( seq , self.protos () ) + if 'PIDs' in monList : addAlgs ( seq , self.pids () ) + setTheProperty ( seq , 'Context' , self.getProp('Context') ) + if self.isPropertySet("OutputLevel") : + setTheProperty ( seq , 'OutputLevel' , self.getProp('OutputLevel') ) + setTheProperty ( seq , 'MeasureTime' , self.getProp('MeasureTime') ) + if self.isPropertySet('MonitorSequence') : + moniSeq=self.getProp('MonitorSequence') + addAlgs ( moniSeq , seq ) + log.info ('Configure main CaloFuture Moni MonitorSequence : %s '% moniSeq.name() ) + if self.getProp('Verbose') : + log.info ( prntCmp ( moniSeq ) ) + + + #----- CHECKERS + checkList = self.CheckList + cseq = [] + if 'Reco' in checkList : addAlgs ( cseq , self.recoChecker () ) + if 'PIDs' in checkList : addAlgs ( cseq , self.pidChecker () ) + setTheProperty ( cseq , 'Context' , self.getProp('Context') ) + if self.isPropertySet("OutputLevel") : + setTheProperty ( cseq , 'OutputLevel' , self.getProp('OutputLevel') ) + setTheProperty ( cseq , 'MeasureTime' , self.getProp('MeasureTime') ) + + if self.isPropertySet('CheckerSequence') : + checkSeq= self.getProp('CheckerSequence') + addAlgs ( checkSeq , cseq ) + log.info ('Configure CheckerSequence : %s '% checkSeq.name() ) + if self.getProp('Verbose') : + log.info ( prntCmp ( checkSeq ) ) + + diff --git a/CaloFuture/CaloFutureMoniDst/python/CaloFutureMoniDst/Monitor.py b/CaloFuture/CaloFutureMoniDst/python/CaloFutureMoniDst/Monitor.py new file mode 100755 index 0000000000000000000000000000000000000000..4ebc20ef699539a4b2f5d584aebfdcb0d689e28b --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/python/CaloFutureMoniDst/Monitor.py @@ -0,0 +1,381 @@ +#!/usr/bin/env python +# ============================================================================= +# $Id: Monitor.py,v 1.8 2010/05/20 09:55:38 odescham Exp $ +# ============================================================================= +## The major building blocks of CaloFuturerimeter Monitoring +# @author Vanya BELYAEV Ivan.Belyaev@nikhe.nl +# @date 2008-07-17 +# ============================================================================= +""" +The major building blocks of CaloFuturerimeter Monitoring +""" +# ============================================================================= +__author__ = "Vanya BELYAEV Ivan.Belyaev@nikhef.nl" +__version__ = "CVS tag $Name: $, version $Revision: 1.8 $" +# ============================================================================= +__all__ = ( + 'digitsMoni' , + 'eflowMoni' , + 'clustersMoni' , + 'hyposMoni' , + 'pi0Moni' , + 'pidsMoni' + ) +# ============================================================================= +from Gaudi.Configuration import * + +from Configurables import GaudiSequencer +from CaloKernel.ConfUtils import ( getAlgo , + setTheProperty ) + +from GaudiKernel.SystemOfUnits import ( MeV , GeV ) + + +# ============================================================================= +## prepare digit monitoring +def digitsMoni ( context ,noSpdPrs=False) : + """ + + Prepare digit monitoring + + """ + from Configurables import ( CaloFutureDigitMonitor , + SpdMonitor ) + + alg = getAlgo ( GaudiSequencer , + "CaloFutureDigitsMoni" , + context ) + + alg1 = getAlgo ( CaloFutureDigitMonitor , "EcalDigitMon" , context ) + alg2 = getAlgo ( CaloFutureDigitMonitor , "HcalDigitMon" , context ) + if not alg1.isPropertySet('histoList') : + alg1.histoList = [ "1", "2" , "3" , "6" , "7" ] + if not alg2.isPropertySet('histoList') : + alg2.histoList = [ "1", "2" , "3" , "6" , "7" ] + + alg.Members = [alg1,alg2] + + if not noSpdPrs : + alg3 = getAlgo ( CaloFutureDigitMonitor , "PrsDigitMon" , context ) + alg4 = getAlgo ( CaloFutureDigitMonitor , "SpdDigitMon" , context ) + alg5 = getAlgo ( SpdMonitor , "SpdMon" , context ) + if not alg3.isPropertySet('histoList') : + alg3.histoList = [ "1", "2" , "3" , "6" , "7" ] + if not alg4.isPropertySet('histoList') : + alg4.histoList = [ "1", "2" , "3" , "6" ] + alg.Members += [alg3,alg4,alg5] + setTheProperty ( alg , 'Context' , context ) + return alg + + +# ============================================================================ +## Define Energy flow monitoring +def eflowMoni ( context ) : + """ + Define Energy flow omnitoring + """ + + from Configurables import CaloFutureEFlowAlg + + seq = getAlgo ( GaudiSequencer , + 'CaloFutureEFlowMoni' , + context ) + + alg = getAlgo ( CaloFutureEFlowAlg , + 'EcalEFlowMon' , + context ) + + if not alg.isPropertySet('histoList') : + alg.histoList = [ 'all' ] + if not alg.isPropertySet('SplitAreas') : + alg.SplitAreas = False + if not alg.isPropertySet('OneDimension') : + alg.OneDimension = True + if not alg.isPropertySet('EtFilterMax') : + alg.EtFilterMax = 1 * GeV + if not alg.isPropertySet('EnergyFilterMax') : + alg.EnergyFilterMax = 10 * GeV + + seq.Members = [ alg ] + + setTheProperty ( alg , 'Context' , context ) + + return seq + + +# ============================================================================= +## prepare cluster monitoring +def clustersMoni ( context ) : + """ + Prepare clusters monitoring + + """ + + from Configurables import CaloFutureClusterMonitor + + alg = getAlgo ( GaudiSequencer , + "CaloFutureClustersMoni" , + context ) + + alg1 = getAlgo ( CaloFutureClusterMonitor , + 'EcalClusterMon' , + context ) + + alg2 = getAlgo ( CaloFutureClusterMonitor , + 'EcalSplitClusterMon' , + context ) + + if not alg1.isPropertySet('histoList') : + alg1.histoList = [ "1", "2" , "3" , "4" , "7" , "8" , "9" ] + +# delegate to CaloFutureAlgUtils +# alg1.Input = 'Rec/Calo/EcalClusters' +# alg2.Input = 'Rec/Calo/EcalSplitClusters' + +# alg.Members = [ alg1 , alg2 ] + alg.Members = [ alg1 ] ## do not monitor splitCluster so far + + setTheProperty ( alg , 'Context' , context ) + + return alg + + +# ============================================================================= +## prepare hypo monitoring +def hyposMoni ( context ) : + """ + Prepare hypo monitoring + + """ + + from Configurables import CaloFutureHypoMonitor + + alg = getAlgo ( GaudiSequencer , + "CaloFutureHyposMoni" , + context ) + + alg1 = getAlgo ( CaloFutureHypoMonitor , + 'ElectronMon' , + context ) + alg2 = getAlgo ( CaloFutureHypoMonitor , + 'PhotonMon' , + context ) + alg3 = getAlgo ( CaloFutureHypoMonitor , + 'SplitPhotonMon' , + context ) + alg4 = getAlgo ( CaloFutureHypoMonitor , + 'MergedPi0Mon' , + context ) + + # Delegate I/O to CaloFutureAlgUtils +# alg1.Input = 'Rec/Calo/Electrons' +# alg2.Input = 'Rec/Calo/Photons' +# alg3.Input = 'Rec/Calo/SplitPhotons' +# alg4.Input = 'Rec/Calo/MergedPi0s' + + + if not alg1.isPropertySet('histoList') : + alg1 .histoList = [ "1", "2" , "3" , "7" , "8" , "9" , "10" , "11" ,"14"] + if not alg2.isPropertySet('histoList') : + alg2 .histoList = [ "1", "2" , "3" , "7" , "8" , "9" , "10" , "11" ,"14"] + if not alg3.isPropertySet('histoList') : + alg3 .histoList = [ "1", "2" , "3" , "7" , "8" , "9" , "10" , "11" ] + if not alg4.isPropertySet('histoList') : + alg4 .histoList = [ "1", "2" , "3" , "4" , "7", "8" , "9","14"] + + + alg.Members = [ alg1 , alg2 , alg3 , alg4 ] + + + setTheProperty ( alg , 'Context' , context ) + + return alg + + + + + +# ============================================================================= +## Define pi0 monitoring +def pi0sMoni ( context ) : + """ + Define pi0 monitoring + + """ + + from Configurables import CaloFuturePi0Monitor + + + alg = getAlgo ( GaudiSequencer , + "DiPhotonMoni" , + context ) + + alg1 = getAlgo ( CaloFuturePi0Monitor , + 'ResolvedPi0Mon' , + context ) + + alg2 = getAlgo ( CaloFuturePi0Monitor , + 'EtaMon' , + context ) + + if not alg1.isPropertySet('PhotonPtFilter') : + alg1.PhotonPtFilter = 500.*MeV; + + if not alg1.isPropertySet('histoList') : + alg1.histoList = [ "1", "2" , "3" , "4", "5", "6", "7" ] + + + if not alg2.isPropertySet('PhotonMaxPtFilter') : + alg2.PhotonMaxPtFilter = 1000.*MeV; + + if not alg2.isPropertySet('HistoMassMin') : + alg2.HistoMassMin = 400.*MeV; + + if not alg2.isPropertySet('HistoMassMax') : + alg2.HistoMassMax = 700.*MeV; + + if not alg2.isPropertySet('histoList') : + alg2.histoList = [ "1", "2" , "3" , "4", "5", "6", "7" ] + + alg.Members = [ alg1 , alg2 ] + setTheProperty ( alg , 'Context' , context ) + + return alg + +# ============================================================================= +## Define pi0 monitoring +def protosMoni ( context ) : + """ + Define protoElectron monitoring + + """ + + from Configurables import CaloFutureProtoElectronMonitor + + alg = getAlgo ( CaloFutureProtoElectronMonitor , + 'ProtoElectronMon' , + context ) + + + if not alg.isPropertySet('histoList') : + alg.histoList = [ "All" ] + + setTheProperty ( alg , 'Context' , context ) + + return alg + +# ============================================================================= +## define CaloFuturePIDs monitoring +def pidsMoni ( context, Histograms ) : + """ + Define CaloFuturePIDs monitoring + """ + + from Configurables import ( CaloFutureClusterMatchMonitor , + CaloFutureHypoMatchMonitor , + CaloFutureEMuPIDMon ) + + alg = getAlgo ( GaudiSequencer , + 'CaloFuturePIDsMoni' , + context ) + + alg1 = getAlgo ( CaloFutureClusterMatchMonitor , + 'PhotonMatchMon' , + context ) + alg2 = getAlgo ( CaloFutureHypoMatchMonitor , + 'ElectronMatchMon' , + context ) + alg3 = getAlgo ( CaloFutureHypoMatchMonitor , + 'BremMatchMon' , + context ) + + alg5 = getAlgo ( CaloFutureEMuPIDMon , + 'CaloFutureEMuPIDMonUncut' , + context ) + + alg6 = getAlgo ( CaloFutureEMuPIDMon , + 'CaloFutureEMuPIDMonSoft' , + context ) + + alg7 = getAlgo ( CaloFutureEMuPIDMon , + 'CaloFutureEMuPIDMonHard' , + context ) + + ## Delegate I/O to CaloFutureAlgUtils +# alg1.Input = 'Rec/Calo/ClusterMatch' +# alg1.Inputs = [ 'Rec/Calo/EcalClusters' ] +# alg2.Input = 'Rec/Calo/ElectronMatch' +# alg2.Inputs = [ 'Rec/Calo/Electrons' ] +# alg3.Input = 'Rec/Calo/BremMatch' +# alg3.Inputs = [ 'Rec/Calo/Photons' ] + + if not alg5.isPropertySet( 'uncut') : alg5.uncut = True + if not alg5.isPropertySet('SplitSides') : alg5.SplitSides= True + + if not alg7.isPropertySet( 'pTmin') : alg7.pTmin = 500. + if not alg7.isPropertySet( 'RichDLLe') : alg7.RichDLLe = 4. + if not alg7.isPropertySet( 'maxEHcalE') : alg7.maxEHcalE = 1000. + if not alg7.isPropertySet( 'minPrsE') : alg7.minPrsE =-1.e10 + + alg.Members = [ alg1 , alg2 , alg3 , alg5, alg6, alg7 ] + + + setTheProperty ( alg , 'Context' , context ) + + return alg + +### ------ CHECKING ----- ### +def recoCheck( context ) : + + from Configurables import ( CaloFutureClusterChecker,CaloFuturePi0Checker) + + alg = getAlgo ( GaudiSequencer ,'CaloFutureRecoCheck' , context) + alg1 = getAlgo ( CaloFutureClusterChecker,'CaloFutureClusterChecker',context) + alg2 = getAlgo ( CaloFuturePi0Checker ,'CaloFuturePi0Checker' ,context) + alg.Members=[alg1,alg2] + setTheProperty(alg,'Context',context) + return alg + +def pidCheck( context,noSpdPrs=False ) : + + from Configurables import ( CaloFuturePIDsChecker,CaloFuturePhotonChecker) + + alg = getAlgo ( GaudiSequencer ,'CaloFuturePIDsCheck' , context) + alg1 = pidCheckerConf('PIDeEcalChecker',context,11,"Rec/Calo/EcalPIDe",50.0*GeV,0.0,"Long", "Rec/Calo/InAccEcal" ) + alg2 = pidCheckerConf('PIDeHcalChecker',context,11,"Rec/Calo/HcalPIDe",50.0*GeV,0.0,"Long", "Rec/Calo/InAccHcal" ) + alg3 = pidCheckerConf('PIDeBremChecker',context,11,"Rec/Calo/BremPIDe",50.0*GeV,0.0,"Long", "Rec/Calo/InAccBrem" ) + alg4 = pidCheckerConf('PIDmEcalChecker',context,13,"Rec/Calo/EcalPIDmu",25.0*GeV,0.0,"Long", "Rec/Calo/InAccEcal" ) + alg5 = pidCheckerConf('PIDmHcalChecker',context,13,"Rec/Calo/HcalPIDmu",25.0*GeV,0.0,"Long", "Rec/Calo/InAccHcal" ) + alg.Members=[alg1,alg2,alg3,alg4,alg5] + if not noSpdPrs : + alg6 = pidCheckerConf('PIDePrsChecker',context,11,"Rec/Calo/PrsPIDe",50.0*GeV,0.0,"Long", "Rec/Calo/InAccPrs" ) + alg.Members += [alg6] + # caloPhotonChecker + alg7 = getAlgo ( CaloFuturePhotonChecker,'CaloFuturePhotonChecker',context) + alg7.Pdf=True + alg7.EPrsBin=[50.,0.,200.] + alg7.Chi2Bin=[26.,0.,104.] + alg7.SeedBin=[50.,0.,1.] +# alg.Members += [alg7] + setTheProperty(alg,'Context',context) + return alg + +def pidCheckerConf(name,context,particle,input,norm,cut,type,acc) : + from Configurables import ( CaloFuturePIDsChecker ) + algo = getAlgo ( CaloFuturePIDsChecker,name,context) + algo.Particle = particle + algo.Input = input + algo.Normalization = norm + algo.Cut = cut + algo.TrackType = type + algo.TrackAcceptance = acc + return algo + + +# ============================================================================= +if '__main__' == __name__ : + print __doc__ + +# ============================================================================= +# The END +# ============================================================================= diff --git a/CaloFuture/CaloFutureMoniDst/python/CaloFutureMoniDst/__init__.py b/CaloFuture/CaloFutureMoniDst/python/CaloFutureMoniDst/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..38bf6a22ba0fdf9dd7a55bb9f3a1b91aa66ad284 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.cpp @@ -0,0 +1,585 @@ +// Include files +#include "LHCbMath/LineTypes.h" +#include "LHCbMath/GeomFun.h" +// +#include "CaloFutureAlignmentNtp.h" +#include "CaloFutureMoniUtils.h" + +namespace { + // hack to allow for tools with non-const interfaces... + template <typename IFace> + IFace* fixup(const ToolHandle<IFace>& iface) { return &const_cast<IFace&>(*iface); } +} + +//----------------------------------------------------------------------------- +// Implementation file for class : CaloFutureAlignmentNtp +// +// 2009-12-11 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( CaloFutureAlignmentNtp ) + +namespace { + using Line = Gaudi::Math::Line<Gaudi::XYZPoint,Gaudi::XYZVector>; + + // Return distance between two calo cell. + double distance( const LHCb::CaloCellID& id1, const LHCb::CaloCellID& id2 ){ + return sqrt(pow(double(id1.row()-id2.row()), 2)+pow(double(id1.col() - id2.col()),2)); + } +} + +//============================================================================== +// Standard constructor, initializes variables +//============================================================================== + +CaloFutureAlignmentNtp::CaloFutureAlignmentNtp( const std::string& name, ISvcLocator* pSvcLocator) +: Consumer( name, pSvcLocator, { + KeyValue{ "VertexLoc" , ""}, // Lecacy naming + KeyValue{ "InputODIN" , LHCb::ODINLocation::Default }, + KeyValue{ "InputDigits" , LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation("SPD")}, + KeyValue{ "InputTracks" , LHCb::TrackLocation::Default }, + KeyValue{ "InputContainer", LHCb::ProtoParticleLocation::Charged }, +}) +{ + // Tools + declareProperty( "ExtrapolatorType" , m_extrapolator ); +} + +//============================================================================== +// Initialization +//============================================================================== + +StatusCode CaloFutureAlignmentNtp::initialize() { + StatusCode sc = Consumer::initialize(); + if( sc.isFailure() ) return sc; + if( msgLevel(MSG::DEBUG) ) debug() << "==> Initialize" << endmsg; + if( !m_tracks.empty() )info() << "Will only look at track type(s) = " << m_tracks << endmsg; + else info() << "Will look at any track type" << endmsg; + + // Get & retrieve & configure tools + m_calo = getDet<DeCalorimeter>(DeCalorimeterLocation::Ecal); + if(!( m_counterStat.retrieve() + && m_caloElectron.retrieve() + && m_odin.retrieve() + && m_toSpd.retrieve() + && m_toPrs.retrieve() + && m_extrapolator.retrieve() )){ + error() << "Unable to retrive one of the ToolHandles" << endmsg; + return StatusCode::FAILURE; + } + m_toSpd->setCalos( "Ecal", "Spd"); + m_toPrs->setCalos( "Ecal", "Prs"); + + // set vertex location + if(m_vertLoc == "") + m_vertLoc = m_usePV3D ? LHCb::RecVertexLocation::Velo3D : LHCb::RecVertexLocation::Primary; + + //activate pairing when mass filter is on + if(m_mas.value().first != -99999 || m_mas.value().second != +99999) m_pairing=true; + + // set vertex location + m_vertLoc = inputLocation(); // <-- Careful with the index + if(m_vertLoc == "") + m_vertLoc = m_usePV3D ? LHCb::RecVertexLocation::Velo3D : LHCb::RecVertexLocation::Primary; + updateHandleLocation( *this, "VertexLoc", m_vertLoc ); + + return StatusCode::SUCCESS; +} + +//============================================================================== + +bool CaloFutureAlignmentNtp::acceptTrack(const LHCb::Track* track) const { + if( track == nullptr ) return false; + if( m_tracks.empty() ) return true; + const int ttype = track->type(); + return std::any_of(m_tracks.begin(), m_tracks.end(), [ttype](int itype){return itype==ttype;}); +} + +//============================================================================== + +bool CaloFutureAlignmentNtp::hypoProcessing(const LHCb::CaloHypo* hypo) const { + if( hypo == nullptr ) return false; + LHCb::CaloMomentum momentum( hypo ); + const double e = momentum.e(); + const double et = momentum.pt(); + if( !inRange(m_et , et )) return false; + if( !inRange(m_e , e )) return false; + const double ePrs = fixup(m_toPrs)->energy( *hypo , "Prs" ); + if( !inRange(m_prs, ePrs)) return false; + const double iSpd = fixup(m_toSpd)->multiplicity( *hypo , "Spd"); + if( !inRange(m_spd, iSpd)) return false; + if( m_inArea && !inArea(hypo) ) return false; + return true; +} + +//============================================================================== + +bool CaloFutureAlignmentNtp::inArea(const LHCb::CaloHypo* hypo) const { + const auto hypoR = position3d(hypo); + const auto cell = m_calo->Cell_( hypoR ); + if( !cell ){ + if(m_counterStat->isQuiet()) counter("no cell related to position") += 1; + info() << "No valid cell related to position " << hypoR << endmsg; + return false; + } + return cell->neighbors().size() == 8; +} + + +//============================================================================== +// Main execution +//============================================================================== + +void CaloFutureAlignmentNtp::operator()(const Vertices& verts, const ODIN& odin, + const Digits& digits, const Tracks& tracks, const Protos& protos) const { + + if( msgLevel(MSG::DEBUG) ) debug() << "==> Execute" << endmsg; + if( m_counterStat->isQuiet() ) counter("#PV="+ Gaudi::Utils::toString(verts.size()) + " ["+inputLocation()+"]")+=1; + + // 1. Validate event + m_odin->getTime(); + const auto nSpd = digits.size(); + const auto nTracks = tracks.size(); + const auto nVertices = verts.size(); + if( !inRange( m_nSpd, nSpd )) return; + if( !inRange( m_nTrk, nTracks )) return; + if( !inRange( m_nVtx, nVertices )) return; + if(m_counterStat->isQuiet()) counter("1-selected events") += 1; + + // Loop over protoparticles + for( auto p = protos.begin(); protos.end() != p ; ++p ){ + const auto proto = *p; + + // 2: Validate proto + if( !fixup(m_caloElectron)->set(proto)) continue; + if( m_counterStat->isQuiet()) counter("2-selected protos")+=1; + + // 3: Validate track + const auto track = proto->track(); + if( !acceptTrack( track )) continue; + if( m_counterStat->isQuiet()) counter("3-selected tracks")+=1; + + // 4: Validate hypo + const auto hypo = fixup(m_caloElectron)->electron(); + if( !hypoProcessing(hypo) ) continue; + if( m_counterStat->isQuiet()) counter("4-selected hypos")+=1; + + // 5: Validate electron + const auto eOp = fixup(m_caloElectron)->eOverP(); + if( !inRange( m_eop , eOp)) continue; + if( !inRange( m_dlle , proto->info(LHCb::ProtoParticle::additionalInfo::CombDLLe , 9999.))) continue; + if( !inRange( m_rdlle , proto->info(LHCb::ProtoParticle::additionalInfo::RichDLLe, 9999.))) continue; + if( !inRange( m_bMatch, proto->info(LHCb::ProtoParticle::additionalInfo::CaloBremMatch, 9999.))) continue; + if( !inRange( m_eMatch, proto->info(LHCb::ProtoParticle::additionalInfo::CaloElectronMatch, 9999.))) continue; + if( !inRange( m_cMatch, proto->info(LHCb::ProtoParticle::additionalInfo::CaloTrMatch, 9999.))) continue; + if( m_counterStat->isQuiet()) counter("5-selected electrons")+=1; + + // track extrapolation + const auto cluster = firstCluster(hypo); + const auto id = cluster->seed(); + const auto hypoR = position3d(hypo); + const auto clusR = position3d(cluster); + const auto statR = position3d(fixup(m_caloElectron)->caloState()); + const auto closR = position3d(fixup(m_caloElectron)->closestState()); + const auto cs = momentum(fixup(m_caloElectron)->caloState()); + const auto theta = fixup(m_caloElectron)->caloState().momentum().Theta(); + const auto t = momentum(track); + const auto brem = fixup(m_caloElectron)->bremstrahlung(); + const auto hasBrem = (brem!=nullptr); + if( m_brem && !hasBrem ) continue; // is Brem explicitly requested + + const Gaudi::XYZPoint cellR( m_calo->cellX(id) , m_calo->cellY(id), m_calo->cellZ(id) );// seed position + + // Bremstrahllung + const auto bP = momentum(fixup(m_caloElectron)->bremCaloFutureMomentum()); + const auto bremR = position3d(brem); + const auto bcluster = firstCluster(brem); + const auto bid = bcluster->seed(); + const auto bclusR = position3d(bcluster); + const auto bcellR = Gaudi::XYZPoint( m_calo->cellX(bid) , m_calo->cellY(bid), m_calo->cellZ(bid) );// seed + const auto dist = hasBrem ? distance(bid,id) : -1.; + if(hasBrem){ + // brem-electron separation + if( bid.area()==id.area() && !inRange( m_dist, dist ) ) continue; + if( m_counterStat->isQuiet() ) counter("6-selected electron+Brem")+=1; + } + + // perform electron pairing + double mas = 9999.; + if( m_pairing && m_extrapolator!=0 ){ + for( auto pp = p+1 ; protos.end() != pp ; ++pp ){ + const auto proto2 = *pp; + if( !fixup(m_caloElectron)->set(proto2) ) continue;; + const auto hypo2 = fixup(m_caloElectron)->electron(); + if( hypo == hypo2 ) continue; + if( !hypoProcessing( hypo2 ) ) continue; + const auto eOp2 = fixup(m_caloElectron)->eOverP(); + if( !inRange( m_eop, eOp2 )) continue; + if( !inRange( m_dlle , proto2->info(LHCb::ProtoParticle::additionalInfo::CombDLLe, 0.))) continue; + if( !inRange( m_rdlle, proto2->info(LHCb::ProtoParticle::additionalInfo::RichDLLe, 0.))) continue; + // compute mass + const auto t1 = proto->track(); + const auto t2 = proto2->track(); + if( !acceptTrack(t2) ) continue; + if( t1==nullptr || t2==nullptr ) continue; + if( -1 != t1->charge()*t2->charge()) continue; + LHCb::State st1 = t1->firstState(); + LHCb::State st2 = t2->firstState(); + StatusCode sc = m_extrapolator->propagate(st1, 0.); + if(sc.isFailure()) Warning("Propagation 1 failed").ignore(); + sc = m_extrapolator->propagate(st2, 0.); + if(sc.isFailure()) Warning("Propagation 2 failed").ignore(); + const auto p1 = st1.momentum(); + const auto p2 = st2.momentum(); + double m2 = p1.R()*p2.R(); + m2 -= p1.X()*p2.X(); + m2 -= p1.Y()*p2.Y(); + m2 -= p1.Z()*p2.Z(); + m2 *= 2; + if( m2 > 0 ){ + const double m = sqrt(m2) ; + if( m < mas ) mas = m; + } + } + // add mass + if( !inRange( m_mas, mas ) ) continue; + } + + // Start filling tuple + if(m_tuple){ + auto ntp = nTuple(500, "CaloFutureAlignment", CLID_ColumnWiseTuple); + ntp->column( "Spd" , fixup(m_toSpd)->multiplicity( *hypo, "Spd" )); + ntp->column( "Prs" , fixup(m_toPrs)->energy( *hypo , "Prs" )); + ntp->column( "BremEleDist", dist ); + ntp->column( "TrackMatch" , proto->info(LHCb::ProtoParticle::additionalInfo::CaloTrMatch, 9999.)); + ntp->column( "ElecMatch" , proto->info(LHCb::ProtoParticle::additionalInfo::CaloElectronMatch, 9999.)); + ntp->column( "BremMatch" , proto->info(LHCb::ProtoParticle::additionalInfo::CaloBremMatch, 9999.)); + ntp->column( "TrajectoryL", proto->info(LHCb::ProtoParticle::additionalInfo::CaloTrajectoryL, 9999.)); + ntp->column( "VeloCharge" , proto->info(LHCb::ProtoParticle::additionalInfo::VeloCharge, -1.)); + ntp->column( "DLLe" , proto->info(LHCb::ProtoParticle::additionalInfo::CombDLLe, 0.)); + ntp->column( "RichDLLe" , proto->info(LHCb::ProtoParticle::additionalInfo::RichDLLe, 0.)); + // hypo info + ntp->column("EoP" , eOp ); + ntp->column("hypoE" , LHCb::CaloMomentum(hypo).e()); + ntp->column("hypoR" , hypoR ); + // track info + ntp->column("Charge" , track->charge()); + ntp->column("TrackP" , t); + ntp->column("TrackR" , statR); + ntp->column("ClosestR" , closR); + ntp->column("caloState" , cs ); + ntp->column("caloStateErrX" , sqrt( fixup(m_caloElectron)->caloState().covariance()(0,0))); + ntp->column("caloStateErrY" , sqrt( fixup(m_caloElectron)->caloState().covariance()(1,1))); + ntp->column("caloStateErrTX", sqrt( fixup(m_caloElectron)->caloState().covariance()(2,2))); + ntp->column("caloStateErrTY", sqrt( fixup(m_caloElectron)->caloState().covariance()(3,3))); + ntp->column("incidence",theta); + // cluster info + ntp->column("id" , id.index()); + ntp->column("ClusterE", cluster->e()); + ntp->column("ClusterR", clusR); + ntp->column("SeedR" , cellR); + // brem info + ntp->column("BremId" , bid.index()); + ntp->column("BremP" , bP); + ntp->column("BremR" , bremR); + ntp->column("BremClusterR", bclusR); + ntp->column("BremSeedR" , bcellR); + + double bStX=0; + double bStY=0; + double bStTX=0; + double bStTY=0; + double bStCX=0; + double bStCY=0; + + if( hasBrem ){ + auto bState = (LHCb::State*) track->stateAt(LHCb::State::Location::BegRich1); + if( bState == nullptr ){ + bState = track->states()[0]; + debug() << track->states(); + Warning("BegRich1 state does not exists - used first state", StatusCode::SUCCESS).ignore(); + } + bStX = sqrt( bState->covariance()(0,0) ); + bStY = sqrt( bState->covariance()(1,1) ); + bStTX = sqrt( bState->covariance()(2,2) ); + bStTY = sqrt( bState->covariance()(3,3) ) ; + const auto dz = bremR.Z()-bState->z(); + bStCX = bState->covariance()(0,0) + bState->covariance()(2,2) * dz * dz + bState->covariance()(0,2) * 2.*dz; + bStCY = bState->covariance()(1,1) + bState->covariance()(3,3) * dz * dz + bState->covariance()(1,3) * 2.*dz; + bStCX = (bStCX > 0) ? sqrt( bStCX) : 0; + bStCY = (bStCY > 0) ? sqrt( bStCY) : 0; + } + ntp->column( "bStateErrX" , bStX); + ntp->column( "bStateErrY" , bStY); + ntp->column( "bStateErrTX", bStTX); + ntp->column( "bStateErrTY", bStTY); + ntp->column( "bCaloStateX", bStCX); + ntp->column( "bCaloStateY", bStCY); + + // odin info + ntp->column("run" , odin.runNumber()); + ntp->column("event" , (double) odin.eventNumber() ); + ntp->column("triggertype", odin.triggerType()); + ntp->column("nSpd" , nSpd ); + ntp->column("nTracks" , nTracks ); + ntp->column("nVertices" , nVertices ); + if(m_pairing) ntp->column("MinMee",mas); + ntp->write(); + if(m_counterStat->isQuiet()) counter("7-Events in ntuple")+=1; + } + + // Histogramming + if( !m_histo && !m_profil ) return; + + std::string prof =""; + + if(m_counterStat->isQuiet()) counter("8-Events in histos")+=1; + + const std::string area = id.areaName() ; + const std::string side = (id.col() < 32) ? "C" : "A"; + const std::string level = (id.row() < 32) ? "Bottom" : "Top"; + const std::string barea = bid.areaName() ; + const std::string bside = (bid.col() < 32) ? "C" : "A"; + const std::string blevel = (bid.row() < 32) ? "Bottom" : "Top"; + + const std::string charge = (track->charge() > 0 ) ? "electron" : "positron"; + std::vector<std::string> q{ "all", charge }; + + std::vector<std::string> bsplit{ + "all/", + barea+"/all/", + barea+"/"+charge+"/all/", + barea+"/"+bside+"/all/", + barea+"/"+bside+"/"+charge+"/all/", + barea+"/"+bside+"/"+ blevel +"/all/", + barea+"/"+bside+"/"+ blevel +"/"+charge+"/all/", + barea+"/"+blevel+"/all/", + barea+"/"+blevel+"/"+charge+"/all/", + barea+"/"+blevel+"/"+ bside +"/all/", + barea+"/"+blevel+"/"+ bside +"/"+charge+"/all/", + }; + + std::vector<std::string> split{ + "all/", + area+"/all/", + area+"/"+charge+"/all/", + area+"/"+side+"/all/", + area+"/"+side+"/"+charge+"/all/", + area+"/"+side+"/"+ level +"/all/", + area+"/"+side+"/"+ level +"/"+charge+"/all/", + area+"/"+level+"/all/", + area+"/"+level+"/"+charge+"/all/", + area+"/"+level+"/"+ side +"/all/", + area+"/"+level+"/"+ side +"/"+charge+"/all/", + }; + + // ------ brem aligment (DeltaXX versus ThetaYY) + const double thMin = -0.30; + const double thMax = +0.30; + const double bthX = t.X()/t.Z(); + const double bthY = t.Y()/t.Z(); + const double step = (thMax-thMin)/m_thBin; + if( hasBrem ){ + const double bdceX = (bcellR.X() - bthX*bcellR.Z()); // relative to cell + const double bdceY = (bcellR.Y() - bthY*bcellR.Z()); + const double bdbX = (bremR.X() - bthX*bremR.Z()); // relative to hypo + const double bdbY = (bremR.Y() - bthY*bremR.Z()); + const double bdclX = (bclusR.X() - bthX*bclusR.Z()); // relative to cluster + const double bdclY = (bclusR.Y() - bthY*bclusR.Z()); + + // extrapolate at Z = ShowerMax plane !! + Gaudi::XYZPoint origin(0,0,0); + Gaudi::XYZVector vector(bthX,bthY,1.); + const Line line( origin ,vector ); + const auto plane = m_calo->plane(CaloPlane::ShowerMax); + const auto point = intersection(line,plane); + const double bdpX = (bremR.X() - bthX*point.Z()); + const double bdpY = (bremR.Y() - bthY*point.Z()); + + const std::string bbinX = "bin"+Gaudi::Utils::toString( int((bthX-thMin)/step) ); + const std::string bbinY = "bin"+Gaudi::Utils::toString( int((bthY-thMin)/step) ); + std::vector<std::string> bhat{ "", bbinX, bbinY }; + + plot1D(eOp,"eOp control (all)", 0.5, 2.,100); + for( const auto label1: q ){ + const std::string base = "BremAlign/Delta/" + label1 + "/"; + if(m_histo){ + for( const auto label2: bhat ){ + plot1D( bdceX, label1+"Cell/"+label2+"/dX" , "dX : Cell-Brem(CellZ)" , m_min, m_max, m_bin ); + plot1D( bdceY, label1+"Cell/"+label2+"/dY" , "dY : Cell-Brem(CellZ)" , m_min, m_max, m_bin ); + plot1D( bdclX, label1+"Cluster/"+label2+"/dX", "dX : Cluster-Brem(ClusterZ)", m_min, m_max, m_bin ); + plot1D( bdclY, label1+"Cluster/"+label2+"/dY", "dY : Cluster-Brem(ClusterZ)", m_min, m_max, m_bin ); + plot1D( bdbX , label1+"Hypo/"+label2+"/dX" , "dX : Hypo-Brem(HypoZ)" , m_min, m_max, m_bin ); + plot1D( bdbY , label1+"Hypo/"+label2+"/dY" , "dY : Hypo-Brem(HypoZ)" , m_min, m_max, m_bin ); + plot1D( bdpX , label1+"HypoSM/"+label2+"/dX" , "dX : Hypo-Brem(ShowerMax)" , m_min, m_max, m_bin ); + plot1D( bdpY , label1+"HypoSM//"+label2+"/dY", "dY : Hypo-Brem(ShowerMax)" , m_min, m_max, m_bin ); + } + } + if(m_profil){ + profile1D( bthX, bdceX , label1+"Cell/dX.thX" , "dX.vs.thX: Cell-Brem(CellZ)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthY, bdceX , label1+"Cell/dX.thY" , "dX.vs.thY: Cell-Brem(CellZ)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthX, bdclX , label1+"Cluster/dX.thX", "dX.vs.thX: Cluster-Brem(ClusterZ)", thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthY, bdclX , label1+"Cluster/dX.thY", "dX.vs.thY: Cluster-Brem(ClusterZ)", thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthX, bdbX , label1+"Hypo/dX.thX" , "dX.vs.thX: Hypo-Brem(HypoZ)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthY, bdbX , label1+"Hypo/dX.thY" , "dX.vs.thY: Hypo-Brem(HypoZ)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthX, bdpX , label1+"HypoSM/dX.thX" , "dX.vs.thX: Hypo-Brem(ShoweMax)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthY, bdpX , label1+"HypoSM/dX.thY" , "dX.vs.thY: Hypo-Brem(ShowerMax)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthX, bdceY , label1+"Cell/dY.thX" , "dY.vs.thX: Hypo-Brem(CellZ)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthY, bdceY , label1+"Cell/dY.thY" , "dY.vs.thY: Hypo-Brem(CellZ)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthX, bdclY , label1+"Cluster/dY.thX", "dY.vs.thX: Cluster-Brem(ClusterZ)", thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthY, bdclY , label1+"Cluster/dY.thY", "dY.vs.thY: Cluster-Brem(ClusterZ)", thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthX, bdbY , label1+"Hypo/dY.thX" , "dY.vs.thX: Hypo-Brem(HypoZ)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthY, bdbY , label1+"Hypo/dY.thY" , "dY.vs.thY: Hypo-Brem(HypoZ)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthX, bdpY , label1+"HypoSM/dY.thX" , "dY.vs.thX: Hypo-Brem(ShowerMax)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthY, bdpY , label1+"HypoSM/dY.thY" , "dY.vs.thY: Hypo-Brem(ShowerMax)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + } + } + + // S-shape + const auto bsize = m_calo->cellSize(bid); + const auto batx = (bthX*bremR.Z() - bcellR.X())/bsize; // brem provides the 'true' position @ HypoZ + const auto baty = (bthY*bremR.Z() - bcellR.Y())/bsize; + const auto batxSM = (bthX*point.Z() - bcellR.X())/bsize; // brem provides the 'true' position @ ShowerMax + const auto batySM = (bthY*point.Z() - bcellR.Y())/bsize; + const auto babx = (bclusR.X() - bcellR.X())/bsize; // e-weighted barycenter (cluster) + const auto baby = (bclusR.Y() - bcellR.Y())/bsize; + const auto bacx = (bremR.X() - bcellR.X())/bsize; // S-shape corrected barycenter (hypo) + const auto bacy = (bremR.Y() - bcellR.Y())/bsize; + + for( const auto label: bsplit ){ + std::string base = "BremAlign/Sshape/" + label; + if(m_histo){ + plot2D( batx , babx, base + "Cluster/X" , "bremX(HypoZ) / clusterX " , -1*m_r, +1*m_r, -1*m_r, +1*m_r, m_b, m_b ); + plot2D( baty , baby, base + "Cluster/Y" , "bremY(HypoZ) / clusterY" , -1*m_r, +1*m_r, -1*m_r, +1*m_r, m_b, m_b ); + plot2D( batx , bacx, base + "Hypo/X" , "bremX(HypoZ) / hypoX" , -1*m_r, +1*m_r, -1*m_r, +1*m_r, m_b, m_b ); + plot2D( baty , bacy, base + "Hypo/Y" , "bremY(HypoZ) / hypoY" , -1*m_r, +1*m_r, -1*m_r, +1*m_r, m_b, m_b ); + plot2D( batxSM, babx, base + "ClusterSM/X", "bremX(ShowerMax) / clusterX", -1*m_r, +1*m_r, -1*m_r, +1*m_r, m_b, m_b ); + plot2D( batySM, baby, base + "ClusterSM/Y", "bremY(ShowerMax) / clusterY", -1*m_r, +1*m_r, -1*m_r, +1*m_r, m_b, m_b ); + plot2D( batxSM, bacx, base + "HypoSM/X" , "bremX(ShowerMax) / hypoX" , -1*m_r, +1*m_r, -1*m_r, +1*m_r, m_b, m_b ); + plot2D( batySM, bacy, base + "HypoSM/Y" , "bremY(ShowerMax) / hypoY" , -1*m_r, +1*m_r, -1*m_r, +1*m_r, m_b, m_b ); + } + if(m_profil){ + base = "BremAlign/Sshape/" + label; + profile1D( batx , babx, base + "Cluster/profX" , "bremX(HypoZ) / clusterX " , -1*m_r, +1*m_r, m_b , prof, -1*m_r, 1*m_r ); + profile1D( baty , baby, base + "Cluster/profY" , "bremY(HypoZ) / clusterY" , -1*m_r, +1*m_r, m_b , prof, -1*m_r, 1*m_r ); + profile1D( batx , bacx, base + "Hypo/profX" , "bremX(HypoZ) / hypoX" , -1*m_r, +1*m_r, m_b , prof, -1*m_r, 1*m_r ); + profile1D( baty , bacy, base + "Hypo/profY" , "bremY(HypoZ) / hypoY" , -1*m_r, +1*m_r, m_b , prof, -1*m_r, 1*m_r ); + profile1D( batxSM, babx, base + "ClusterSM/profX", "bremX(ShowerMax) / clusterX", -1*m_r, +1*m_r, m_b , prof, -1*m_r, 1*m_r ); + profile1D( batySM, baby, base + "ClusterSM/profY", "bremY(ShowerMax) / clusterY", -1*m_r, +1*m_r, m_b , prof, -1*m_r, 1*m_r ); + profile1D( batxSM, bacx, base + "HypoSM/profX" , "bremX(ShowerMax) / hypoX" , -1*m_r, +1*m_r, m_b , prof, -1*m_r, 1*m_r ); + profile1D( batySM, bacy, base + "HypoSM/profY" , "bremY(ShowerMax) / hypoY" , -1*m_r, +1*m_r, m_b , prof, -1*m_r, 1*m_r ); + + base = "BremAlign/iSshape/" + label; + profile1D( babx, batx , base + "Cluster/profX" , "bremX(HypoZ) .vs. clusterX " , -1*m_r, +1*m_r, m_b , prof, -1*m_r, 1*m_r); + profile1D( baby, baty , base + "Cluster/profY" , "bremY(HypoZ) .vs. clusterY" , -1*m_r, +1*m_r, m_b , prof, -1*m_r, 1*m_r); + profile1D( bacx, batx , base + "Hypo/profX" , "bremX(HypoZ) .vs. hypoX" , -1*m_r, +1*m_r, m_b , prof, -1*m_r, 1*m_r); + profile1D( bacy, baty , base + "Hypo/profY" , "bremY(HypoZ) .vs. hypoY" , -1*m_r, +1*m_r, m_b , prof, -1*m_r, 1*m_r); + profile1D( babx, batxSM, base + "ClusterSM/profX", "bremX(ShowerMax) .vs. clusterX" , -1*m_r, +1*m_r, m_b , prof, -1*m_r, 1*m_r); + profile1D( baby, batySM, base + "ClusterSM/profY", "bremY(ShowerMax) .vs. clusterY" , -1*m_r, +1*m_r, m_b , prof, -1*m_r, 1*m_r); + profile1D( bacx, batxSM, base + "HypoSM/profX" , "bremX(ShowerMax) .vs. hypoX" , -1*m_r, +1*m_r, m_b , prof, -1*m_r, 1*m_r); + profile1D( bacy, batySM, base + "HypoSM/profY" , "bremY(ShowerMax) .vs. hypoY" , -1*m_r, +1*m_r, m_b , prof, -1*m_r, 1*m_r); + } + } + } + + + // ----- track extrapolator alignment + const double thX = hypoR.X()/hypoR.Z(); + const double thY = hypoR.Y()/hypoR.Z(); + const double dsX = (hypoR.X() - statR.X()); // extrapolate @ ShowerMax plane + const double dsY = (hypoR.Y() - statR.Y()); + const double dcX = (hypoR.X() - closR.X()); // extrapolate @ closest state + const double dcY = (hypoR.Y() - closR.Y()); + const double dceX = (cellR.X() - statR.X()); // relative to cell + const double dceY = (cellR.Y() - statR.Y()); + const double dclX = (clusR.X() - statR.X()); // relative to cluster + const double dclY = (clusR.Y() - statR.Y()); + + // plot delta's + const std::string binX = "bin"+Gaudi::Utils::toString( int((thX-thMin)/step) ); + const std::string binY = "bin"+Gaudi::Utils::toString( int((thY-thMin)/step) ); + const std::vector<std::string> hat{ "all", binX, binY }; + + for( const auto label1: q ){ + std::string base = "ElectronAlign/Delta/" + label1 + "/"; + if(m_histo){ + for( const auto label2: hat ){ + plot1D( dceX, base+"Cell/"+label2+"/dX" , "dX : Cell-Track(CellZ)" , m_min, m_max, m_bin ); + plot1D( dceY, base+"Cell/"+label2+"/dY" , "dY : Cell-Track(CellZ)" , m_min, m_max, m_bin ); + plot1D( dclX, base+"Cluster/"+label2+"/dX", "dX : Cluster-Track(ClusterZ)" , m_min, m_max, m_bin ); + plot1D( dclY, base+"Cluster/"+label2+"/dY", "dY : Cluster-Track(ClusterZ)" , m_min, m_max, m_bin ); + plot1D( dsX , base+"HypoSM/"+label2+"/dX" , "dX : Hypo-Track(ShowerMax)" , m_min, m_max, m_bin ); + plot1D( dsY , base+"HypoSM/"+label2+"/dY" , "dY : Hypo-Track(ShowerMax)" , m_min, m_max, m_bin ); + plot1D( dcX , base+"Hypo/"+label2+"/dX" , "dX : Hypo-Track(HypoZ)" , m_min, m_max, m_bin ); + plot1D( dcY , base+"Hypo/"+label2+"/dY" , "dY : Hypo-Track(HypoZ)" , m_min, m_max, m_bin ); + } + } + if(m_profil){ + profile1D( bthX, dceX, base+"Cell/dX.thX" , "dX.vs.thX: Cell-Track(CellZ)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthY, dceX, base+"Cell/dX.thY" , "dX.vs.thY: Cell-Track(CellZ)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthX, dclX, base+"Cluster/dX.thX", "dX.vs.thX: Cluster-Track(ClusterZ)", thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthY, dclX, base+"Cluster/dX.thY", "dX.vs.thY: Cluster-Track(ClusterZ)", thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthX, dcX , base+"Hypo/dX.thX" , "dX.vs.thX: Hypo-Track(HypoZ)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthY, dcX , base+"Hypo/dX.thY" , "dX.vs.thY: Hypo-Track(HypoZ)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthX, dsX , base+"HypoSM/dX.thX" , "dX.vs.thX: Hypo-Track(ShowerMax)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthY, dsX , base+"HypoSM/dX.thY" , "dX.vs.thY: Hypo-Track(ShowerMax)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthX, dceY, base+"Cell/dY.thX" , "dY.vs.thX: Hypo-Track(CellZ)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthY, dceY, base+"Cell/dY.thY" , "dY.vs.thY: Hypo-Track(CellZ)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthX, dclY, base+"Cluster/dY.thX", "dY.vs.thX: Hypo-Track(ClusterZ)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthY, dclY, base+"Cluster/dY.thY", "dY.vs.thY: Hypo-Track(ClusterZ)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthX, dcY , base+"Hypo/dY.thX" , "dY.vs.thX: Hypo-Track(HypoZ)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthY, dcY , base+"Hypo/dY.thY" , "dY.vs.thY: Hypo-Track(HypoZ)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthX, dsY , base+"HypoSM/dY.thX" , "dY.vs.thX: Hypo-Track(ShowerMax)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + profile1D( bthY, dsY , base+"HypoSM/dY.thY" , "dY.vs.thY: Hypo-Track(ShowerMax)" , thMin, thMax, m_thBin, prof, m_min, m_max ); + } + } + + // S-shape + const double size = m_calo->cellSize(id); + const double atx = ( closR.X() - cellR.X())/size; // track propagation provides the 'true' position @ HypoZ + const double aty = ( closR.Y() - cellR.Y())/size; + const double atxSM = ( statR.X() - cellR.X())/size; // track propagation provides the 'true' position @ ShowerMax + const double atySM = ( statR.Y() - cellR.Y())/size; + const double abx = ( clusR.X() - cellR.X())/size; // e-weighted barycenter (cluster) + const double aby = ( clusR.Y() - cellR.Y())/size; + const double acx = ( hypoR.X() - cellR.X())/size; // S-shape corrected barycenter (hypo) + const double acy = ( hypoR.Y() - cellR.Y())/size; + + for( const auto label: split ){ + std::string base = "ElectronAlign/Sshape/" + label; + if(m_histo){ + plot2D( atx , abx, base + "Cluster/X" , "trackX(bestZ) .vs. clusterX " , -1*m_r, +1*m_r, -1*m_r, +1*m_r, m_b, m_b ); + plot2D( aty , aby, base + "Cluster/Y" , "trackY(bestZ) .vs. clusterY" , -1*m_r, +1*m_r, -1*m_r, +1*m_r, m_b, m_b ); + plot2D( atx , acx, base + "Hypo/X" , "trackX(bestZ) .vs. hypoX" , -1*m_r, +1*m_r, -1*m_r, +1*m_r, m_b, m_b ); + plot2D( aty , acy, base + "Hypo/Y" , "trackY(bestZ) .vs. hypoY" , -1*m_r, +1*m_r, -1*m_r, +1*m_r, m_b, m_b ); + plot2D( atxSM, abx, base + "ClusterSM/X", "trackX(ShowerMax) .vs. clusterX" , -1*m_r, +1*m_r, -1*m_r, +1*m_r, m_b, m_b ); + plot2D( atySM, aby, base + "ClusterSM/Y", "trackY(ShowerMax) .vs. clusterY" , -1*m_r, +1*m_r, -1*m_r, +1*m_r, m_b, m_b ); + plot2D( atxSM, acx, base + "HypoSM/X" , "trackX(ShowerMax) .vs. hypoX" , -1*m_r, +1*m_r, -1*m_r, +1*m_r, m_b, m_b ); + plot2D( atySM, acy, base + "HypoSM/Y" , "trackY(ShowerMax) .vs. hypoY" , -1*m_r, +1*m_r, -1*m_r, +1*m_r, m_b, m_b ); + } + if(m_profil){ + profile1D( atx , abx, base + "Cluster/profX" , "trackX(bestZ) .vs. clusterX " , -1*m_r, +1*m_r, m_b, prof, -1*m_r, 1*m_r ); + profile1D( aty , aby, base + "Cluster/profY" , "trackY(bestZ) .vs. clusterY" , -1*m_r, +1*m_r, m_b, prof, -1*m_r, 1*m_r ); + profile1D( atx , acx, base + "Hypo/profX" , "trackX(bestZ) .vs. hypoX" , -1*m_r, +1*m_r, m_b, prof, -1*m_r, 1*m_r ); + profile1D( aty , acy, base + "Hypo/profY" , "trackY(bestZ) .vs. hypoY" , -1*m_r, +1*m_r, m_b, prof, -1*m_r, 1*m_r ); + profile1D( atxSM, abx, base + "ClusterSM/profX" , "trackX(ShowerMax) .vs. clusterX" , -1*m_r, +1*m_r, m_b, prof, -1*m_r, 1*m_r ); + profile1D( atySM, aby, base + "ClusterSM/profY" , "trackY(ShowerMax) .vs. clusterY" , -1*m_r, +1*m_r, m_b, prof, -1*m_r, 1*m_r ); + profile1D( atxSM, acx, base + "HypoSM/profX" , "trackX(ShowerMax) .vs. hypoX" , -1*m_r, +1*m_r, m_b, prof, -1*m_r, 1*m_r ); + profile1D( atySM, acy, base + "HypoSM/profY" , "trackY(ShowerMax) .vs. hypoY" , -1*m_r, +1*m_r, m_b, prof, -1*m_r, 1*m_r ); + base = "ElectronAlign/iSshape/" + label; + profile1D( abx, atx , base + "Cluster/profX" , "trackX(bestZ) .vs. clusterX " , -1*m_r, +1*m_r, m_b, prof, -1*m_r, 1*m_r ); + profile1D( aby, aty , base + "Cluster/profY" , "trackY(bestZ) .vs. clusterY" , -1*m_r, +1*m_r, m_b, prof, -1*m_r, 1*m_r ); + profile1D( acx, atx , base + "Hypo/profX" , "trackX(bestZ) .vs. hypoX" , -1*m_r, +1*m_r, m_b, prof, -1*m_r, 1*m_r ); + profile1D( acy, aty , base + "Hypo/profY" , "trackY(bestZ) .vs. hypoY" , -1*m_r, +1*m_r, m_b, prof, -1*m_r, 1*m_r ); + profile1D( abx, atxSM, base + "ClusterSM/profX" , "trackX(ShowerMax) .vs. clusterX" , -1*m_r, +1*m_r, m_b, prof, -1*m_r, 1*m_r ); + profile1D( aby, atySM, base + "ClusterSM/profY" , "trackY(ShowerMax) .vs. clusterY" , -1*m_r, +1*m_r, m_b, prof, -1*m_r, 1*m_r ); + profile1D( acx, atxSM, base + "HypoSM/profX" , "trackX(ShowerMax) .vs. hypoX" , -1*m_r, +1*m_r, m_b, prof, -1*m_r, 1*m_r ); + profile1D( acy, atySM, base + "HypoSM/profY" , "trackY(ShowerMax) .vs. hypoY" , -1*m_r, +1*m_r, m_b, prof, -1*m_r, 1*m_r ); + } + } + } + return; +} + +//============================================================================== diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.h b/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.h new file mode 100644 index 0000000000000000000000000000000000000000..86e9487ba901b55f4f34620ce691262ae96a90c4 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureAlignmentNtp.h @@ -0,0 +1,114 @@ +#ifndef CALOFUTUREALIGNEMENTNTP_H +#define CALOFUTUREALIGNEMENTNTP_H 1 + +// Include files +// from Gaudi +#include "GaudiAlg/Consumer.h" +#include "GaudiAlg/GaudiTupleAlg.h" +#include "GaudiKernel/IEventTimeDecoder.h" +#include "Event/ODIN.h" +#include "Event/ProtoParticle.h" +#include "Event/RecVertex.h" +#include "Event/Track.h" +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureInterfaces/ICaloFutureHypo2CaloFuture.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" +// #include "CaloFutureInterfaces/ICaloFutureHypoEstimator.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "CaloFutureUtils/CaloMomentum.h" +#include "CaloFutureUtils/ICaloFutureElectron.h" +#include "TrackInterfaces/ITrackExtrapolator.h" + + +// List of Consumers dependencies +namespace { + using Vertices = LHCb::RecVertices; + using ODIN = LHCb::ODIN; + using Digits = LHCb::CaloDigits; + using Tracks = LHCb::Tracks; + using Protos = LHCb::ProtoParticles; +} + +//============================================================================== + +/** @class CaloFutureAlignmentNtp CaloFutureAlignmentNtp.h + * + * + * @author Olivier Deschamps + * @date 2009-12-11 + */ + +class CaloFutureAlignmentNtp final +: public Gaudi::Functional::Consumer<void(const Vertices&, const ODIN&, const Digits&, const Tracks&, const Protos&), + Gaudi::Functional::Traits::BaseClass_t<GaudiTupleAlg>> +{ +public: + /// Standard constructor + CaloFutureAlignmentNtp( const std::string& name, ISvcLocator* pSvcLocator ); + + StatusCode initialize() override; ///< Algorithm initialization + void operator()(const Vertices&, const ODIN&, const Digits&, const Tracks&, const Protos&) const override; + + /// C++11 non-copyable idiom + CaloFutureAlignmentNtp() = delete; + CaloFutureAlignmentNtp( const CaloFutureAlignmentNtp& ) = delete; + CaloFutureAlignmentNtp &operator=( const CaloFutureAlignmentNtp& ) = delete; + +private: + bool acceptTrack(const LHCb::Track*) const; + bool hypoProcessing(const LHCb::CaloHypo* hypo) const; + bool inArea(const LHCb::CaloHypo* hypo) const; + + // Tools + DeCalorimeter* m_calo = nullptr; + std::string m_vertLoc; + + ToolHandle<IFutureCounterLevel> m_counterStat { "FutureCounterLevel"}; + ToolHandle<ICaloFutureElectron> m_caloElectron { "CaloFutureElectron" , this }; + ToolHandle<IEventTimeDecoder> m_odin { "OdinTimeDecoder/OdinDecoder" , this }; + ToolHandle<ICaloFutureHypo2CaloFuture> m_toSpd { "CaloFutureHypo2CaloFuture/CaloFutureHypo2Spd" , this }; + ToolHandle<ICaloFutureHypo2CaloFuture> m_toPrs { "CaloFutureHypo2CaloFuture/CaloFutureHypo2Prs" , this }; + ToolHandle<ITrackExtrapolator> m_extrapolator { "TrackRungeKuttaExtrapolator/Extrapolator", this }; + + // Flags -- init + Gaudi::Property<bool> m_usePV3D { this, "UsePV3D", false}; + Gaudi::Property<std::vector<int>> m_tracks { this, "TrackTypes", { LHCb::Track::Types::Long }}; + + // Flags -- global cuts + Gaudi::Property<std::pair<double, double>> m_nSpd { this, "SpdMult" , { 0. , 250. }}; + Gaudi::Property<std::pair<double, double>> m_nTrk { this, "nTracks" , { 0. , 350. }}; + Gaudi::Property<std::pair<double, double>> m_nVtx { this, "nVertices", { -1., 999999. }}; + Gaudi::Property<bool> m_inArea {this, "inAreaAcc", true}; + + // Flags -- hypo cuts + Gaudi::Property<std::pair<double, double>> m_e { this, "EFilter" , { 0. , 99999999. }}; + Gaudi::Property<std::pair<double, double>> m_et { this, "EtFilter" , { 150., 999999. }}; + Gaudi::Property<std::pair<double, double>> m_prs { this, "PrsFilter", { 10. , 1024 }}; + Gaudi::Property<std::pair<double, double>> m_spd { this, "SpdFilter", { .5 , 9999. }}; + + // Flags + Gaudi::Property<std::pair<double, double>> m_eop { this, "EoPFilter" , { 0.7 , 1.3}}; + Gaudi::Property<std::pair<double, double>> m_dlle { this, "DLLeFilter" , { -9999999. , 9999999.}}; + Gaudi::Property<std::pair<double, double>> m_rdlle { this, "RichDLLeFilter" , { 0. , 99999.}}; + Gaudi::Property<std::pair<double, double>> m_bMatch { this, "BremMatchFilter" , { -99999999., 99999999.}}; + Gaudi::Property<std::pair<double, double>> m_eMatch { this, "ElectronMatchFilter", { -999999. , 999999.}}; + Gaudi::Property<std::pair<double, double>> m_cMatch { this, "ClusterMatchFilter" , { -999999. , 999999.}}; + Gaudi::Property<std::pair<double, double>> m_mas { this, "MassFilter" , { -99999. , 99999.}}; + Gaudi::Property<std::pair<double, double>> m_dist { this, "BremEleDistFilter" , { 4. , 99999.}}; + + Gaudi::Property<bool> m_pairing { this, "EmlectronPairing" , true}; + Gaudi::Property<float> m_min { this, "DeltaMin" , -150.}; + Gaudi::Property<float> m_max { this, "DeltaMax" , +150.}; + Gaudi::Property<int> m_thBin { this, "ThetaBin" , 14}; + Gaudi::Property<int> m_bin { this, "DeltaBin" , 150}; + Gaudi::Property<bool> m_brem { this, "ElectronWithBremOnly", false}; + Gaudi::Property<float> m_r { this, "SshapeRange" , 0.7}; + Gaudi::Property<int> m_b { this, "SshapeBin" , 50}; + + // Flags -- outputs + Gaudi::Property<bool> m_histo { this, "Histo" , true}; + Gaudi::Property<bool> m_tuple { this, "Tuple" , true}; + Gaudi::Property<bool> m_profil { this, "Profile", true}; + +}; +#endif // CALOFUTUREALIGNEMENTNTP_H diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureClusterChecker.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureClusterChecker.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f037ad823aedf1214e22562ab4393edb7198557e --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureClusterChecker.cpp @@ -0,0 +1,115 @@ +// Includes +#include "GaudiAlg/Consumer.h" +#include "Relations/RelationWeighted1D.h" +#include "Event/CaloCluster.h" +#include "Event/MCParticle.h" +#include "CaloFutureMoniAlg.h" + +// ============================================================================= + +/** @class CaloFutureClusterChecker CaloFutureClusterChecker.cpp + * + * The algorithm for trivial monitoring of MCTruthing of + * "CaloClusters" with Tracks. + * It produces 5 histograms: + * + * <ol> + * <li> Total Link distribution </li> + * <li> Link multiplicity distribution </li> + * <li> Minimal Weight distribution </li> + * <li> Maximal Weight distribution </li> + * <li> Weight distribution </li> + * </ol> + * + * Histograms reside in the directory @p /stat/"Name" , where + * @ "Name" is the name of the algorithm + * + * @see CaloFutureMoniAlg + * @see GaudiHistoAlg + * @see GaudiAlgorithm + * @see Algorithm + * @see IAlgorithm + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 02/11/2001 + */ + +using Input = LHCb::RelationWeighted1D<LHCb::CaloCluster,LHCb::MCParticle,float>; +using Clusters = LHCb::CaloCluster::Container; + + +class CaloFutureClusterChecker final +: public Gaudi::Functional::Consumer<void(const Input&, const Clusters&, const Clusters&), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureMoniAlg>> +{ +public: + StatusCode initialize() override; + void operator()(const Input&, const Clusters&, const Clusters&) const override; + + CaloFutureClusterChecker( const std::string &name, ISvcLocator *pSvcLocator ); +}; + +// ============================================================================= + +DECLARE_COMPONENT( CaloFutureClusterChecker ) + +// ============================================================================= + +CaloFutureClusterChecker::CaloFutureClusterChecker( const std::string &name, ISvcLocator *pSvcLocator ) +: Consumer( name, pSvcLocator, { + KeyValue{ "Input" , "Relations/"+LHCb::CaloClusterLocation::Default }, + KeyValue{ "InputClusters" , LHCb::CaloClusterLocation::Ecal }, + KeyValue{ "InputSplitClusters", LHCb::CaloClusterLocation::EcalSplit } +}){} + +// ============================================================================= + +StatusCode CaloFutureClusterChecker::initialize(){ + StatusCode sc = Consumer::initialize(); + if ( sc.isFailure() ) return sc; + hBook1( "1", "log10(#Links+1) '" + inputLocation() + "'", 0, 5 ); + hBook1( "2", "Rels/Cluster '" + inputLocation() + "'", 0, 50 ); + hBook1( "3", "Minimal weight/e '" + inputLocation() + "'", 0, 2.0 ); + hBook1( "4", "Maximal weight/e '" + inputLocation() + "'", 0, 2.0 ); + hBook1( "5", " Weight/e '" + inputLocation() + "'", 0, 2.0 ); + if( m_split ){ + Warning( "No area spliting allowed for CaloFutureClusterChecker").ignore(); + m_split = false; + } + return StatusCode::SUCCESS; +} + +// ============================================================================= + +void CaloFutureClusterChecker::operator()(const Input& table, const Clusters& clusters1, const Clusters& clusters2) const { + // produce histos ? + if ( !produceHistos() ) return; + + // total number of links + hFill1( "1", log10( table.relations().size() + 1. ) ); + + // loop over clusters + auto filler = [&table, this](auto& clusters){ + for( const auto& cluster: clusters ){ + const auto& range = table.relations( cluster ); + // number of relations per cluster + hFill1( "2", range.size() ); + if ( range.empty() ) continue; + // cluster energy + const double e = cluster->e(); + // minimal weight + hFill1( "3", range.front().weight() / e ); + // maximal weight + hFill1( "4", range.back().weight() / e ); + // all weights + for( const auto& relation: range ){ + hFill1( "5", relation.weight() / e ); + } + } // end of loop over clusters + }; + + filler(clusters1); + filler(clusters2); + + return; +} diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureClusterMatchMonitor.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureClusterMatchMonitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7503372ccd6e04298c25b335479e4d9a5f63c757 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureClusterMatchMonitor.cpp @@ -0,0 +1,127 @@ +// Includes +#include "GaudiAlg/Consumer.h" +#include "Relations/RelationWeighted2D.h" +#include "Event/CaloCluster.h" +#include "Event/Track.h" +#include "CaloFutureUtils/CaloFuture2Track.h" +#include "CaloFutureMoniAlg.h" + +#include "CaloFutureMoniUtils.h" // Local + +// ============================================================================= + +/** @class CaloFutureClusterMatchMonitor CaloFutureClusterMatchMonitor.cpp + * + * The algorithm for trivial monitoring of matching of + * "CaloFutureClusters" with Tracks. + * It produces 5 histograms: + * + * <ol> + * <li> Total Link distribution </li> + * <li> Link multiplicity distribution </li> + * <li> Minimal Weight distribution </li> + * <li> Maximal Weight distribution </li> + * <li> Weight distribution </li> + * </ol> + * + * Histograms reside in the directory @p /stat/"Name" , where + * @ "Name" is the name of the algorithm + * + * @see CaloFutureMoniAlg + * @see GaudiHistoAlg + * @see GaudiAlgorithm + * @see Algorithm + * @see IAlgorithm + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 02/11/2001 + */ + +using Input = LHCb::RelationWeighted2D< LHCb::CaloCluster, LHCb::Track, float >; +using Clusters = LHCb::CaloCluster::Container; + +class CaloFutureClusterMatchMonitor final +: public Gaudi::Functional::Consumer<void(const Input&, const Clusters&, const Clusters&), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureMoniAlg>> +{ +public: + /// standard algorithm initialization + StatusCode initialize() override; + void operator()(const Input&, const Clusters&, const Clusters&) const override; + + CaloFutureClusterMatchMonitor( const std::string &name, ISvcLocator *pSvcLocator ); +}; + +// ============================================================================= + +DECLARE_COMPONENT( CaloFutureClusterMatchMonitor ) + +// ============================================================================= + +CaloFutureClusterMatchMonitor::CaloFutureClusterMatchMonitor( const std::string &name, ISvcLocator *pSvcLocator ) +: Consumer( name, pSvcLocator, { + KeyValue{ "Input" , "" }, + KeyValue{ "InputClusters" , "" }, + KeyValue{ "InputSplitClusters", "" } +}){ + updateHandleLocation( *this, "Input" , LHCb::CaloFutureAlgUtils::CaloFutureIdLocation("ClusterMatch", context() )); + updateHandleLocation( *this, "InputClusters", LHCb::CaloFutureAlgUtils::CaloFutureClusterLocation(name,context() )); + updateHandleLocation( *this, "InputSplitClusters", LHCb::CaloFutureAlgUtils::CaloFutureSplitClusterLocation( context() )); +} + +// ============================================================================= + +StatusCode CaloFutureClusterMatchMonitor::initialize(){ + StatusCode sc = Consumer::initialize(); + if ( sc.isFailure() ) return sc; + + hBook1( "1", "log10(#Links+1) '"+inputLocation()+"'", 0, 4, 100 ); + hBook1( "2", "Tracks per cluster", 0, 25, 25 ); + hBook1( "3", "Minimal weight", 0, 100, 200 ); + hBook1( "4", "Maximal weight", 0, 1000, 200 ); + hBook1( "5", "Weights", 0, 1000, 500 ); + if( m_split ){ + Warning( "No area spliting allowed for CaloFutureClusterMatchMonitor").ignore(); + m_split = false; + } + return StatusCode::SUCCESS; +} + +// ============================================================================= + +void CaloFutureClusterMatchMonitor::operator()(const Input& table, const Clusters& clusters1, const Clusters& clusters2 ) const { + + // produce histos ? + if ( !produceHistos() ) return; + + // total number of links + hFill1( "1", log10( table.relations().size() + 1. ) ); + + // loop over all clusters + auto filler = [&table, this](auto& clusters){ + for( const auto& cluster: clusters ){ + const auto& range = table.relations( cluster ); + // number of related tracks + hFill1( "2", range.size() ); + if ( range.empty() ) continue; + // minimal weight + hFill1( "3", range.front().weight() ); + // maximal weight + hFill1( "4", range.back().weight() ); + // all weights + for( const auto& relation: range ){ + hFill1( "5", relation.weight() ); + } + } // end of loop over clusters + }; + + filler(clusters1); + filler(clusters2); + + if(m_counterStat->isQuiet()){ + counter("Monitor " + inputLocation<0>()) += table.relations().size(); + counter("Monitor " + inputLocation<1>()) += clusters1.size(); + counter("Monitor " + inputLocation<2>()) += clusters2.size(); + } + return; +} diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureClusterMonitor.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureClusterMonitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ca02636c7e252bb624fe84344ba7d48e4eac90f0 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureClusterMonitor.cpp @@ -0,0 +1,136 @@ +// Includes +#include "GaudiAlg/Consumer.h" +#include "Event/CaloCluster.h" +#include "CaloFutureMoniAlg.h" + +// ============================================================================= + +/** @class CaloFutureClusterMonitor CaloFutureClusterMonitor.cpp + * + * The algorithm for trivial monitoring of "CaloFutureCluster" containers. + * The algorithm produces 8 histograms: + * + * <ol> + * <li> @p CaloCluster multiplicity </li> + * <li> @p CaloCluster size (number of cells) </li> + * <li> @p CaloCluster energy distribution </li> + * <li> @p CaloCluster transverse energy distribution </li> + * <li> @p CaloCluster x-distribution </li> + * <li> @p CaloCluster y-distribution </li> + * <li> @p CaloCluster x vs y-distribution </li> + * </ol> + * + * Histograms reside in the directory @p /stat/"Name" , where + * @ "Name" is the name of the algorithm + * + * @see CaloFutureMoniAlg + * @see GaudiHistoAlg + * @see GaudiAlgorithm + * @see Algorithm + * @see IAlgorithm + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 02/11/2001 + */ + +using Input = LHCb::CaloCluster::Container; + +class CaloFutureClusterMonitor final +: public Gaudi::Functional::Consumer<void(const Input&), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureMoniAlg>> +{ +public: + /// standard algorithm initialization + StatusCode initialize() override; + void operator()(const Input&) const override; + + CaloFutureClusterMonitor( const std::string &name, ISvcLocator *pSvcLocator ); +}; + +// ============================================================================= + +DECLARE_COMPONENT( CaloFutureClusterMonitor ) + +// ============================================================================= + +CaloFutureClusterMonitor::CaloFutureClusterMonitor( const std::string &name, ISvcLocator *pSvcLocator ) +: Consumer( name, pSvcLocator, KeyValue{ "Input", {}} +){ + m_multMax = 200; + m_multBin = 100; + auto Input = LHCb::CaloFutureAlgUtils::CaloFutureClusterLocation( name, context() ); + updateHandleLocation( *this, "Input", Input ); +} + +// ============================================================================= + +/// standard algorithm initialization +StatusCode CaloFutureClusterMonitor::initialize(){ + StatusCode sc = Consumer::initialize(); + if ( sc.isFailure() ) return sc; + hBook1( "1", "# of Clusters " + inputLocation() , m_multMin , m_multMax , m_multBin ); + hBook1( "2", "Cluster digit multiplicity " + inputLocation() , m_sizeMin , m_sizeMax , m_sizeBin ); + hBook1( "3", "Cluster Energy " + inputLocation() , m_energyMin , m_energyMax , m_energyBin ); + hBook1( "4", "Cluster Et " + inputLocation() , m_etMin , m_etMax , m_etBin ); + hBook1( "5", "Cluster x " + inputLocation() , m_xMin , m_xMax , m_xBin ); + hBook1( "6", "Cluster y " + inputLocation() , m_yMin , m_yMax , m_yBin ); + hBook2( "7", "Cluster barycenter position x vs y " + inputLocation() , m_xMin , m_xMax , m_xBin, m_yMin, m_yMax, m_yBin ); + hBook2( "8", "Energy-weighted cluster barycenter position x vs y " + inputLocation(), m_xMin , m_xMax , m_xBin, m_yMin, m_yMax, m_yBin ); + hBook1( "9", "Cluster digit used for Energy multiplicity " + inputLocation() , m_sizeMin , m_sizeMax , m_sizeBin ); + return StatusCode::SUCCESS; +} + +// ============================================================================= +// standard execution method +// ============================================================================= + +// StatusCode CaloFutureClusterMonitor::execute(){ +void CaloFutureClusterMonitor::operator()(const Input& clusters) const { + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " Producing histo " << produceHistos() << endmsg; + // produce histos ? + if ( !produceHistos() ) return; + + if ( clusters.empty() ){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Found empty cluster in " << inputLocation() << endmsg; + return; + } + + // fill multiplicity histogram + initFutureCounters(); + + for( const auto& cluster: clusters ){ + if ( 0 == cluster ) continue; + const double e = cluster->position().e(); + const double x = cluster->position().x(); + const double y = cluster->position().y(); + const double z = cluster->position().z(); + const double et = e * sqrt( x*x + y*y ) / sqrt( x*x+y*y+z*z ); + if( e < m_eFilter) continue; + if( et < m_etFilter) continue; + const auto id = cluster->seed(); + count( id ); + hFill1(id, "2", cluster->entries().size() ); + hFill1(id, "3", e ); + hFill1(id, "4", et ); + hFill1(id, "5", x ); + hFill1(id, "6", y ); + hFill2(id, "7", x,y ); + hFill2(id, "8", x,y,e); + + int iuse = 0; + for( const auto& entry: cluster->entries() ){ + if( 0 != (LHCb::CaloDigitStatus::UseForEnergy & entry.status()) ) iuse++; + } + hFill1(id,"9", iuse ); + if(doHisto("10"))fillCaloFuture2D("10", id, 1., "Cluster position 2Dview " + inputLocation() ); + if(doHisto("11"))fillCaloFuture2D("11", id, e , "Cluster Energy 2Dview " + inputLocation() ); + + } + // fill counter + fillFutureCounters("1"); + + return; +} diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureDigitMonitor.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureDigitMonitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..254718916ee0591aeec4a25a222fe6216ef157f1 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureDigitMonitor.cpp @@ -0,0 +1,154 @@ +// Includes +#include "GaudiAlg/Consumer.h" +#include "Event/CaloDigit.h" +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureMoniAlg.h" + +// ============================================================================= + +/** @class CaloFutureDigitMonitor CaloFutureDigitMonitor.cpp + * + * The algorithm for trivial monitoring of "CaloDigit" containers. + * The algorithm produces the following histograms: + * 1. CaloDigit multiplicity + * 2. CaloDigit ocupancy 2D plot per area + * 3. CaloDigit energy 2D plot per area + * The same set of histograms, but with cut on Et (or E), is produced if specified + * + * Histograms reside in the directory @p /stat/"Name" , where + * @p "Name" is the name of the algorithm + * + * @see CaloFutureMoniAlg + * @see GaudiHistoAlg + * @see GaudiAlgorithm + * @see Algorithm + * @see IAlgorithm + * + * @author Konstantin Belous Konstantin.Beloous@itep.ru + * @date 21/06/2007 + */ + +using Input = LHCb::CaloDigit::Container; + +class CaloFutureDigitMonitor final +: public Gaudi::Functional::Consumer<void(const Input&), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureMoniAlg>> +{ +public: + StatusCode initialize() override; + void operator()(const Input&) const override; + + CaloFutureDigitMonitor( const std::string &name, ISvcLocator *pSvcLocator ); + +private: + DeCalorimeter *m_calo = nullptr; + Gaudi::Property<bool> m_spectrum {this, "Spectrum", false, "activate spectrum per channel histogramming"}; +}; + +// ============================================================================= + +DECLARE_COMPONENT( CaloFutureDigitMonitor ) + +// ============================================================================= + +CaloFutureDigitMonitor::CaloFutureDigitMonitor( const std::string &name, ISvcLocator *pSvcLocator ) +: Consumer( name, pSvcLocator, + KeyValue{ "Input", LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation("") } +){ + updateHandleLocation( *this, "Input", LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation(name)); +} + +// ============================================================================= +// standard initialize method +// ============================================================================= + +StatusCode CaloFutureDigitMonitor::initialize(){ + StatusCode sc = Consumer::initialize(); + if ( sc.isFailure() ) return sc; + + if ( "Ecal" == detData() ) { + m_calo = getDet<DeCalorimeter>( DeCalorimeterLocation::Ecal ); } + else if ( "Hcal" == detData() ) { + m_calo = getDet<DeCalorimeter>( DeCalorimeterLocation::Hcal ); } + else if ( "Prs" == detData() ){ + m_calo = getDet<DeCalorimeter>( DeCalorimeterLocation::Prs ); } + else if ( "Spd" == detData() ) { + m_calo = getDet<DeCalorimeter>( DeCalorimeterLocation::Spd ); } + else { + return Error( "Unknown detector name "+detData() ); + } + + hBook1( "1", detData() + " : # of Digits" , m_multMin , m_multMax, m_multBin ); + if( detData() != "Spd" ) hBook1( "2", detData() + " digits energy" , m_energyMin , m_energyMax, m_energyBin ); + if( detData() != "Spd" && detData() != "Prs")hBook1( "3", detData() + " digits Et" , m_etMin , m_etMax , m_etBin); + hBook1( "4", "Hypo X " + inputLocation(), m_xMin , m_xMax , m_xBin ); + hBook1( "5", "Hypo Y " + inputLocation(), m_yMin , m_yMax , m_yBin ); + hBook2( "6", "Digit position x vs y " + inputLocation(), m_xMin, m_xMax, m_xBin, m_yMin, m_yMax, m_yBin); + hBook2( "7", "Energy-weighted digit position x vs y " + inputLocation(),m_xMin, m_xMax, m_xBin, m_yMin, m_yMax, m_yBin); + + info() << detData() << " digits from " << inputLocation() << endmsg; + + return StatusCode::SUCCESS; +} + +// ============================================================================ +// standard execution method +// ============================================================================ + +void CaloFutureDigitMonitor::operator()(const Input& digits) const { + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << name() << " execute " << endmsg; + + // produce histos ? + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " Producing histo " << produceHistos() << endmsg; + if ( !produceHistos() ) return; // StatusCode::SUCCESS; + + if ( digits.empty() ){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Found empty container in " << inputLocation() << endmsg; + return; + } + + initFutureCounters(); + + for( const auto& digit: digits ){ + if ( digit == nullptr ) continue; + const auto id = digit->cellID(); + const auto e = digit->e(); + const auto et = e * m_calo->cellSine( id ); + if( e < m_eFilter) continue; + if( et < m_etFilter) continue; + count( id ); + hFill1(id , "2", e ); + if( detData() != "Spd" && detData() != "Prs")hFill1(id, "3", et ); + const double x = m_calo->cellCenter(id).X(); + const double y = m_calo->cellCenter(id).Y(); + hFill1(id, "4", x ); + hFill1(id, "5", y ); + hFill2(id, "6", x, y ); + hFill2(id, "7", x, y, e ); + if(doHisto("8")) fillCaloFuture2D("8", id , 1. , detData() + " digits position 2D view"); + if( detData() != "Spd" && doHisto("9") ) fillCaloFuture2D("9", id , e , detData() + " digits energy 2D view"); + + if (m_spectrum) { + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Filling cell by cell histograms" << endmsg; + const int col = id.col(); + const int row = id.row(); + std::ostringstream tit; + tit << detData() << " channel : " << id; + const auto unit = detData() + "Cells/" + id.areaName() + "/" + + Gaudi::Utils::toString(row) + ";" + Gaudi::Utils::toString(col); + if( UNLIKELY( msgLevel(MSG::VERBOSE) ) ) + verbose() << " et " << et << " cell " << unit << endmsg; + if( detData() == "Prs") + plot1D(e , unit, tit.str(), m_energyMin, m_energyMax, m_energyBin); + else + plot1D(et, unit, tit.str(), m_etMin, m_etMax, m_etBin); + } + } + fillFutureCounters("1"); + return; // StatusCode::SUCCESS; +} diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureEFlowAlg.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureEFlowAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac29a2eb840523bc8e788cadf59d5cb12a1ad513 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureEFlowAlg.cpp @@ -0,0 +1,108 @@ +#include "CaloFutureEFlowBase.h" +#include "GaudiAlg/Consumer.h" +#include "Event/ODIN.h" + +/* + Class CaloFutureEFlowAlg + + Refactored from the original implementation to allow migration to Gaudi::Functional, + such that this class's computation doesn't rely on MC objects. + + Author: Chitsanu Khurewathanakul + Data : 2016-10-29 + */ + +class CaloFutureEFlowAlg final +: public Gaudi::Functional::Consumer<void(const Input&, const LHCb::ODIN&), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureEFlowBase>> +{ +public: + void operator()(const Input&, const LHCb::ODIN&) const override; + + CaloFutureEFlowAlg(const std::string &name, ISvcLocator *pSvcLocator); + +private: + Gaudi::Property<bool> m_simulation { this, "Simulation" , true}; + Gaudi::Property<bool> m_ignoreTAE { this, "IgnoreTAE" , true}; + Gaudi::Property<bool> m_ignoreNonBeamCrossing { this, "IgnoreNonBeamCrossing" , true}; + Gaudi::Property<bool> m_ignoreNonPhysicsTrigger { this, "IgnoreNonPhysicsTrigger", true}; +}; + +//============================================================================== + +DECLARE_COMPONENT( CaloFutureEFlowAlg ) + +//============================================================================== + +CaloFutureEFlowAlg::CaloFutureEFlowAlg( const std::string &name, ISvcLocator *pSvcLocator ) + : Consumer( name, pSvcLocator, { + KeyValue{ "Input" , "" }, + KeyValue{ "InputODIN" , LHCb::ODINLocation::Default }, + }) +{ + // Configure Input, based on detData() + updateHandleLocation( *this, "Input", digitLocation()); +} + +//============================================================================== +// Main execution +//============================================================================== + +void CaloFutureEFlowAlg::operator()(const Input& digits, const LHCb::ODIN& evt) const { + + // In simulated sample, it bypasses this check + if(!m_simulation) { + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Event: " << evt.eventNumber() << " Run: " << evt.runNumber() << endmsg; + + const LHCb::ODIN::BXTypes bxtype = evt.bunchCrossingType(); + const unsigned int tae = evt.timeAlignmentEventWindow(); + const unsigned int trigger = evt.triggerType(); + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " TAE " << tae + << " BXType " << bxtype + << " trigger type " << trigger + << endmsg; + + if (tae!=0 && m_ignoreTAE) { + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " TAE WINDOW SET TO " << tae << " WILL SKIP THE EVENT " << endmsg; + return; + } + if (bxtype!=3 && m_ignoreNonBeamCrossing) { + //3 = BeamCrossing + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " BEAM CROSSING TYPE IS " << bxtype << " WILL SKIP THE EVENT " << endmsg; + return; + } + if (trigger!=1 && m_ignoreNonPhysicsTrigger){ + //1 = PhysicsTrigger + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " TRIGGER TYPE IS " << trigger << " WILL SKIP THE EVENT " << endmsg; + return; + } + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " TAE " << tae + << " BXType " << bxtype + << " trigger type " << trigger + << endmsg; + } + + // produce histos ? + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " Producing histo " << produceHistos() << endmsg; + if ( !produceHistos() ) return; + + // get input data + if ( digits.empty() ){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Empty digit found at " << inputLocation() << endmsg; + return; + } + + // Main execution in the CaloFutureEFlowBase + process_digits(digits); +} + +//============================================================================== diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureEFlowBase.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureEFlowBase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d58ac9316919a5f86b5e21f7647620704c232610 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureEFlowBase.cpp @@ -0,0 +1,84 @@ +// Includes +#include "CaloFutureEFlowBase.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : CaloFutureEFlowAlg +// +// 2009-04-08 : Aurelien Martens +//----------------------------------------------------------------------------- + +//============================================================================== +// Initialization +//============================================================================== + +StatusCode CaloFutureEFlowBase::initialize() { + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "==> Initialize" << endmsg; + StatusCode sc = CaloFutureMoniAlg::initialize(); + if ( sc.isFailure() ) return sc; + + // Configure pointer to detector + const auto loc = deCaloFutureLocation(); + if(loc == ""){ + return Error( "Unknown detector name "+detData() ); + } + m_calo = getDetIfExists<DeCalorimeter>(loc); + if (!m_calo) return Error("No DeCalorimeter for "+detData()); + + hBook1( "4", detData() + " : # of Digits", m_calo->numberOfCells(), 0, m_calo->numberOfCells()); + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << " initialized" << endmsg; + return StatusCode::SUCCESS; +} + +//============================================================================== +// Main execution +//============================================================================== + +void CaloFutureEFlowBase::process_digits(const Input& digits) const { + // Reset the counter + initFutureCounters(); + + // Loop over digits + for( const auto& digit: digits ){ + if( 0 == digit ) continue; + + const auto id = digit->cellID(); + if(!(m_calo->valid(id) && !m_calo->isPinId(id))) continue; + + const double e = digit->e(); + const double et = e * m_calo->cellSine(id); + + if( UNLIKELY( msgLevel(MSG::VERBOSE) ) ) + verbose() << " before thresholds : cellID " << id.index() << " e " << e << " et " << et << endmsg; + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "thresholds are EMin " << m_eFilterMin << " EMax " << m_eFilterMax + << " EtMin " << m_etFilterMin << " EtMax " << m_etFilterMax << endmsg; + + const double pedShift = m_calo->pedestalShift(); + const double gain = m_calo->cellGain(id); + const int adc = (gain !=0.) ? (int) floor((e + pedShift) / gain) : (int) 0; + + // Skip poor input + if( adc < m_ADCFilterMin && m_ADCFilterMin !=-999) continue; + if( adc > m_ADCFilterMax && m_ADCFilterMax !=-999) continue; + if( e < m_eFilterMin && m_eFilterMin !=-999) continue; + if( e > m_eFilterMax && m_eFilterMax !=-999) continue; + if( et < m_etFilterMin && m_etFilterMin !=-999) continue; + if( et > m_etFilterMax && m_etFilterMax !=-999) continue; + + if( UNLIKELY( msgLevel(MSG::VERBOSE) ) ) + verbose() << " cellID " << id.index() << " e " << e << " et " << et << endmsg; + + count( id ); + if(doHisto("1")) fillCaloFuture2D("1", id , 1. , detData() + " digits position 2D view"); + if(doHisto("2")) fillCaloFuture2D("2", id , e , detData() + " energy weighted - digits position 2D view"); + if(doHisto("3")) fillCaloFuture2D("3", id , et , detData() + " Et weighted - digits position 2D view"); + + } // end loop over digits + + // Finally + fillFutureCounters("4"); +} + +//============================================================================== diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureEFlowBase.h b/CaloFuture/CaloFutureMoniDst/src/CaloFutureEFlowBase.h new file mode 100644 index 0000000000000000000000000000000000000000..3f7b601b43f96b3874a819ed05b11831325ead71 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureEFlowBase.h @@ -0,0 +1,77 @@ +#ifndef CALOFUTUREENERGYFLOWMONITOR_H +#define CALOFUTUREENERGYFLOWMONITOR_H 1 + +// Includes +#include "Event/CaloDigit.h" +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureMoniAlg.h" + +// ============================================================================= + +/** @class CaloFutureEFlowAlg CaloFutureEFlowAlg.h + * + * + * The algorithm for dedicated "EnergyFlow" monitoring of "CaloDigits" containers. + * The algorithm produces the following histograms: + * 1. CaloDigit multiplicity + * 2. CaloDigit ocupancy 2D plot per area + * 3. CaloDigit energy and transverse energy 2D plot per area + * The same set of histograms, but with cut on Et (or E), is produced if specified + * + * Histograms reside in the directory @p /stat/"Name" , where + * @p "Name" is the name of the algorithm + * + * @see CaloFutureMoniAlg + * @see GaudiHistoAlg + * @see GaudiAlgorithm + * @see Algorithm + * @see IAlgorithm + * + * @author Aurelien Martens + * @date 2009-04-08 + */ + +namespace { + using Input = LHCb::CaloDigit::Container; +} + +class CaloFutureEFlowBase: public CaloFutureMoniAlg { + +public: + using CaloFutureMoniAlg::CaloFutureMoniAlg; + StatusCode initialize() override; + +protected: + DeCalorimeter *m_calo = nullptr; + + // Helper method to determine input location from detector name + std::string digitLocation() const { + if(detData() == "Ecal" ){ return LHCb::CaloDigitLocation::Ecal; } + else if(detData()== "Hcal" ){ return LHCb::CaloDigitLocation::Hcal; } + else if(detData()== "Prs" ){ return LHCb::CaloDigitLocation::Prs; } + else if(detData()== "Spd" ){ return LHCb::CaloDigitLocation::Spd; } + return ""; + } + + std::string deCaloFutureLocation() const { + if ( "Ecal" == detData() ) { return DeCalorimeterLocation::Ecal; } + else if ( "Hcal" == detData() ) { return DeCalorimeterLocation::Hcal; } + else if ( "Prs" == detData() ) { return DeCalorimeterLocation::Prs; } + else if ( "Spd" == detData() ) { return DeCalorimeterLocation::Spd; } + return ""; + } + + // Main computation to be shared by subclass + void process_digits(const Input&) const; + +private: + Gaudi::Property<float> m_eFilterMin { this, "EnergyFilterMin", -999}; + Gaudi::Property<float> m_etFilterMin { this, "EtFilterMin" , -999}; + Gaudi::Property<float> m_eFilterMax { this, "EnergyFilterMax", -999}; + Gaudi::Property<float> m_etFilterMax { this, "EtFilterMax" , -999}; + Gaudi::Property<int> m_ADCFilterMin { this, "ADCFilterMin" , -999}; + Gaudi::Property<int> m_ADCFilterMax { this, "ADCFilterMax" , -999}; + +}; +#endif // CALOFUTUREENERGYFLOWMONITOR_H + diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureEFlowMC.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureEFlowMC.cpp new file mode 100644 index 0000000000000000000000000000000000000000..46d1047f1c08dad0b6bec7dbfd20a262d16f9b26 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureEFlowMC.cpp @@ -0,0 +1,137 @@ +#include "CaloFutureEFlowBase.h" +#include "GaudiAlg/Consumer.h" + +/* + Class CaloFutureEFlowMC + + Refactored from the original implementation to allow migration to Gaudi::Functional, + such that this class's computation specialized in MC objects. + + Author: Chitsanu Khurewathanakul + Data : 2016-10-29 + */ + +namespace { + using MCHits = LHCb::MCCaloHit::Container; +} + +class CaloFutureEFlowMC final +: public Gaudi::Functional::Consumer<void(const Input&, const MCHits&), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureEFlowBase>> +{ +public: + StatusCode initialize() override; + void operator()(const Input&, const MCHits&) const override; + + CaloFutureEFlowMC(const std::string &name, ISvcLocator *pSvcLocator); + +private: + Gaudi::Property<std::string> m_slot {this, "Slot", "", "pile up evetn '' or Prev/ or Next/ "}; + Gaudi::Property<bool> m_mctruth {this, "MCTruth", false}; + + const short int m_pidKplus = 321; + const short int m_pidKminus = -321; + const short int m_pidPiplus = 211; + const short int m_pidPiminus = -211; +}; + +//============================================================================== + +DECLARE_COMPONENT( CaloFutureEFlowMC ) + +//============================================================================== + +CaloFutureEFlowMC::CaloFutureEFlowMC( const std::string &name, ISvcLocator *pSvcLocator ) + : Consumer( name, pSvcLocator, { + KeyValue{ "Input" , "" }, + KeyValue{ "InputMCHits", "" }, + }) +{} + +//============================================================================== +// Initialization +//============================================================================== + +StatusCode CaloFutureEFlowMC::initialize() { + StatusCode sc = Consumer::initialize(); + if ( sc.isFailure() ) return sc; + + // Configure InputMCHits, after m_slot is frozen + // getting detector name from instance's name (so it requires the algo's name + // to start with the detector name, e.g., EcalEFlowMon + int index = name().find_last_of(".") +1 ; // return 0 if '.' not found --> OK !! + auto detectorName = name().substr( index, 4 ); + if ( name().substr(index,3) == "Prs" ) detectorName = "Prs"; + if ( name().substr(index,3) == "Spd" ) detectorName = "Spd"; + auto InputMCHits = m_slot + "MC/" + detectorName + "/Hits"; + updateHandleLocation( *this, "InputMCHits", InputMCHits ); + + return StatusCode::SUCCESS; +} + +//============================================================================== +// Main execution +//============================================================================== + +void CaloFutureEFlowMC::operator()(const Input& digits, const MCHits& hits) const { + + // produce histos ? + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " Producing histo " << produceHistos() << endmsg; + if ( !produceHistos() ) return; + + // get input data + if ( digits.empty() ){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Empty digit found at " << inputLocation() << endmsg; + return; + } + + // Main execution in the CaloFutureEFlowBase + process_digits(digits); + + // Extra work for on MCTruth if requested + if (!m_mctruth) return; + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "LOOKING FOR MCTRUTH" << endmsg; + + // Loop over MC hits + for( const auto& hit: hits ){ + if ( hit == nullptr ) continue; + const auto id = hit->cellID(); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "hit " << hit << " id " << id << endmsg; + if(!(m_calo->valid(id) && !m_calo->isPinId( id ))) continue ; + + const double e = hit->activeE(); + const int pid = hit->particle()->particleID().pid(); + + if( UNLIKELY( msgLevel(MSG::VERBOSE) ) ) + verbose() << " cellID " << id.index() << " e " << e << endmsg; + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) { + debug() << " part " << hit->particle() << endmsg; + debug() << " partID " << pid + << " origin vtx " << hit->particle()->originVertex()->position() << endmsg; + } + + // Fill the histos + if(pid==m_pidKplus) { + if(doHisto("5")) fillCaloFuture2D("5", id, 1., detData() + " K+ digits position 2D view"); + if(doHisto("6")) fillCaloFuture2D("6", id, e , detData() + " K+ energy weighted - digits position 2D view"); + } + else if(pid==m_pidKminus) { + if(doHisto("7")) fillCaloFuture2D("7", id, 1., detData() + " K- digits position 2D view"); + if(doHisto("8")) fillCaloFuture2D("8", id, e , detData() + " K- energy weighted - digits position 2D view"); + } + else if(pid==m_pidPiplus) { + if(doHisto("9")) fillCaloFuture2D("9" , id, 1., detData() + " Pi+ digits position 2D view"); + if(doHisto("10")) fillCaloFuture2D("10", id, e , detData() + " Pi+ energy weighted - digits position 2D view"); + } + else if(pid==m_pidPiminus) { + if(doHisto("11")) fillCaloFuture2D("11", id, 1., detData() + " Pi- digits position 2D view"); + if(doHisto("12")) fillCaloFuture2D("12", id, e , detData() + " Pi- energy weighted - digits position 2D view"); + } + } +} diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureEMuPIDMon.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureEMuPIDMon.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a48da0d4039cd64ef208aef5c61a68d72e4fad57 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureEMuPIDMon.cpp @@ -0,0 +1,183 @@ +// Includes +#include "GaudiAlg/Consumer.h" +#include "AIDA/IAxis.h" +#include "Event/Track.h" +#include "Event/ProtoParticle.h" +#include "Relations/IRelation.h" +#include "Relations/IRelationWeighted.h" +#include "CaloFutureUtils/CaloFuture2Track.h" +#include "CaloFutureMoniAlg.h" + +// ============================================================================= + +/** @class CaloFutureEMuPIDMon CaloFutureEMuPIDMon.cpp + * + * Class for monitoring some CaloFuturePID quantities + * + * @author Dmitry Golubkov + * @date 2010-03-25 + */ + +using Input = LHCb::ProtoParticle::Container; + +class CaloFutureEMuPIDMon final +: public Gaudi::Functional::Consumer<void(const Input&), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureMoniAlg>> +{ +public: + StatusCode initialize() override; + void operator()(const Input&) const override; + + /// Standard constructor + CaloFutureEMuPIDMon( const std::string &name, ISvcLocator *isvc ); + +private: + Gaudi::Property<bool> m_uncut + {this, "uncut", false, "true = do not apply the cuts"}; + + Gaudi::Property<float> m_minPt + {this, "pTmin", 250., "minimal pT of the track [MeV/c]"}; + + Gaudi::Property<float> m_maxPt + {this, "pTmax", 1.e10, "maximal pT of the track [MeV/c]"}; + + Gaudi::Property<float> m_RichDLLe + {this, "RichDLLe", -1.e10, "minimal ProtoParticle::additionalInfo::RichDLLe for electron id"}; + + Gaudi::Property<float> m_maxEHcalE + {this, "maxEHcalE", 1.e10, "maximal ProtoParticle::additionalInfo::CaloHcalE for electron id [MeV/c]"}; + + Gaudi::Property<float> m_minPrsE + {this, "minPrsE", 15., "minimal ProtoParticle::additionalInfo::CaloPrsE for electron id [MeV/c]"}; + + Gaudi::Property<unsigned long int> m_nEventMin + {this, "nEventMin", 200, "minimal number of events to check"}; + + Gaudi::Property<bool> m_muonLoose + {this, "useIsMuonLoose", true, "use IsMuonLoose instead of IsMuon for muon selection"}; +}; + +DECLARE_COMPONENT( CaloFutureEMuPIDMon ) + +// ============================================================================= + +/** Standard constructor + * @param name name of the algorithm instance + * @param isvc pointer to the Service Locator + */ +CaloFutureEMuPIDMon::CaloFutureEMuPIDMon( const std::string &name, ISvcLocator *pSvcLocator ) +: Consumer( name, pSvcLocator, + KeyValue{ "Input", LHCb::ProtoParticleLocation::Charged } +){ + setProperty( "histoList", std::vector<std::string>{ { "All" } } ).ignore(); + setProperty( "removeFromHistoList", std::vector<std::string>() ).ignore(); + setProperty( "SaturationBin1D", false).ignore(); + setProperty( "SaturationBin2D", false).ignore(); +} + +// ============================================================================= + +/** + * initialize the algorithm, define the histograms + */ +StatusCode CaloFutureEMuPIDMon::initialize(){ + StatusCode sc = Consumer::initialize(); + if ( sc.isFailure() ) return sc; + + hBook1( "eop", "E/p", 0.05, 2.55, 50); + + // for the time being let's not split MIP plots into A and C sides + bool old_m_splitSides = m_splitSides; + m_splitSides = false; + + hBook1( "prsem", "E Prs", 0.5, 25.5, 25); + hBook1( "ecalem", "E Ecal", 40., 2040., 50); + hBook1( "hcalem", "E Hcal", 100., 5100., 50); + + m_splitSides = old_m_splitSides; + + return StatusCode::SUCCESS; +} + + +// ============================================================================= +// standard execution method +// ============================================================================= + +void CaloFutureEMuPIDMon::operator()(const Input& particles) const { + + if( !produceHistos() ) return; // StatusCode::SUCCESS; + if( m_counterStat->isQuiet()) ++counter("nEvents"); + + // ------------------------------------------------------------------- + // Track loop + // ------------------------------------------------------------------- + + for( const auto& proto: particles ){ + if ( 0 == proto ) continue ; + const auto track = proto->track() ; + if ( 0 == track ) continue ; + if ( track->type() < LHCb::Track::Types::Long ) continue; + if ( ( track->pt() < m_minPt || track->pt() > m_maxPt ) && !m_uncut ) continue; + + const bool inprs = (proto->info( LHCb::ProtoParticle::additionalInfo::InAccPrs, double(false) )!=0); + const bool inecal = (proto->info( LHCb::ProtoParticle::additionalInfo::InAccEcal, double(false) )!=0); + const bool inhcal = (proto->info( LHCb::ProtoParticle::additionalInfo::InAccHcal, double(false) )!=0); + + const float prse = (float) proto->info(LHCb::ProtoParticle::additionalInfo::CaloPrsE, -1 * Gaudi::Units::GeV); + const float ecale = (float) proto->info(LHCb::ProtoParticle::additionalInfo::CaloEcalE, -1 * Gaudi::Units::GeV); + const float hcale = (float) proto->info(LHCb::ProtoParticle::additionalInfo::CaloHcalE, -1 * Gaudi::Units::GeV); + + + // ----------------------------------------------------------------- + // electron histograms + // e.g.: "pt>0.5&&inecal==1&&(hcale<=0||hcale>0&&inhcal==1&&hcale<1000.)&&rdlle>4" + // or: "pt>250&&inecal==1&&prse>15" + // ----------------------------------------------------------------- + + do { + if ( !inecal ) break; // ---- + float rdlle = (float) proto->info( LHCb::ProtoParticle::additionalInfo::RichDLLe, -9999.); + if ( rdlle < m_RichDLLe && !m_uncut ) break; // ---- + if ( inhcal && hcale > m_maxEHcalE && !m_uncut) break; // ---- + if ( prse < m_minPrsE && !m_uncut ) break; // ---- + + const auto hypos = proto->calo(); + const LHCb::CaloHypo* m_electron = NULL; + + for( const auto& hypo: hypos ){ + if ( LHCb::CaloHypo::Hypothesis::EmCharged == hypo->hypothesis() ) m_electron = hypo; + } + + // E/p histogram + if ( m_electron ){ + double eoverp = m_electron->position()->e() / track->p() ; + if (eoverp > 0.){ + const auto clust = *(m_electron->clusters().begin()); + if( clust ){ + const auto cell = clust->seed(); + hFill1( cell, "eop", eoverp ); + } + } + } + } while( false ); + + + // ----------------------------------------------------------------- + // muon histograms + // ----------------------------------------------------------------- + + bool ismuon = (0!= + ( proto->muonPID() + ? ( m_muonLoose ? proto->muonPID()->IsMuonLoose() : proto->muonPID()->IsMuon() ) + : false) + ); + + if ( ismuon || m_uncut ){ + if ( inprs) hFill1( "prsem", prse); + if (inecal) hFill1("ecalem", ecale); + if (inhcal) hFill1("hcalem", hcale); + } + } + return; // StatusCode::SUCCESS; +} diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bfb0cfb189603c43203c31fcc3d8c4e26697ff46 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.cpp @@ -0,0 +1,272 @@ +// Include files +#include "CaloFutureElectronNtp.h" +#include "CaloFutureMoniUtils.h" + + +namespace { + /// hack to allow for tools with non-const interfaces... + template <typename IFace> + IFace* fixup(const ToolHandle<IFace>& iface) { return &const_cast<IFace&>(*iface); } +} +//------------------------------------------------------------------------------ +// Implementation file for class : CaloFutureElectronNtp +// +// 2009-12-11 : Olivier Deschamps +//------------------------------------------------------------------------------ + +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( CaloFutureElectronNtp ) + +//============================================================================== +// Standard constructor, initializes variables +//============================================================================== + +CaloFutureElectronNtp::CaloFutureElectronNtp( const std::string& name, ISvcLocator* pSvcLocator) +: Consumer( name, pSvcLocator, { + KeyValue{ "InputODIN" , LHCb::ODINLocation::Default }, + KeyValue{ "InputContainer", LHCb::ProtoParticleLocation::Charged }, + KeyValue{ "VertexLoc" , LHCb::RecVertexLocation::Primary } +}) {} + +//============================================================================== +// Initialization +//============================================================================== + +StatusCode CaloFutureElectronNtp::initialize(){ + StatusCode sc = Consumer::initialize(); + if ( sc.isFailure() ) return sc; + if ( msgLevel(MSG::DEBUG) ) debug() << "==> Initialize" << endmsg; + if( !m_tracks.empty() )info() << "Will only look at track type(s) = " << m_tracks.value() << endmsg; + else info() << "Will look at any track type" << endmsg; + + // Get, retrieve, configure tools + m_calo = getDet<DeCalorimeter>(DeCalorimeterLocation::Ecal); + if(!( m_counterStat.retrieve() + && m_caloElectron.retrieve() + && m_odin.retrieve() + && m_toSpd.retrieve() + && m_toPrs.retrieve() + && m_extrapolator.retrieve() )){ + error() << "Unable to retrive one of the ToolHandles" << endmsg; + return StatusCode::FAILURE; + } + m_toSpd->setCalos( "Ecal" ,"Spd"); + m_toPrs->setCalos( "Ecal" ,"Prs"); + + // set vertex location + m_vertLoc = inputLocation<2>(); // <-- Careful with the index, 'VertexLoc' is 3rd. + // use fallback if null (forced by user) + if(m_vertLoc == "") + m_vertLoc = m_usePV3D ? LHCb::RecVertexLocation::Velo3D : LHCb::RecVertexLocation::Primary; + updateHandleLocation( *this, "VertexLoc", m_vertLoc ); + + return StatusCode::SUCCESS; +} + +//============================================================================== + +// Warning, not actually a const member function, as it modifies the internal +// state of m_caloElectron. Use with care. +// Note, extra flag count to count at the specific place. Because this method +// is used on both first-electron, and second-electron, the counting should only +// be enabled in the first one only. +bool CaloFutureElectronNtp::set_and_validate( const LHCb::ProtoParticle* proto, bool count ) const { + // abort if fail to set + if( !fixup(m_caloElectron)->set(proto) ) return false; + // counting + if( count && m_counterStat->isQuiet() ) counter("proto electron")+=1; + // abort if no hypo obtained + const auto hypo = fixup(m_caloElectron)->electron(); + if ( hypo == nullptr ) return false; + // abort if null track + const auto track = proto->track(); + if ( track == nullptr ) return false; + // abort if not matching track whitelist + if(!m_tracks.empty()){ + const auto ttype = proto->track()->type(); + if(!std::any_of(m_tracks.begin(), m_tracks.end(), + [ttype](int itype){return itype==ttype;})){ + return false; + } + } + // Abort if poor energy + LHCb::CaloMomentum mmt( hypo ); + const double e = mmt.e(); + const double et= mmt.pt(); + if( !inRange(m_et , et )) return false; + if( !inRange(m_e , e )) return false; + const double ePrs = proto->info(LHCb::ProtoParticle::additionalInfo::CaloPrsE, 0.); + if( !inRange(m_prs, ePrs)) return false; + const double eOp = fixup(m_caloElectron)->eOverP(); + if( !inRange( m_eop, eOp)) return false; + // finally + if( count && m_counterStat->isQuiet() ) counter("Selected electron")+=1; + return true; +} + +// Calculated the squared of the invar mass of two tracks +// The result can be negative. +double CaloFutureElectronNtp::invar_mass_squared( const LHCb::Track* t1, const LHCb::Track* t2 ) const { + auto st1 = t1->firstState(); + auto st2 = t2->firstState(); + auto sc = m_extrapolator->propagate(st1, 0.); + if(sc.isFailure()) Warning("Propagation 1 failed").ignore(); + sc = m_extrapolator->propagate(st2, 0.); + if(sc.isFailure()) Warning("Propagation 2 failed").ignore(); + const auto p1 = st1.momentum(); + const auto p2 = st2.momentum(); + double m2 = p1.R()*p2.R(); + m2 -= p1.X()*p2.X(); + m2 -= p1.Y()*p2.Y(); + m2 -= p1.Z()*p2.Z(); + m2 *= 2; + return m2; +} + +//============================================================================== +// Main execution +//============================================================================== + +void CaloFutureElectronNtp::operator()(const ODIN& odin, const Protos& protos, + const Vertices& verts) const { + + if ( msgLevel(MSG::DEBUG) ) debug() << "==> Execute" << endmsg; + + // GET ODIN INFO + m_odin->getTime(); + ulonglong evt = odin.eventNumber(); + int run = odin.runNumber(); + int tty = odin.triggerType(); + + // Loop over each protoparticle + for( auto p = protos.begin(); protos.end() != p ; ++p ){ + const auto proto = *p; + if(!set_and_validate(proto, true)) continue; + + // Retrieve info for tuple + const auto ePrs = proto->info(LHCb::ProtoParticle::additionalInfo::CaloPrsE, 0.); + const auto track1 = proto->track(); + const auto hypo = fixup(m_caloElectron)->electron(); + const auto iSpd = (int) fixup(m_toSpd)->multiplicity( *hypo , "Spd" ); + const auto track1mmt = momentum(track1); + const auto caloCluster = firstCluster(hypo); + const auto caloCellId = caloCluster->seed(); + const auto caloState = fixup(m_caloElectron)->caloState(); + const auto caloStateMmt = momentum(caloState); + const auto brem = fixup(m_caloElectron)->bremstrahlung(); + const auto bremCellId = firstCluster(brem)->seed(); + const auto bremMmt = momentum(fixup(m_caloElectron)->bremCaloFutureMomentum()); + const auto eOp = fixup(m_caloElectron)->eOverP(); + const auto e = LHCb::CaloMomentum(hypo).e(); + + // dielectron filter + double mas = 999999.; + if( m_pairing ){ + for( auto pp = p+1 ; protos.end () != pp ; ++pp ){ + const auto proto2 = *pp; + if(!set_and_validate(proto2)) continue; + // abort if same pair (shouldn't happen) + const auto hypo2 = fixup(m_caloElectron)->electron(); + if( hypo == hypo2 ) continue; + // Need opposite charge + const auto t1 = proto->track(); + const auto t2 = proto2->track(); + if( -1 != t1->charge()*t2->charge()) continue; + // compute mass + const auto m2 = invar_mass_squared( t1, t2 ); + if(m2 > 0){ + const auto m = sqrt(m2) ; + if(m < mas) mas = m; + } + } + } + if( mas > 0 && mas < 100 && m_counterStat->isQuiet()) counter("Selected (di)electron")+=1; + + // proto info + if(m_tuple){ + auto ntp = nTuple(500, "e_tupling" ,CLID_ColumnWiseTuple); + ntp->column("Spd" , iSpd ); + ntp->column("Prs" , ePrs ); + ntp->column("TrackMatch" , proto->info(LHCb::ProtoParticle::additionalInfo::CaloTrMatch, 9999.)); + ntp->column("ElecMatch" , proto->info(LHCb::ProtoParticle::additionalInfo::CaloElectronMatch, 9999.)); + ntp->column("BremMatch" , proto->info(LHCb::ProtoParticle::additionalInfo::CaloBremMatch, 9999.)); + ntp->column("TrajectoryL", proto->info(LHCb::ProtoParticle::additionalInfo::CaloTrajectoryL, 9999.)); + ntp->column("VeloCharge" , proto->info(LHCb::ProtoParticle::additionalInfo::VeloCharge, -1.)); + ntp->column("DLLe" , proto->info(LHCb::ProtoParticle::additionalInfo::CombDLLe, 0.)); + ntp->column("RichDLLe" , proto->info(LHCb::ProtoParticle::additionalInfo::RichDLLe, 0.)); + // hypo info + ntp->column("EoP" , eOp ); + ntp->column("HypoE" , e ); + ntp->column("HypoR" , position3d(hypo) ); + ntp->column("HypoTheta" , position3d(hypo).theta() ); + // track info + ntp->column("TrackP" , track1mmt); + ntp->column("TrackR" , position3d(caloState)); + ntp->column("caloState" , caloStateMmt); + ntp->column("incidence" , caloStateMmt.theta()); + ntp->column("incidenceX" , atan2(caloStateMmt.X(),caloStateMmt.Z())); + ntp->column("incidenceY" , atan2(caloStateMmt.Y(),caloStateMmt.Z())); + ntp->column("trackType" , track1->type()); + ntp->column("trackProb" , track1->probChi2()); + // cluster info + ntp->column("id" , caloCellId.index()); + ntp->column("ClusterE" , caloCluster->e()); + ntp->column("ClusterR" , position3d(caloCluster) ); + // brem info + ntp->column("BremId" , bremCellId.index()); + ntp->column("BremP" , bremMmt ); + // odin info + ntp->column("run" , run ); + ntp->column("event" , (double) evt ); + ntp->column("triggertype", tty ); + if(m_pairing) ntp->column("MinMee" , mas); + ntp->write(); + } + + // histogramming / channel + const auto trmatch = proto->info(LHCb::ProtoParticle::additionalInfo::CaloTrMatch, 9999.); + if(m_histo && iSpd != 0 && trmatch < 25){ + fillH( eOp, track1mmt, caloCellId ); + if( m_pairing && mas >0. && mas < 100. ) fillH( eOp, track1mmt, caloCellId, "conversion/" ); + } + + // vertices + const auto nVert = verts.size(); + if(m_counterStat->isQuiet()) counter("#PV="+ Gaudi::Utils::toString(nVert) + " ["+ m_vertLoc+"]")+=1; + + if( m_trend ){ + std::string sNpv = "PV" + Gaudi::Utils::toString( nVert ) +"/"; + std::string sRun = "r" + Gaudi::Utils::toString( run ) +"/"; + std::string base = "Trend/"; + plot1D(eOp, base+"allPV/allRun/eOp","e/p spectrum for all run & allPV" , 0. , 2.5, 250); + plot1D(eOp, base+"allPV/"+sRun+"eOp","e/p spectrum for run = "+sRun , 0. , 2.5, 250); + plot1D(eOp, base+sNpv+sRun+"eOp","e/p spectrum for PV="+sNpv+" (run = "+sRun+")", 0. , 2.5, 250); + plot1D(eOp, base+sNpv+"allRun/eOp","e/p spectrum for PV="+sNpv+" (all run)" , 0. , 2.5, 250); + } + } + return; +} +//============================================================================= + +void CaloFutureElectronNtp::fillH(double eOp, Gaudi::LorentzVector t, LHCb::CaloCellID id,std::string hat) const { + if(!m_histo) return; + std::string zone=id.areaName(); + plot1D(eOp, hat+"all/eOp" , "all/eOp" , 0., 3., 300); + plot1D(eOp, hat+zone+"/eOp", zone+"/eOp", 0., 3., 300); + if( m_splitFEBs ){ + std::ostringstream sid; + int feb = m_calo->cardNumber( id ); + sid << hat << "crate" << format("%02i", m_calo->cardCrate( feb ) ) << "/" + << "feb" << format( "%02i" , m_calo->cardSlot( feb ) )<< "/" + <<Gaudi::Utils::toString( m_calo->cardColumn( id ) + nColCaloCard * m_calo->cardRow( id ) ); + plot1D(eOp, sid.str() , sid.str() , 0., 3., 300); + } + if( m_splitE && t.P() < 200. * Gaudi::Units::GeV ){ // put a limit at 200 GeV + int ebin=( t.P() / 5000.)*5; // 1 GeV binning + std::ostringstream sid ; + sid << "/E_"<< ebin<<"/eOp"; + if(m_counterStat->isQuiet()) counter(sid.str()+"[<p>]") += t.P(); + plot1D(eOp, hat+zone+sid.str() , zone+sid.str() , 0., 3., 300); + plot1D(eOp, hat+"all"+sid.str(), "all"+sid.str(), 0., 3., 300); + } +} diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.h b/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.h new file mode 100644 index 0000000000000000000000000000000000000000..27d9b4831363765a2e4b06a7c488cf1d7f28ec25 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureElectronNtp.h @@ -0,0 +1,79 @@ +#ifndef CALOFUTUREELECTRONNTP_H +#define CALOFUTUREELECTRONNTP_H 1 + +// Include files +#include "GaudiAlg/Consumer.h" +#include "GaudiAlg/GaudiTupleAlg.h" +#include "GaudiKernel/IEventTimeDecoder.h" +#include "Event/ODIN.h" +#include "Event/ProtoParticle.h" +#include "Event/RecVertex.h" +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureInterfaces/ICaloFutureHypo2CaloFuture.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" +#include "CaloFutureUtils/ICaloFutureElectron.h" +#include "TrackInterfaces/ITrackExtrapolator.h" + +// List of Consumers dependencies +namespace { + using ODIN = LHCb::ODIN; + using Protos = LHCb::ProtoParticles; + using Vertices = LHCb::RecVertices; +} + +//============================================================================== + +/** @class CaloFutureElectronNtp CaloFutureElectronNtp.h + * + * + * @author Olivier Deschamps + * @date 2009-12-11 + */ +class CaloFutureElectronNtp final +: public Gaudi::Functional::Consumer<void(const ODIN&, const Protos&, const Vertices&), + Gaudi::Functional::Traits::BaseClass_t<GaudiTupleAlg>> +{ +public: + CaloFutureElectronNtp( const std::string& name, ISvcLocator* pSvcLocator ); + StatusCode initialize() override; + void operator()(const ODIN&, const Protos&, const Vertices&) const override; + + /// C++11 non-copyable idiom + CaloFutureElectronNtp() = delete; + CaloFutureElectronNtp( const CaloFutureElectronNtp& ) = delete; + CaloFutureElectronNtp &operator=( const CaloFutureElectronNtp& ) = delete; + +private: + DeCalorimeter* m_calo = nullptr; + std::string m_vertLoc; + + ToolHandle<IFutureCounterLevel> m_counterStat { "FutureCounterLevel" }; + ToolHandle<ICaloFutureElectron> m_caloElectron { "CaloFutureElectron" , this }; + ToolHandle<IEventTimeDecoder> m_odin { "OdinTimeDecoder/OdinDecoder" , this }; + ToolHandle<ICaloFutureHypo2CaloFuture> m_toSpd { "CaloFutureHypo2CaloFuture/CaloFutureHypo2Spd" , this }; + ToolHandle<ICaloFutureHypo2CaloFuture> m_toPrs { "CaloFutureHypo2CaloFuture/CaloFutureHypo2Prs" , this }; + ToolHandle<ITrackExtrapolator> m_extrapolator { "TrackRungeKuttaExtrapolator/Extrapolator", this }; + + Gaudi::Property<std::pair<double, double>> m_e { this, "EFilter" , { 0. , 99999999}}; + Gaudi::Property<std::pair<double, double>> m_et { this, "EtFilter" , { 200., 999999.}}; + Gaudi::Property<std::pair<double, double>> m_prs { this, "PrsFilter", { 50. , 9999999.}}; + Gaudi::Property<std::pair<double, double>> m_eop { this, "EoPFilter", { 0. , 2.5}}; + + Gaudi::Property<bool> m_pairing {this, "ElectronPairing", true}; + Gaudi::Property<bool> m_histo {this, "Histo", true}; + Gaudi::Property<bool> m_tuple {this, "Tuple", true}; + Gaudi::Property<bool> m_trend {this, "Trend", false}; + Gaudi::Property<bool> m_usePV3D {this, "UsePV3D", false}; + Gaudi::Property<bool> m_splitFEBs{this, "splitFEBs", false}; + Gaudi::Property<bool> m_splitE {this, "splitE", false}; + + Gaudi::Property<std::vector<int>> m_tracks + {this, "TrackTypes", {LHCb::Track::Types::Long, LHCb::Track::Types::Downstream}}; + + bool set_and_validate( const LHCb::ProtoParticle* proto, bool count=false ) const; + double invar_mass_squared( const LHCb::Track* t1, const LHCb::Track* t2 ) const; + void fillH(double eOp,Gaudi::LorentzVector t, LHCb::CaloCellID id,std::string hat="") const; + +}; + +#endif // CALOFUTUREELECTRONNTP_H diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoMatchMonitor.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoMatchMonitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f0645fff126c94c731823ab12ce553da064e4d7e --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoMatchMonitor.cpp @@ -0,0 +1,126 @@ +// Includes +#include "GaudiAlg/Consumer.h" +#include "Relations/RelationWeighted2D.h" +#include "Event/CaloHypo.h" +#include "Event/Track.h" +#include "CaloFutureMoniAlg.h" + +// ============================================================================= + +/** @class CaloFutureHypoMatchMonitor CaloFutureHypoMatchMonitor.cpp + * + * The algorithm for trivial monitoring of matching of + * "CaloFutureClusters" with Tracks. + * It produces 5 histograms: + * + * <ol> + * <li> @p log10(#Relations+1) distribution </li> + * <li> Link multiplicity distribution </li> + * <li> Minimal Weight distribution </li> + * <li> Maximal Weight distribution </li> + * <li> Weight distribution </li> + * </ol> + * + * Histograms reside in the directory @p /stat/"Name" , where + * @ "Name" is the name of the algorithm + * + * @see CaloFutureMoniAlg + * @see GaudiHistoAlg + * @see GaudiAlgorithm + * @see Algorithm + * @see IAlgorithm + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 02/11/2001 + */ + +using Input = LHCb::RelationWeighted2D< LHCb::CaloHypo, LHCb::Track, float >; +using Inputs = LHCb::CaloHypo::Container; + +class CaloFutureHypoMatchMonitor final +: public Gaudi::Functional::Consumer<void(const Input&, const Inputs&), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureMoniAlg>> +{ +public: + StatusCode initialize() override; + void operator()(const Input&, const Inputs&) const override; + + CaloFutureHypoMatchMonitor( const std::string &name, ISvcLocator *pSvcLocator ); +}; + +// ============================================================================= + +DECLARE_COMPONENT( CaloFutureHypoMatchMonitor ) + +// ============================================================================= + +CaloFutureHypoMatchMonitor::CaloFutureHypoMatchMonitor( const std::string &name, ISvcLocator *pSvcLocator ) +: Consumer( name, pSvcLocator, { + KeyValue{ "Input" , "" }, + KeyValue{ "Inputs", "" } +}){ + /* + * During genconf.exe, the default name "DefaultName" is not well-supported + * by the CaloFutureAlgUtils, returning the null string "" as a location path, + * which will raise exception in `updateHandleLocation` --> `setProperty`. + * To get around this, the location will only be updated outside the genconf. + */ + if( name != "DefaultName" ){ + const auto Input = LHCb::CaloFutureAlgUtils::CaloFutureIdLocation(name, context()); + const auto Inputs = LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation(name, context()); + updateHandleLocation( *this, "Input" , Input ); + updateHandleLocation( *this, "Inputs", Inputs ); + } +} + +// ============================================================================= + +/// standard algorithm initialization +StatusCode CaloFutureHypoMatchMonitor::initialize(){ + StatusCode sc = Consumer::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; // error already printedby GaudiAlgorithm + std::string common = "'" + inputLocation() + "' " + name(); + hBook1( "1", "log10(#Links+1) " + common, 0, 4, 100 ); + hBook1( "2", "Rels per Hypo " + common, 0, 25, 50 ); + hBook1( "3", "Min weight " + common, 0, 100, 200 ); + hBook1( "4", "Max weight " + common, 0, 1000, 200 ); + hBook1( "5", "Weights " + common, 0, 1000, 500 ); + if( m_split ){ + Warning( "No area spliting allowed for CaloFutureHypoMatchMonitor").ignore(); + m_split = false; + } + return StatusCode::SUCCESS; +} + +// ============================================================================= +// standard execution method +// ============================================================================= + +void CaloFutureHypoMatchMonitor::operator()(const Input& table, const Inputs& hypos) const { + + if ( !produceHistos() ) return; + + // logarithm of ( total number of links + 1 ) + hFill1( "1", log10( table.relations().size() + 1. ) ); + + // loop over all hypos + for( const auto& hypo: hypos ){ + const auto range = table.relations( hypo ); + // number of related tracks + hFill1( "2", range.size() ); + if ( range.empty() ) continue; + // minimal weight + hFill1( "3", range.front().weight() ); + // maximal weight + hFill1( "4", range.back().weight() ); + // all weights + for( const auto& relation: range ){ + hFill1( "5", relation.weight() ); + } + } // end of loop over hypos + + if( m_counterStat->isQuiet()) counter("Monitor " + inputLocation<1>()) += hypos.size(); + if( m_counterStat->isQuiet()) counter("Monitor " + inputLocation() ) += table.relations().size(); + + return; +} diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoMonitor.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoMonitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6ae6e2e9bc9009a59ccf0b37b8e46740415285ea --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoMonitor.cpp @@ -0,0 +1,183 @@ +// Includes +#include "GaudiAlg/Consumer.h" +#include "Event/CaloHypo.h" +#include "Event/CaloDataFunctor.h" +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureUtils/CaloMomentum.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "CaloFutureMoniAlg.h" + +// ============================================================================= + +/** @class CaloFutureHypoMonitor CaloFutureHypoMonitor.cpp + * + * The algorithm for trivial monitoring of "CaloHypo" container + * The algorithm produces 10 histograms: + * <ol> + * <li> @p CaloHypo multiplicity </li> + * <li> @p CaloHypo energy distribution </li> + * <li> @p CaloHypo transverse momentum distribution </li> + * <li> @p CaloHypo mass distribution </li> + * <li> @p CaloHypo x distribution </li> + * <li> @p CaloHypo y distribution </li> + * <li> multiplicity of @p CaloCluster per @p CaloHypo </li> + * <li> multiplicity of Spd @p CaloDigit per @p CaloHypo </li> + * <li> multiplicity of Prs @p CaloDigit per @p CaloHypo </li> + * <li> CaloHypo x vs y distribution </li> + * </ol> + * Histograms reside in the directory @p /stat/"Name" , where + * @ "Name" is the name of the algorithm + * + * @see CaloFutureAlgorithm + * @see Algorithm + * @see IAlgorithm + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 02/11/2001 + */ + +using Input = LHCb::CaloHypo::Container; + +class CaloFutureHypoMonitor final +: public Gaudi::Functional::Consumer<void(const Input&, const LHCb::CaloClusters&), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureMoniAlg>> +{ +public: + /// standard algorithm initialization + StatusCode initialize() override; + void operator()(const Input&, const LHCb::CaloClusters&) const override; + + CaloFutureHypoMonitor( const std::string &name, ISvcLocator *pSvcLocator ); + +private: + Gaudi::Property<int> m_clusBin { this, "NClusterBin", 5 }; + Gaudi::Property<float> m_clusMax { this, "NClusterMax", 5.}; + Gaudi::Property<float> m_clusMin { this, "NClusterMin", 0.}; + Gaudi::Property<int> m_spdBin { this, "NSpdBin" , 10 }; + Gaudi::Property<float> m_spdMax { this, "NSpdMax" , 10.}; + Gaudi::Property<float> m_spdMin { this, "NSpdMin" , 0. }; + Gaudi::Property<int> m_prsBin { this, "NPrsBin" , 10 }; + Gaudi::Property<float> m_prsMax { this, "NPrsMax" , 10.}; + Gaudi::Property<float> m_prsMin { this, "NPrsMin" , 0. }; +}; + +DECLARE_COMPONENT( CaloFutureHypoMonitor ) + +// ============================================================================= + +CaloFutureHypoMonitor::CaloFutureHypoMonitor( const std::string &name, ISvcLocator *pSvcLocator ) +: Consumer( name, pSvcLocator, { + KeyValue{ "Input" , "" }, + KeyValue{ "InputClusters", "" }, + } +){ + m_multMax = 250; + m_multBin = 50; + + /* + * During genconf.exe, the default name "DefaultName" is not well-supported + * by the CaloFutureAlgUtils, returning the null string "" as a location path, + * which will raise exception in `updateHandleLocation` --> `setProperty`. + * To get around this, the location will only be updated outside the genconf. + */ + if( name != "DefaultName" ){ + const auto InputData = LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation(name,context()); + const auto InputClusters = LHCb::CaloFutureAlgUtils::CaloFutureClusterLocation(name,context()); + updateHandleLocation( *this, "Input", InputData ); + updateHandleLocation( *this, "InputClusters", InputClusters ); + } +} + +// ============================================================================= + +/// standard algorithm initialization +StatusCode CaloFutureHypoMonitor::initialize(){ + StatusCode sc = Consumer::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; // error already printedby GaudiAlgorithm + hBook1( "1", "# of Hypos " + inputLocation(), m_multMin , m_multMax , m_multBin ); + hBook1( "2", "Hypo Energy " + inputLocation(), m_energyMin , m_energyMax, m_energyBin ); + hBook1( "3", "Hypo Pt " + inputLocation(), m_etMin , m_etMax , m_etBin ); + if( inputLocation() == "Rec/Calo/MergedPi0s" || inputLocation() == "Hlt/Calo/MergedPi0s" ) + hBook1("4", "Hypo Mass " + inputLocation(), m_massMin , m_massMax , m_massBin ); + hBook1( "5", "Hypo X " + inputLocation(), m_xMin , m_xMax , m_xBin ); + hBook1( "6", "Hypo Y " + inputLocation(), m_yMin , m_yMax , m_yBin ); + hBook1( "7", "Clusters/Hypo " + inputLocation(), m_clusMin , m_clusMax , m_clusBin ); + hBook1( "8", "Spd/Hypo " + inputLocation(), m_spdMin , m_spdMax , m_spdBin ); + hBook1( "9", "Prs/Hypo " + inputLocation(), m_prsMin , m_prsMax , m_prsBin ); + hBook2( "10", "Hypo barycenter position x vs y " + inputLocation(), m_xMin, m_xMax, m_xBin, m_yMin, m_yMax, m_yBin); + hBook2( "11", "Energy-weighted hypo barycenter position x vs y " + inputLocation(), m_xMin,m_xMax, m_xBin, m_yMin, m_yMax, m_yBin); + hBook1( "14", "#Hypo/#Cluster" + inputLocation(), 0., 1.,100); + return StatusCode::SUCCESS; +} + +// ============================================================================= +// standard execution method +// ============================================================================= + +void CaloFutureHypoMonitor::operator()(const Input& hypos, const LHCb::CaloClusters& clusters) const { + // produce histos ? + if ( !produceHistos() ) return; + + // check data + if( hypos.empty() ){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Empty hypos found in" << inputLocation() << endmsg; + return; + } + + // get functor + LHCb::CaloDataFunctor::DigitFromCalo spd( DeCalorimeterLocation::Spd ); + LHCb::CaloDataFunctor::DigitFromCalo prs( DeCalorimeterLocation::Prs ); + + initFutureCounters(); + + // Start looping over hypo + for( const auto& hypo: hypos ){ + LHCb::CaloMomentum momentum( hypo ); + const double e = momentum.e(); + const double et= momentum.pt(); + const double mass=momentum.momentum().mass(); + if(e < m_eFilter) continue; + if(et < m_etFilter) continue; + if(mass < m_massFilterMin || mass > m_massFilterMax) continue; + auto id = LHCb::CaloCellID(); + if( hypo->clusters().size() > 0 ){ + const auto cluster = *(hypo->clusters().begin()); + if( 0 != cluster) id = cluster->seed(); + } + + // Start filling histo + count(id); + hFill1(id, "2", e ); + hFill1(id, "3", et ); + if( inputLocation() == "Rec/Calo/MergedPi0s" || inputLocation() == "Hlt/Calo/MergedPi0s" )hFill1(id, "4", mass ); + + const auto position = hypo->position(); + if( position != nullptr ){ + hFill1(id, "5", position->x() ); + hFill1(id, "6", position->y() ); + hFill2(id, "10", position->x(),position->y() ); + hFill2(id, "11", position->x(),position->y() , e); + } + + const auto digits = hypo->digits(); + hFill1(id, "7", hypo->clusters().size() ); + hFill1(id, "8", std::count_if( digits.begin(), digits.end(), spd ) ); + hFill1(id, "9", std::count_if( digits.begin(), digits.end(), prs ) ); + + if( !(id == LHCb::CaloCellID()) ){ + if(doHisto("12"))fillCaloFuture2D("12", id , 1. , "Hypo position 2Dview " + inputLocation() ); + if(doHisto("13"))fillCaloFuture2D("13", id , e , "Hypo Energy 2Dview " + inputLocation() ); + } + + } + // fill multiplicity histogram + fillFutureCounters("1"); + + //cluster fraction (no area-splittable so far) + const int nClus = clusters.size(); + const double frac = nClus>0 ? (double) m_count / (double) nClus : 0.; + hFill1("14",frac); + + return; +} diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoNtp.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoNtp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ccc04f844a4194b9f961ff5b669481898cdd4a27 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoNtp.cpp @@ -0,0 +1,180 @@ +// Include files +// from Gaudi +#include "Event/MCParticle.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "CaloFutureUtils/CaloMomentum.h" +// locals +#include "CaloFutureHypoNtp.h" +#include "CaloFutureMoniUtils.h" + +namespace { + /// hack to allow for tools with non-const interfaces... + template <typename IFace> + IFace* fixup(const ToolHandle<IFace>& iface) { return &const_cast<IFace&>(*iface); } +} +// ============================================================================= + +DECLARE_COMPONENT( CaloFutureHypoNtp ) + +// ============================================================================= + +CaloFutureHypoNtp::CaloFutureHypoNtp( const std::string &name, ISvcLocator *pSvcLocator ) +: Consumer( name, pSvcLocator, { + KeyValue{ "InputODIN", LHCb::ODINLocation::Default }, + KeyValue{ "InputL0" , LHCb::L0DUReportLocation::Default }, + KeyValue{ "Locations", "" }, + KeyValue{ "TrackLoc" , LHCb::TrackLocation::Default }, + KeyValue{ "VertexLoc", LHCb::RecVertexLocation::Primary } +}) +{} + +// ============================================================================= + +StatusCode CaloFutureHypoNtp::initialize(){ + StatusCode sc = Consumer::initialize(); + if ( sc.isFailure() ) return sc; + // retrieve tools + if(!( m_2MC.retrieve() + && m_counterStat.retrieve() + && m_estimator.retrieve() )){ + error() << "Unable to retrive one of the ToolHandles" << endmsg; + return StatusCode::FAILURE; + } + + // Configure tool + std::string seed = m_seed ? "true" : "false"; + std::string line = m_extrapol ? "true" : "false"; + std::string neig = m_neig ? "true" : "false"; + m_estimator->hypo2CaloFuture()->_setProperty("Seed", seed).ignore(); + m_estimator->hypo2CaloFuture()->_setProperty("PhotonLine", line).ignore(); + m_estimator->hypo2CaloFuture()->_setProperty("AddNeighbors", neig).ignore(); + + // Configure input locations + using namespace LHCb::CaloHypoLocation; + // get the user-override input + auto loc = inputLocation<2>(); // <-- Careful with the index, 'Location' is 3rd. + std::vector<std::string> m_locs{}; + if( loc != "" ) m_locs.push_back(loc); + // get the respective input from Hypos + for( const auto h: m_hypos ){ + if(h == "Photons") m_locs.push_back( LHCb::CaloFutureAlgUtils::PathFromContext( context() , Photons )); + else if(h == "Electrons") m_locs.push_back( LHCb::CaloFutureAlgUtils::PathFromContext( context() , Electrons )); + else if(h == "MergedPi0s") m_locs.push_back( LHCb::CaloFutureAlgUtils::PathFromContext( context() , MergedPi0s )); + else if(h == "SplitPhotons")m_locs.push_back( LHCb::CaloFutureAlgUtils::PathFromContext( context() , SplitPhotons )); + } + // Finally, update handle + updateHandleLocation( *this, "Locations", boost::algorithm::join(m_locs,"&")); + + return StatusCode::SUCCESS; +} + + +// ============================================================================= +// standard execution method +// ============================================================================= + +void CaloFutureHypoNtp::operator()(const ODIN& odin, const L0& l0, const Hypos& hypos, + const Tracks& tracks, const Vertices& verts) const { + + using namespace CaloFutureDataType; + + // declare tuple + Tuple ntp = (!m_tupling) ? Tuple{nullptr} : nTuple(500, "HypoNtp", CLID_ColumnWiseTuple); + + // Collect global info (in pre-Functional implementation, some are optionals) + const auto run = odin.runNumber(); + const auto evt = (double) odin.eventNumber(); + const auto tty = odin.triggerType(); + const auto nSpd = (int) l0.dataValue("Spd(Mult)"); + const auto nTrack = tracks.size(); + const auto nVert = verts.size(); + + // loop over hypo containers + bool ok = true; + for( const auto& hypo: hypos ){ + // hypo string + std::ostringstream type(""); + type << hypo->hypothesis(); + std::string hypothesis = type.str(); + + // filtering hypo + if( !inRange( m_et , fixup(m_estimator)->data( hypo, HypoEt , 0. ))) continue; + if( !inRange( m_e , fixup(m_estimator)->data( hypo, HypoE , 0. ))) continue; + if( !inRange( m_spdM , fixup(m_estimator)->data( hypo, HypoSpdM, 0. ))) continue; + if( !inRange( m_prsE , fixup(m_estimator)->data( hypo, HypoPrsE, 0. ))) continue; + + // MC-associated filtering + if( m_checker ){ + const auto mcp = fixup(m_2MC)->from(hypo)->bestMC(); + if( mcp == nullptr ) continue; + if( m_mcID >= 0 && (int) mcp->particleID().abspid() != m_mcID) continue; + } + + // PrintOut + if ( m_print ){ + info() << "+++ Run/Evt " << run << "/" << evt << endmsg; + info() << " === hypothesis " << hypo->hypothesis() << "(" << tesLocation(hypo) << ")" << endmsg; + if( m_checker ) fixup(m_2MC)->from(hypo)->descriptor(); + } + + // DataTypes statistics + for( int i = 0 ; i < CaloFutureDataType::Last ; ++i){ + const auto val = fixup(m_estimator)->data( hypo, (DataType) i, 0. ); + if(m_stat && m_counterStat->isQuiet()) counter( Name[i] + " for " + hypothesis ) += val; + if(m_tupling) ok &= ntp->column( Name[i], val ); + if(m_print) info() << " --> " << Name[i] << " : " << val << endmsg; + } + + // Tupling + if( m_tupling){ + + // hypothesis + ok &= ntp->column( "hypothesis", hypo->hypothesis() ); + + // kinematics + const auto cluster = fixup(m_estimator)->toCluster(CaloFutureClusterType::SplitOrMain); + ok &= ntp->column( "ClusterR" , position3d(cluster) ); + ok &= ntp->column( "HypoR" , position3d(hypo) ); + ok &= ntp->column( "HypoP" , momentum(hypo) ); + + // matched tracks + for( int match = 0 ; match < CaloFutureMatchType::Last ; ++match){ + const auto track = fixup(m_estimator)->toTrack( (CaloFutureMatchType::MatchType) match ); + ok &= ntp->column( CaloFutureMatchType::Name[match] + "TrackP" , momentum(track) ); + } + + // odin info + ok &= ntp->column("Run" , run ); + ok &= ntp->column("Event" , evt ); + ok &= ntp->column("Triggertype", tty ); + ok &= ntp->column("Nvertices" , nVert ); + ok &= ntp->column("NTracks" , nTrack); + ok &= ntp->column("spdMult" , nSpd ); + + // Checker Mode (MC info) + if( m_checker ){ + int id = -999; + double weight = -999; + double quality = -999; + const auto mcp = fixup(m_2MC)->from(hypo)->bestMC(); + if( mcp != nullptr ){ + id = mcp->particleID().pid(); + weight = fixup(m_2MC)->from(hypo)->weight( mcp ); + quality= fixup(m_2MC)->from(hypo)->quality( mcp ); + } + ok &= ntp->column( "MCid", id ); + ok &= ntp->column( "MCw" , weight ); + ok &= ntp->column( "MCq" , quality ); + } + ok &= ntp->write(); + } + } + + // Finally, report + if(ok){ + if(m_counterStat->isQuiet()) counter("Events in tuple") += 1; + } else { + Warning("Error with ntupling", StatusCode::SUCCESS).ignore(); + } + return; +} diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoNtp.h b/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoNtp.h new file mode 100644 index 0000000000000000000000000000000000000000..c05309e974c4de57fa783855d40ee44635d36f8d --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureHypoNtp.h @@ -0,0 +1,59 @@ +#ifndef CALOFUTUREHYPONTP_H +#define CALOFUTUREHYPONTP_H 1 + +#include "GaudiAlg/Consumer.h" +#include "GaudiAlg/GaudiTupleAlg.h" +#include "GaudiKernel/IEventTimeDecoder.h" +#include "Event/CaloHypo.h" +#include "Event/L0DUReport.h" +#include "Event/ODIN.h" +#include "Event/RecVertex.h" +#include "CaloFutureInterfaces/ICaloFutureHypoEstimator.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" +#include "CaloFutureInterfaces/ICaloFuture2MCTool.h" + +// List of Consumers dependencies +namespace { + using ODIN = LHCb::ODIN; + using L0 = LHCb::L0DUReport; + using Hypos = LHCb::CaloHypo::Container; + using Tracks = LHCb::Tracks; + using Vertices = LHCb::RecVertices; +} + +// ============================================================================ + +class CaloFutureHypoNtp final +: public Gaudi::Functional::Consumer<void(const ODIN&, const L0&, const Hypos&, const Tracks&, const Vertices&), + Gaudi::Functional::Traits::BaseClass_t<GaudiTupleAlg>> +{ +public: + CaloFutureHypoNtp( const std::string& name, ISvcLocator* pSvcLocator ); + StatusCode initialize() override; + void operator()(const ODIN&, const L0&, const Hypos&, const Tracks&, const Vertices&) const override; + +private: + ToolHandle<ICaloFuture2MCTool> m_2MC = {"CaloFuture2MCTool", this}; + ToolHandle<IFutureCounterLevel> m_counterStat = {"FutureCounterLevel"}; + ToolHandle<ICaloFutureHypoEstimator> m_estimator = {"CaloFutureHypoEstimator", this}; + + Gaudi::Property<bool> m_extrapol { this, "Extrapolation", true}; + Gaudi::Property<bool> m_seed { this, "AddSeed" , false}; + Gaudi::Property<bool> m_neig { this, "AddNeighbors" , false}; + + Gaudi::Property<std::pair<double,double>> m_et {this, "RangePt" , {100., 15000. }}; + Gaudi::Property<std::pair<double,double>> m_e {this, "RangeE" , {0. , 5000000 }}; + Gaudi::Property<std::pair<double,double>> m_spdM {this, "RangeSpdM", {0. , 5000000.}}; + Gaudi::Property<std::pair<double,double>> m_prsE {this, "RangePrsE", {0. , 9999. }}; + + Gaudi::Property<std::vector<std::string>> m_hypos + {this, "Hypos", {"Electrons", "Photons", "MergedPi0s"}}; + + Gaudi::Property<bool> m_tupling { this, "Tupling" , true}; + Gaudi::Property<bool> m_checker { this, "CheckerMode", false}; + Gaudi::Property<bool> m_print { this, "Printout" , false}; + Gaudi::Property<bool> m_stat { this, "Statistics" , true}; + Gaudi::Property<int> m_mcID { this, "MCID" , -99999999}; + +}; +#endif // CALOFUTUREHYPONTP_H diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureMoniAlg.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureMoniAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fbd9b0928d7c17fc85cf601876614bf8f001e7d1 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureMoniAlg.cpp @@ -0,0 +1,354 @@ +// Includes +#include "CaloFutureMoniAlg.h" + +//------------------------------------------------------------------------------ +// Implementation file for class : CaloFutureMoniAlg +// +// 2008-09-03 : Olivier Deschamps +//------------------------------------------------------------------------------ + +//============================================================================== +// Standard constructor, initializes variables +//============================================================================== + +CaloFutureMoniAlg::CaloFutureMoniAlg( const std::string& name, ISvcLocator* pSvcLocator ) +: CaloFuture2Dview( name, pSvcLocator ) +{ + // Areas + m_mcount.reserve(m_nAreas); + m_scount.reserve(2); + + //set default detectorName + m_detData = LHCb::CaloFutureAlgUtils::CaloFutureNameFromAlg( name ); + if ( m_detData == "Prs" ) + m_energyMax = 300.* Gaudi::Units::MeV; + if ( m_detData == "Spd" ) + m_energyMax = 10.* Gaudi::Units::MeV; +} + +//============================================================================== +// Initialization +//============================================================================== + +StatusCode CaloFutureMoniAlg::initialize() { + StatusCode sc = CaloFuture2Dview::initialize(); + if ( sc.isFailure() ) return sc; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "==> Initialize" << endmsg; + + m_counterStat.retrieve().ignore(); + if("" == histoTopDir()) setHistoTopDir("CaloFutureMoniDst/"); + + if( m_split && m_splitSides ){ + warning() << "Cannot split simultaneously the calo sides and areas, so far - Area splitting wins" << endmsg; + m_splitSides=false; + } + return StatusCode::SUCCESS; +} + +//============================================================================== + +void CaloFutureMoniAlg::initFutureCounters() const { + m_count = 0; + for(unsigned int i = 0; i != m_nAreas ; ++i){ + m_mcount[i]=0; + } + for(unsigned int i = 0; i <2 ; ++i){ + m_scount[i]=0; + } +} + +//============================================================================== + +void CaloFutureMoniAlg::count(LHCb::CaloCellID id) const { + m_count++; + if( !(id == LHCb::CaloCellID()) ){ + int area = id.area(); + m_mcount[area]++; + int col = id.col(); + int side = 1; + if( CaloCellCode::CaloNameFromNum(id.calo()) == "Hcal"){ + if(col<16)side = 0; + } + else if(col<32){ + side = 0; + } + m_scount[side]++; + } +} + +//============================================================================== + +void CaloFutureMoniAlg::fillFutureCounters(std::string unit) const { + fill(m_h1[unit], m_count , 1); + + // Source monitor. Fetch from "Input" field if existed. + // This required consistent naming across its functional children. + std::string cname{"Monitor"}; + if(hasProperty("Input")) + cname += " "+getProperty("Input").toString(); + if( m_counterStat->isQuiet()) counter(cname) += m_count; + + // Split monitor + if( m_splitSides ){ + for(unsigned int i = 0;i < 2 ;++i){ + std::string side = (i==0) ? "C-side" : "A-side"; + if( m_scount[i] == 0 ) continue; + GaudiAlg::HistoID id(side + "/"+unit); + fill(m_h1[id], m_scount[i] , 1); + if( m_counterStat->isQuiet()) counter("Monitor (" + side +")" ) += m_scount[i]; + } + } else if( m_split ){ + for(unsigned int i = 0;i != m_nAreas;++i){ + //std::string area = CaloFutureCellCode::CaloFutureAreaFromNum( CaloFutureCellCode::CaloFutureNumFromName( m_detData ), i ); + std::string area = CaloCellCode::caloArea ( CaloCellCode::caloNum ( m_detData ), i ); + if( !validArea( area )|| m_mcount[i] == 0) continue; + GaudiAlg::HistoID id(area + "/"+unit); + fill(m_h1[id], m_mcount[i] , 1); + if( m_counterStat->isQuiet()) counter("Monitored (" + area +")" ) += m_mcount[i]; + } + } +} + +//============================================================================== +// BOOKINGS +//============================================================================== + +void CaloFutureMoniAlg::hBook1( const std::string hid, + const std::string titl, + const double low, + const double high, + const unsigned long bins ){ + if(!doHisto(hid)) return; + + if( m_splitSides ){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Booking histogram1D per calo side" << endmsg; + for(unsigned int i = 0;i <2 ;++i){ + std::string side = (i==0) ? "C-side" : "A-side"; + GaudiAlg::HistoID id(side + "/" + hid); + std::string tit = titl + " (" + side + ")"; + m_h1[id] = book1D( id, tit, low, high, bins ); + } + } + else if(m_split){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Booking histogram1D per calo area" << endmsg; + for(unsigned int i = 0;i != m_nAreas;++i){ + // std::string area = CaloFutureCellCode::CaloFutureAreaFromNum( CaloFutureCellCode::CaloFutureNumFromName( m_detData ), i ); + std::string area = CaloCellCode::caloArea ( CaloCellCode::caloNum( m_detData ), i ); + if( !validArea( area )) continue; + GaudiAlg::HistoID id(area + "/" + hid); + std::string tit = titl + " (" + area + ")"; + m_h1[id] = book1D( id, tit, low, high, bins ); + } + } + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Booking histogram1D for whole calo" << endmsg; + m_h1[hid] = book1D( hid, titl, low, high, bins ); +} + +//============================================================================== + +void CaloFutureMoniAlg::h1binLabel( const std::string hid, int bin, std::string label ) const { + if(!doHisto(hid)) return; + + if( m_splitSides ){ + for(unsigned int i = 0;i <2 ;++i){ + std::string side = (i==0) ? "C-side" : "A-side"; + GaudiAlg::HistoID id(side + "/" + hid); + const auto th = Gaudi::Utils::Aida2ROOT::aida2root( m_h1[id] ); + th->GetXaxis()->SetBinLabel( bin , label.c_str() ); + } + } + else if(m_split){ + for(unsigned int i = 0;i != m_nAreas;++i){ + // std::string area = CaloFutureCellCode::CaloFutureAreaFromNum( CaloFutureCellCode::CaloFutureNumFromName( m_detData ), i ); + std::string area = CaloCellCode::caloArea ( CaloCellCode::caloNum( m_detData ), i ); + if( !validArea( area )) continue; + GaudiAlg::HistoID id(area + "/" + hid); + const auto th = Gaudi::Utils::Aida2ROOT::aida2root( m_h1[id] ); + th->GetXaxis()->SetBinLabel( bin , label.c_str() ); + } + } + const auto th = Gaudi::Utils::Aida2ROOT::aida2root( m_h1[hid] ); + th->GetXaxis()->SetBinLabel( bin, label.c_str() ); +} + +//============================================================================== + +void CaloFutureMoniAlg::hBook2( const std::string hid, const std::string titl, + const double lowx, const double highx, const unsigned long binsx, + const double lowy, const double highy, const unsigned long binsy ){ + if(!doHisto(hid)) return; + if( m_splitSides ){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Booking histogram2D per calo side" << endmsg; + for(unsigned int i = 0;i <2 ;++i){ + std::string side = (i==0) ? "C-side" : "A-side"; + GaudiAlg::HistoID id(side + "/" + hid); + std::string tit = titl + " (" + side + ")"; + m_h2[id] = book2D( id, tit, lowx, highx, binsx, lowy, highy, binsy ); + } + } + else if( m_split ){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Booking histogram2D per calo region" << endmsg; + for(unsigned int i = 0;i != m_nAreas;++i){ + std::string area = CaloCellCode::caloArea ( CaloCellCode::caloNum( m_detData ), i ); + if( !validArea( area )) continue; + GaudiAlg::HistoID id(area + "/" + hid); + std::string tit = titl + " (" + area + ")"; + m_h2[id] = book2D( id, tit, lowx, highx, binsx, lowy, highy, binsy ); + } + } + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Booking histogram2D for whole calo" << endmsg; + m_h2[hid] = book2D( hid, titl, lowx, highx, binsx, lowy, highy, binsy ); +} + +//============================================================================== +// FILLING +//============================================================================== + +void CaloFutureMoniAlg::hFill1(std::string hid, double value, double w ) const { + if(!doHisto(hid)) return; + const auto h = m_h1[hid]; + if( h == nullptr ) return; + double bins = (double) h->axis().bins(); + double step = h->axis().upperEdge() - h->axis().lowerEdge(); + step = ( bins == 0) ? 0 : step/bins/2.; + if(m_sat){ + if( value < h->axis().lowerEdge() )value = h->axis().lowerEdge()+step; + if( value > h->axis().upperEdge() )value = h->axis().upperEdge()-step; + } + fill(h,value,w); +} + +void CaloFutureMoniAlg::hFill2(std::string hid, double x, double y, double w ) const { + if(!doHisto(hid)) return; + const auto h = m_h2[hid]; + if( h == nullptr ) return; + double xbins = (double) h->xAxis().bins(); + double xstep = h->xAxis().upperEdge() - h->xAxis().lowerEdge(); + xstep = ( xbins == 0) ? 0 : xstep/xbins/2.; + double ybins = (double) h->yAxis().bins(); + double ystep = h->yAxis().upperEdge() - h->yAxis().lowerEdge(); + ystep = ( ybins == 0) ? 0 : ystep/ybins/2.; + + if(m_sat2D){ + if( x < h->xAxis().lowerEdge() )x = h->xAxis().lowerEdge()+xstep; + if( x > h->xAxis().upperEdge() )x = h->xAxis().upperEdge()-xstep; + if( y < h->yAxis().lowerEdge() )y = h->yAxis().lowerEdge()+ystep; + if( y > h->yAxis().upperEdge() )y = h->yAxis().upperEdge()-ystep; + } + fill(h,x,y,w); +} + +void CaloFutureMoniAlg::hFill1(LHCb::CaloCellID cellID , std::string hid, double value, double w ) const{ + if(!doHisto(hid)) return; + const auto h = m_h1[hid]; + if( h == nullptr ) return; + double bins = (double) h->axis().bins(); + double step = h->axis().upperEdge() - h->axis().lowerEdge(); + step = ( bins == 0) ? 0 : step/bins/2.; + if(m_sat){ + if( value < h->axis().lowerEdge() )value = h->axis().lowerEdge()+step; + if( value > h->axis().upperEdge() )value = h->axis().upperEdge()-step; + } + + if( m_splitSides && !(cellID == LHCb::CaloCellID()) ) { + int col = cellID.col(); + int cal = cellID.calo(); + std::string side = "A-side"; + if( CaloCellCode::CaloNameFromNum(cal) == "Hcal"){ + if(col<16)side = "C-side"; + } + else if(col<32){ + side = "C-side"; + } + GaudiAlg::HistoID id(side + "/" + hid); + const auto hh = m_h1[id]; + if( hh == nullptr ) return; + fill(hh,value,w); + } + else if( m_split && !(cellID == LHCb::CaloCellID()) ) { + std::string area = CaloCellCode::caloArea ( CaloCellCode::caloNum( m_detData ), cellID.area() ); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Filling histogram2D per calo region " << cellID << endmsg; + if( validArea( area ) ){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "valid area " << area << endmsg; + GaudiAlg::HistoID id(area + "/" + hid); + const auto hh = m_h1[id]; + if( hh == nullptr ) return; + fill(hh,value,w); + } + } + fill(h,value,w); +} + +void CaloFutureMoniAlg::hFill2( LHCb::CaloCellID cellID , std::string hid, double x, double y, double w ) const { + if(!doHisto(hid)) return; + const auto h = m_h2[hid]; + if( h == nullptr ) return; + double xbins = (double) h->xAxis().bins(); + double xstep = h->xAxis().upperEdge() - h->xAxis().lowerEdge(); + xstep = ( xbins == 0) ? 0 : xstep/xbins/2.; + double ybins = (double) h->yAxis().bins(); + double ystep = h->yAxis().upperEdge() - h->yAxis().lowerEdge(); + ystep = ( ybins == 0) ? 0 : ystep/ybins/2.; + if(m_sat2D){ + if( x < h->xAxis().lowerEdge() )x = h->xAxis().lowerEdge()+xstep; + if( x > h->xAxis().upperEdge() )x = h->xAxis().upperEdge()-xstep; + if( y < h->yAxis().lowerEdge() )y = h->yAxis().lowerEdge()+ystep; + if( y > h->yAxis().upperEdge() )y = h->yAxis().upperEdge()-ystep; + } + + if( m_splitSides && !(cellID == LHCb::CaloCellID()) ) { + int col = cellID.col(); + int cal = cellID.calo(); + std::string side = "A-side"; + if( CaloCellCode::CaloNameFromNum(cal) == "Hcal"){ + if(col<16)side = "C-side"; + } + else if(col<32){ + side = "C-side"; + } + GaudiAlg::HistoID id(side + "/" + hid); + const auto hh = m_h2[id]; + fill(hh,x,y,w); + } + else if( m_split && !(cellID == LHCb::CaloCellID()) ){ + // std::string area = CaloFutureCellCode::CaloFutureAreaFromNum( CaloFutureCellCode::CaloFutureNumFromName( m_detData ), cellID.area() ); + std::string area = CaloCellCode::caloArea ( CaloCellCode::caloNum ( m_detData ), cellID.area() ); + if( validArea( area ) ){ + GaudiAlg::HistoID id(area + "/" + hid); + const auto hh = m_h2[id]; + fill(hh,x,y,w); + } + fill(h,x,y,w); + }else{ + fill(h,x,y,w); + } +} + +//============================================================================== +// MISC +//============================================================================== + +bool CaloFutureMoniAlg::doHisto( const std::string histo ) const { + // blacklist has highest priority + if(std::any_of( m_removeHisto.begin(), m_removeHisto.end(), + [histo](std::string h){return histo == h;})) return false; + // Followup by whitelist, "ALL" + return std::any_of( m_histoList.begin(), m_histoList.end(), + [histo](std::string h){return histo==h || "All"==h;}); +} + +//============================================================================== + +bool CaloFutureMoniAlg::validArea( const std::string area ) const { + return std::any_of( m_areas.begin(), m_areas.end(), [area](auto s){return s==area;} ); +} + +//============================================================================== diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureMoniAlg.h b/CaloFuture/CaloFutureMoniDst/src/CaloFutureMoniAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..1d1000f50672fb419457f10df820304eee9f26bf --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureMoniAlg.h @@ -0,0 +1,128 @@ +#ifndef CALOFUTUREMONIDST_CALOFUTUREMONIALG_H +#define CALOFUTUREMONIDST_CALOFUTUREMONIALG_H 1 +// ============================================================================ +// Include files +// ============================================================================ +// from Gaudi +// ============================================================================ + +#include "GaudiAlg/GaudiHistoAlg.h" +#include "GaudiKernel/HashMap.h" +#include "GaudiUtils/Aida2ROOT.h" +#include "CaloFutureUtils/CaloFuture2Dview.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" +#include "Kernel/CaloCellID.h" +#include "AIDA/IAxis.h" +#include "AIDA/IHistogram1D.h" +#include "AIDA/IHistogram2D.h" +#include "TROOT.h" + +// ============================================================================ +// AIDA +// ============================================================================ +#include "AIDA/IHistogram1D.h" + +// @class CaloFutureMoniAlg CaloFutureMoniAlg.h +// +// @see GaudiHistoAlg +// @see GaudiAlgorithm +// @see Algorithm +// @see IAlgorithm + +class CaloFutureMoniAlg : public CaloFuture2Dview{ + +public: + // Standard constructor + // @param name algorithm name + // @param pSvcLocator pointer to service locator + CaloFutureMoniAlg( const std::string &name, ISvcLocator *pSvcLocator ); + StatusCode initialize() override; + + // address/location/name in Transient Store of detector data + const std::string &detData() const { return m_detData; } + // set address/location/name in Transient Store of detector data + void setDetData( const std::string &addr ) { m_detData = addr; } + + // booking histogram + void initFutureCounters() const; + void count(LHCb::CaloCellID id = LHCb::CaloCellID() ) const; + void fillFutureCounters(std::string) const; + void hBook1( const std::string, const std::string, const double low=0, + const double high=100, const unsigned long bins=100 ); + void h1binLabel( const std::string hid,int bin, std::string label ) const; + void hBook2( const std::string hid, + const std::string titl, + const double lowx=0, + const double highx=100, + const unsigned long binsx=100, + const double lowy=0, + const double highy=100, + const unsigned long binsy=100 ); + + // fill histogram + void hFill1(std::string hid, double value, double w=1. ) const; + void hFill2(std::string hid, double x, double y, double w=1. ) const; + void hFill1(LHCb::CaloCellID cellID, std::string hid, double value, double w=1. ) const; + void hFill2(LHCb::CaloCellID cellID, std::string hid, double x, double y, double w=1. ) const; + +private: + Gaudi::Property<std::string> m_detData {this, "Detector", "Ecal", "address/location/name in Transient Store of detector data"}; + +protected: + ToolHandle<IFutureCounterLevel> m_counterStat { "FutureCounterLevel" }; + + // Histogram Map + GaudiUtils::HashMap< std::string, AIDA::IHistogram1D * > m_h1; + GaudiUtils::HashMap< std::string, AIDA::IHistogram2D * > m_h2; + + // Properties + Gaudi::Property<float> m_energyMin { this, "HistoEnergyMin" , 0.}; + Gaudi::Property<float> m_etMin { this, "HistoEtMin" , 0.}; + Gaudi::Property<float> m_massMin { this, "HistoMassMin" , 0.}; + Gaudi::Property<float> m_xMin { this, "HistoXMin" , -4 * Gaudi::Units::meter}; + Gaudi::Property<float> m_yMin { this, "HistoYMin" , -4 * Gaudi::Units::meter}; + Gaudi::Property<float> m_multMin { this, "HistoMultiplicityMin", 0.}; + Gaudi::Property<float> m_sizeMin { this, "HistoSizeMin" , 0.}; + + Gaudi::Property<float> m_energyMax { this, "HistoEnergyMax" , 250. * Gaudi::Units::GeV}; + Gaudi::Property<float> m_etMax { this, "HistoEtMax" , 15. * Gaudi::Units::GeV}; + Gaudi::Property<float> m_massMax { this, "HistoMassMax" , 250.*Gaudi::Units::MeV}; + Gaudi::Property<float> m_xMax { this, "HistoXMax" , +4 * Gaudi::Units::meter}; + Gaudi::Property<float> m_yMax { this, "HistoYMax" , +4 * Gaudi::Units::meter}; + Gaudi::Property<float> m_multMax { this, "HistoMultiplicityMax", 2000.}; + Gaudi::Property<float> m_sizeMax { this, "HistoSizeMax" , 25.}; + + Gaudi::Property<int> m_energyBin { this, "HistoEnergyBin" , 100}; + Gaudi::Property<int> m_etBin { this, "HistoEtBin" , 100}; + Gaudi::Property<int> m_massBin { this, "HistoMassBin" , 100}; + Gaudi::Property<int> m_xBin { this, "HistoXBin" , 50}; + Gaudi::Property<int> m_yBin { this, "HistoYBin" , 50}; + Gaudi::Property<int> m_multBin { this, "HistoMultiplicityBin", 100}; + Gaudi::Property<int> m_sizeBin { this, "HistoSizeBin" , 25}; + + Gaudi::Property<float> m_eFilter { this, "EnergyFilter" , -100.}; + Gaudi::Property<float> m_etFilter { this, "EtFilter" , -100.}; + Gaudi::Property<float> m_massFilterMin { this, "MassWindowMin", -9999999.}; + Gaudi::Property<float> m_massFilterMax { this, "MassWindowMax", +9999999.}; + + Gaudi::Property<bool> m_sat { this, "SaturationBin1D", true}; + Gaudi::Property<bool> m_sat2D { this, "SaturationBin2D", false}; + Gaudi::Property<bool> m_print { this, "PrintOut" , false}; + Gaudi::Property<bool> m_splitSides { this, "SplitSides" , false}; + + Gaudi::Property<std::vector<std::string>> m_histoList { this, "histoList" , { "All"}}; + Gaudi::Property<std::vector<std::string>> m_removeHisto { this, "removeFromHistoList", { }}; + Gaudi::Property<std::vector<std::string>> m_areas { this, "listOfAreas" , { "Outer" , "Middle", "Inner"}, "list of areas to be split"}; + + const unsigned int m_nAreas = 1 << (CaloCellCode::BitsArea +1); + + // For const operator() + mutable unsigned int m_count = 0; + mutable std::vector<unsigned int> m_mcount; + mutable std::vector<unsigned int> m_scount; + + bool doHisto( const std::string histo ) const; + bool validArea( const std::string area ) const; +}; +#endif // CALOFUTUREMONIDST_CALOFUTUREMONIALG_H diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureMoniUtils.h b/CaloFuture/CaloFutureMoniDst/src/CaloFutureMoniUtils.h new file mode 100644 index 0000000000000000000000000000000000000000..b7413e0d46421913a05a3f76cda566df5e64a835 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureMoniUtils.h @@ -0,0 +1,96 @@ +#include "GaudiKernel/Plane3DTypes.h" +#include "GaudiKernel/Vector3DTypes.h" +#include "LHCbMath/Line.h" +#include "LHCbMath/GeomFun.h" +#include "CaloFutureUtils/CaloMomentum.h" + +inline bool inRange(const std::pair<double,double> range, double value){ + return (value>=range.first) && (value<=range.second); +} + +inline bool inRange(const std::pair<int,int> range, int value){ + return (value==0 && range.first==1 ) || (value>0 &&range.second==1); +} + +//============================================================================== + +// Helper method to calculate intersection, when only interested in a point, +// assuming that the intersection exists. +// Usage: +// const auto cross = intersection(line, plane); +inline Gaudi::XYZPoint intersection(const Gaudi::Math::Line<Gaudi::XYZPoint,Gaudi::XYZVector>& line, const Gaudi::Plane3D& plane){ + Gaudi::XYZPoint cross; + double mu; + Gaudi::Math::intersection<Gaudi::Math::Line<Gaudi::XYZPoint,Gaudi::XYZVector>,Gaudi::Plane3D,Gaudi::XYZPoint>(line, plane, cross, mu); + return cross; +} + +//============================================================================== + +// shamelessly stolen from Vanya's LHCb/Phys/LoKiCore/src/Print.cpp +inline std::string tesLocation( const ContainedObject* obj ){ + if ( obj == nullptr ) { return "" ; } + const auto parent = obj->parent(); + if ( parent == nullptr ) { return "" ; } + const auto reg = parent->registry(); + if ( reg == nullptr ) { return "" ; } + return reg->identifier(); +} + +//============================================================================== + +// Idiom I often encountered +// inline LHCb::CaloCellID firstClusterSeed( const LHCb::CaloHypo* hypo ){ +inline SmartRef<LHCb::CaloCluster> firstCluster( const LHCb::CaloHypo* hypo ){ + SmartRef<LHCb::CaloCluster> cluster; + if( hypo != nullptr ){ + const auto clusters = hypo->clusters(); + if( !clusters.empty() ){ + cluster = *clusters.begin(); + } + } + return cluster; +} + +//============================================================================== + +// Adapters for ntuple, guard against nullptr too +inline Gaudi::XYZPoint position3d( const LHCb::CaloHypo* obj ){ + if( obj == nullptr ) return Gaudi::XYZPoint(); + return Gaudi::XYZPoint( obj->position()->x(), obj->position()->y(), obj->position()->z() ); +} +// e.g. from firstCluster(hypo) +inline Gaudi::XYZPoint position3d( const LHCb::CaloCluster* obj ){ + if( obj == nullptr ) return Gaudi::XYZPoint(); + return Gaudi::XYZPoint( obj->position().x(), obj->position().y(), obj->position().z() ); +} +inline Gaudi::XYZPoint position3d( const LHCb::State& obj ){ + return obj.position(); +} +inline Gaudi::LorentzVector position4d( const LHCb::CaloCluster* obj ){ + if( obj == nullptr ) return Gaudi::LorentzVector(); + return Gaudi::LorentzVector( obj->position().x(), obj->position().y(), obj->position().z(), obj->e() ); +} + +// e.g., from +inline Gaudi::LorentzVector momentum( const LHCb::CaloHypo* obj ){ + if( obj == nullptr ) return Gaudi::LorentzVector(); + return Gaudi::LorentzVector(LHCb::CaloMomentum(obj).momentum()); +} +// e.g., from proto->track() +inline Gaudi::LorentzVector momentum( const LHCb::Track* obj ){ + if( obj == nullptr ) return Gaudi::LorentzVector(); + return Gaudi::LorentzVector(obj->momentum().x(), obj->momentum().y(), obj->momentum().z(), obj->p()); +} +// e.g., from m_caloElectron->caloState() +inline Gaudi::LorentzVector momentum( const LHCb::State& obj ){ + return Gaudi::LorentzVector(obj.momentum().x(), obj.momentum().y(), obj.momentum().z(), obj.p()); +} +// e.g., from m_caloElectron->bremCaloMomentum() +inline Gaudi::LorentzVector momentum( LHCb::CaloMomentum obj ){ + return Gaudi::LorentzVector( obj.momentum().x(), obj.momentum().y(), + obj.momentum().z(), obj.momentum().e()); +} + + +//============================================================================== diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFuturePIDsChecker.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePIDsChecker.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7607ef8aff7037469733d1592ca5217fecee32dd --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePIDsChecker.cpp @@ -0,0 +1,277 @@ +// Includes +#include "GaudiAlg/Consumer.h" +#include "AIDA/IAxis.h" +#include "Event/Track.h" +#include "Event/MCParticle.h" +// #include "Relations/IRelation.h" +#include "Relations/Relation1D.h" +// #include "Relations/IRelationWeighted.h" +#include "Kernel/Particle2MCLinker.h" +#include "CaloFutureUtils/CaloFuture2Track.h" +#include "boost/lexical_cast.hpp" +#include "CaloFutureMoniAlg.h" + +// ============================================================================= + +namespace { + /** extract the momentum from Track + * @param track pointer to the track + * @return the momentum of the track + */ + constexpr double momentum( const LHCb::Track *track ){ + return track != nullptr ? track->closestState( 0.0 ).p() : -100*Gaudi::Units::GeV; + } + +} + +using Input = LHCb::Relation1D<LHCb::Track,float>; +using Inputs = LHCb::Track::Container; +using AccTable = LHCb::Relation1D<LHCb::Track,bool>; + +// ============================================================================= + +/** @class CaloFuturePIDsChecker CaloFuturePIDsChecker.cpp + * + * Class for monitoring the CaloFuturePIDs quantities + * + * The major properties + * + * - "Input" + * The default value is "" + * The PID-quantity to be monitored, relation table of + * type IRelation<Track,float> + * + * - "Inputs" + * The default value is : TrackLocation::Default + * The list of Track containers to be monitored + * + * - "Tr2MCP" + * The default value is : "Rec/Relations/Tr2MCP" + * The location in TES the relation table of type + * IRelationWeighted<Track,MCParticle,double> + * + * - "Particle" + * The default value is : 11 + * Particle ID for "signal" hypothesis + * + * - "Cut" + * The default value is : 0 + * The cut on PID to be used for monitoring + * + * - "Normialization" + * The default value is : 50 GeV + * The normalization factor used for histogramming + * + * @author Vanya BELYAEV Ivan.Belyaev@itep.ru + * @date 2004-02-15 + */ + +class CaloFuturePIDsChecker final +: public Gaudi::Functional::Consumer<void(const Input&, const Inputs&, const AccTable&), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureMoniAlg>> +{ +public: + StatusCode initialize() override; + StatusCode finalize() override; + void operator()(const Input&, const Inputs&, const AccTable&) const override; + + CaloFuturePIDsChecker( const std::string &name, ISvcLocator *isvc ); + +protected: + /// transformation function for momentum + inline double pFunc( const double value ) const + { return tanh( value / m_pNorm );} + + /// h3=h1/h2 + StatusCode divide( AIDA::IHistogram1D *hh1, AIDA::IHistogram1D *hh2, + AIDA::IHistogram1D *hh3 ) const; + +private: + // Track -> MC associator + Object2MCLinker<LHCb::Track>* m_track2MCLink = nullptr; + + Gaudi::Property<unsigned int> m_pid + {this, "Particle", 11, "particle to be identified"}; + + Gaudi::Property<float> m_cut + {this, "Cut", 0., "cut value"}; + + Gaudi::Property<float> m_pNorm + {this, "Normalization", 50 * Gaudi::Units::GeV, "momentum normalization"}; + + Gaudi::Property<std::string> m_typName + {this, "TrackType", "ALL"}; + + LHCb::Track::Types m_typ = LHCb::Track::Types::TypeUnknown; + bool m_checkType = true; +}; + +// ============================================================================= + +DECLARE_COMPONENT( CaloFuturePIDsChecker ) + +// ============================================================================= + +CaloFuturePIDsChecker::CaloFuturePIDsChecker( const std::string &name, ISvcLocator *isvc ) +: Consumer( name, isvc, { + KeyValue{ "Input" , "" }, + KeyValue{ "Inputs" , LHCb::TrackLocation::Default }, + KeyValue{ "TrackAcceptance", "Rec/Calo/InAccEcal" } +}) +{} + +// ============================================================================= + +StatusCode CaloFuturePIDsChecker::initialize(){ + StatusCode sc = Consumer::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; // error already printedby GaudiAlgorithm + + const std::string mom = "tanh(P/" + + boost::lexical_cast<std::string>( m_pNorm / Gaudi::Units::GeV ) + + " GeV/c) "; + const std::string cut = "with cut 'DLL>" + + boost::lexical_cast<std::string>( m_cut.value() ) + "' "; + + hBook1( "1", "DLL for 'Signal'", -5, 5 ); + hBook1( "2", "DLL for 'Ghosts'", -5, 5 ); + hBook1( "3", "DLL for 'Background'", -5, 5 ); + + hBook1( "11", mom + "for 'Signal'", 0, 1.02, 51 ); + hBook1( "12", mom + "for 'Ghosts'", 0, 1.02, 51 ); + hBook1( "13", mom + "for 'Background'", 0, 1.02, 51 ); + + hBook1( "21", mom + cut + "for 'Signal'", 0, 1.02, 51 ); + hBook1( "22", mom + cut + "for 'Ghosts'", 0, 1.02, 51 ); + hBook1( "23", mom + cut + "for 'Background'", 0, 1.02, 51 ); + + hBook1( "31", "Eff " + mom + cut + "for 'Signal'", 0, 1.02, 51 ); + hBook1( "32", "Eff " + mom + cut + "for 'Ghosts'", 0, 1.02, 51 ); + hBook1( "33", "Eff " + mom + cut + "for 'Background'", 0, 1.02, 51 ); + + m_track2MCLink = new Object2MCLinker<LHCb::Track>( this, "", "", inputLocation<1>() ); + if( m_split ){ + Warning( "No area spliting allowed for CaloFuturePIDsChecker").ignore(); + m_split = false; + } + + if ( LHCb::CaloFutureAlgUtils::toUpper(m_typName.value()) == "ALL" ) + m_checkType = false; + else + m_typ = LHCb::Track::TypesToType(m_typName.value()); + + return StatusCode::SUCCESS; +} + +// ============================================================================= + +StatusCode CaloFuturePIDsChecker::finalize(){ + StatusCode sc = divide( m_h1["21"], m_h1["11"], m_h1["31"] ); + if(sc.isSuccess())sc=divide( m_h1["22"], m_h1["12"], m_h1["32"] ); + if(sc.isSuccess())sc= divide( m_h1["23"], m_h1["13"], m_h1["33"] ); + if(!sc.isSuccess())error()<<"Failed dividing histograms " << endmsg; + + if( nullptr != m_track2MCLink ) delete m_track2MCLink; + m_track2MCLink = nullptr; + + return Consumer::finalize(); +} + + +// ============================================================================= + +void CaloFuturePIDsChecker::operator()(const Input& pidTable, const Inputs& tracks, const AccTable& accTable) const { + + // produce histos ? + if ( !produceHistos() ) return; + + // Loop over tracks + for( const auto& track: tracks ){ + + // Abort if track type mismatched + if( m_checkType && track->type() != m_typ ) continue; + + // Abort if track is outside acceptance + if(accTable.relations(track).front().to() == false) continue; + + // get MC truth + double maxWeight = 0; + const LHCb::MCParticle* mc = m_track2MCLink->first(track, maxWeight); + auto mcp = (LHCb::MCParticle*) mc; + if( mc != nullptr ){ + do{ + double weight = 0; + mc = m_track2MCLink->next(weight); + if(weight > maxWeight){ + maxWeight = weight; + mcp = (LHCb::MCParticle*) mc; + } + }while( mc != nullptr ); + } + + // retrieve calo pid information + const auto calo = pidTable.relations( track ); + + // get THE LAST pid + const double DLL = calo.empty() ? -1000.0 : calo.back().to(); + if ( 0 == mcp ) hFill1("2", DLL); //ghosts + else if ( mcp->particleID().abspid() == m_pid ) hFill1("1", DLL); //signal + else hFill1("3", DLL); //background + + // evaluate the function of momentum + const double pMom = pFunc( momentum( track ) ); + if ( 0 == mcp ) hFill1("12", pMom); //ghosts + else if ( mcp->particleID().abspid() == m_pid ) hFill1("11", pMom); //signal + else hFill1("13", pMom); //background + + // apply DLL cut + if ( DLL < m_cut ) continue; + if ( 0 == mcp ) hFill1("22", pMom); //ghosts + else if ( mcp->particleID().abspid() == m_pid ) hFill1("21", pMom); //signal + else hFill1("23", pMom); //background + } + return; +} + +// ============================================================================= +// Divide the histograms +// ============================================================================= + +StatusCode CaloFuturePIDsChecker::divide( AIDA::IHistogram1D *hh1 + , AIDA::IHistogram1D *hh2 + , AIDA::IHistogram1D *hh3 ) const +{ if (( 0 == hh1 ) || ( 0 == hh2 ) || ( 0 == hh3 )){ + return Error( "AIDA::IHistogram1D* points to NULL" ); + } + const IAxis &axis1 = hh1->axis(); + const IAxis &axis2 = hh2->axis(); + const IAxis &axis3 = hh3->axis(); + const int nBins = axis3.bins(); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "DIVIDE nbins " << nBins << endmsg; + + if (( axis1.bins() != nBins ) || ( axis2.bins() != nBins )) + { return Error( "Different histogram specifications" ); + } + double count = 0; + for( int nBin = 0; nBin < nBins; ++nBin ) + { const double v1 = hh1->binHeight( nBin ); + const double v2 = hh2->binHeight( nBin ); + const double x = 0.5 * ( axis3.binLowerEdge ( nBin ) + + axis3.binUpperEdge ( nBin ) ); + +// fill the histogram + if ( 0 != v2 ) hh3->fill( x, v1/v2 ); + if ( 0 != v1) count += 1.; + } + + const double content = hh3->sumBinHeights(); + if ( 0 != count ){ + info() << "'" << hh3->title() << "' = " + << (content/count)*100 << "[%]" << endmsg; + }else{ + info() << "'" << hh1->title() + << "' contains no filled bins - histogram ratio undefined" << endmsg; + } + + return StatusCode::SUCCESS; +} diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFuturePhotonChecker.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePhotonChecker.cpp new file mode 100644 index 0000000000000000000000000000000000000000..794ce5726e363c268b548f4621006205b81d8587 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePhotonChecker.cpp @@ -0,0 +1,612 @@ +// Include files +// STD & STL +#include <algorithm> +// from Gaudi +#include "GaudiKernel/Plane3DTypes.h" +#include "GaudiKernel/Point3DTypes.h" +#include "GaudiKernel/Vector3DTypes.h" +// From PartProp +#include "Kernel/IParticlePropertySvc.h" +#include "Kernel/ParticleProperty.h" +#include "Event/MCParticle.h" +#include "Event/MCVertex.h" +#include "Event/CaloHypo.h" +#include "CaloFutureUtils/CaloFuture2Track.h" +#include "CaloFutureUtils/CaloMomentum.h" +#include "CaloFutureUtils/ClusterFunctors.h" +#include "CaloFutureInterfaces/ICaloFutureHypoLikelihood.h" +#include "CaloDet/DeCalorimeter.h" +// local +#include "CaloFuturePhotonChecker.h" +#include "CaloFutureMoniUtils.h" + +DECLARE_COMPONENT( CaloFuturePhotonChecker ) + +// ============================================================================= + +namespace { + // math transform + constexpr double transform(double e){ + return (e<1.e-10) ? 0. : std::max({ log(1.35914*e)-6.21461, 5.5 }); + } +} + +// ============================================================================= +/** @file + * + * Implementation file for class CaloFuturePhotonChecker + * Photon Selection Monitoring + * (LHCb 2004-03) + * + * @author Frederic Machefert frederic.machefert@in2p3.fr + * @date 2004-15-04 + */ +// ============================================================================= + +CaloFuturePhotonChecker::CaloFuturePhotonChecker( const std::string &name, ISvcLocator *pSvcLocator ) +: Consumer( name, pSvcLocator, { + KeyValue{ "Input" , LHCb::CaloHypoLocation::Photons }, // Legacy naming + KeyValue{ "InputMCPs" , LHCb::MCParticleLocation::Default }, + KeyValue{ "CC2TrTableName" , LHCb::CaloFutureIdLocation::ClusterMatch }, // Legacy naming + KeyValue{ "CC2MCPTableName" , "Relations/"+LHCb::CaloClusterLocation::Default },// Legacy naming + KeyValue{ "InputIDTable" , LHCb::CaloFutureIdLocation::PhotonID } +}) {} + +// ============================================================================= + +StatusCode CaloFuturePhotonChecker::initialize(){ + StatusCode sc = Consumer::initialize(); + if ( sc.isFailure() ) return sc; + + //----- locate particle property service + LHCb::IParticlePropertySvc* ppSvc = svc<LHCb::IParticlePropertySvc>( "LHCb::ParticlePropertySvc", true ); + if( 0 == ppSvc ) return Error("Could not locate LHCb::ParticlePropertySvc!"); + + const auto ppg = ppSvc->find( m_gammaName ); + if( 0 == ppg ) { + error() << "Could not locate particle ' " <<m_gammaName << " '" << endmsg; + return StatusCode::FAILURE; + } + m_gammaID = ppg->pid() ; + + const auto ppp = ppSvc->find( m_pi0Name ); + if( 0 == ppp ) { + error() << "Could not locate particle ' " << m_pi0Name << " '" << endmsg; + return StatusCode::FAILURE; + } + m_pi0ID = ppp->pid() ; + + info() << "Photon/Pi0 particle properties locatlized." << endmsg; + + //----- Detector recovery + + m_ecal = getDet<DeCalorimeter>( DeCalorimeterLocation::Ecal ); + m_spd = getDetIfExists<DeCalorimeter>( DeCalorimeterLocation::Spd ); + m_prs = getDetIfExists<DeCalorimeter>( DeCalorimeterLocation::Prs ); + if( !m_spd || !m_prs) return Error("DeCalorimeter does not exist for Prs/Spd"); + + m_ecalPlane = m_ecal->plane( CaloPlane::ShowerMax ); + m_spdPlane = m_spd->plane ( CaloPlane::Middle ); + m_prsPlane = m_prs->plane ( CaloPlane::Middle ); + + const auto spdFront = m_spd->plane( CaloPlane::Front ); + const auto normal = spdFront.Normal(); + m_zConv = -spdFront.HesseDistance() / normal.Z(); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "z conversion definition is set to SPD front : " << m_zConv << endmsg; + + //----- Tool recovery + + + //----- Check data consistency + if (m_prsbin.size()!=3) { return Error("Wrong Binning Parameter (EPrs)"); } + if (m_chi2bin.size()!=3) { return Error("Wrong Binning Parameter (Chi2Tk)"); } + if (m_seedbin.size()!=3) { return Error("Wrong Binning Parameter (ESeed)"); } + + // Reset Monitoring parameter + for (int i=0 ; i<m_nbinpt ; ++i){ + m_mc_g.push_back(0); + m_rec_bkg.push_back(0); + m_rec_sig.push_back(0); + } + + m_lh_mcg=0; + m_lh_mcg_conv=0; + m_lh_mcg_noconv=0; + for (int i=0 ; i<m_nbinlh ; ++i){ + m_lh_recsig.push_back(0); + m_lh_recbkg.push_back(0); + m_lh_recsig_conv.push_back(0); + m_lh_recsig_spd.push_back(0); + m_lh_recbkg_spd.push_back(0); + m_lh_recsig_noconv.push_back(0); + m_lh_recsig_nospd.push_back(0); + m_lh_recbkg_nospd.push_back(0); + } + + // Likelihood Output for Signal / Background + m_lhSig = book1D( "Lh_Sig_noSpd","likelihood Signal - no SPD" ,0.,1.,50); + m_lhSigSpd = book1D( "Lh_Sig_Spd" ,"likelihood Signal - SPD hit" ,0.,1.,50); + m_lhBkg = book1D( "Lh_Bkg_noSpd","likelihood Background - no SPD" ,0.,1.,50); + m_lhBkgSpd = book1D( "Lh_Bkg_Spd" ,"likelihood Background - SPD hit",0.,1.,50); + + // Efficiency / Purity versus Pt + m_efficiency = book1D( "Efficiency" ,"Photon Selection Efficiency vs Pt",m_ptmin,m_ptmax,m_nbinpt); + m_purity = book1D( "Purity" ,"Photon Selection Purity vs Pt",m_ptmin,m_ptmax,m_nbinpt); + + m_effpur = book2D( "Eff_Pur", "Efficiency vs Purity - Lh cut",0.,1.,100,0.,1.,100); + m_effpur_spd = book2D( "Eff_Pur_Spd", "Efficiency vs Purity - Lh cut - no Conv. sample",0.,1.,100,0.,1.,100); + m_effpur_nospd = book2D( "Eff_Pur_noSpd", "Efficiency vs Purity - Lh cut - Conv. sample",0.,1.,100,0.,1.,100); + + + // Probability Density Functions Definitions + if (m_pdf){ + m_signalEPrs2D=defHisto(int(m_prsbin[ 0 ]),m_prsbin[ 1 ],m_prsbin[ 2 ], + 10, std::string("Signal_Prs_noSpdHit")); + m_signalChi22D=defHisto(int(m_chi2bin[ 0 ]),m_chi2bin[ 1 ],m_chi2bin[ 2 ], + 20, std::string("Signal_Chi2Tk_noSpdHit")); + m_signalSeed2D=defHisto(int(m_seedbin[ 0 ]),m_seedbin[ 1 ],m_seedbin[ 2 ], + 30, std::string("Signal_ESeed_noSpdHit")); + + m_signalEPrsSpd2D=defHisto(int(m_prsbin[ 0 ]),m_prsbin[ 1 ],m_prsbin[ 2 ], + 15, std::string("Signal_Prs_SpdHit")); + m_signalChi2Spd2D=defHisto(int(m_chi2bin[ 0 ]),m_chi2bin[ 1 ],m_chi2bin[ 2 ], + 25, std::string("Signal_Chi2Tk_SpdHit")); + m_signalSeedSpd2D=defHisto(int(m_seedbin[ 0 ]),m_seedbin[ 1 ],m_seedbin[ 2 ], + 35, std::string("Signal_ESeed_SpdHit")); + + m_backgrEPrs2D=defHisto(int(m_prsbin[ 0 ]),m_prsbin[ 1 ],m_prsbin[ 2 ], + 110, std::string("Background_Prs_noSpdHit")); + m_backgrChi22D=defHisto(int(m_chi2bin[ 0 ]),m_chi2bin[ 1 ],m_chi2bin[ 2 ], + 120, std::string("Background_Chi2Tk_noSpdHit")); + m_backgrSeed2D=defHisto(int(m_seedbin[ 0 ]),m_seedbin[ 1 ],m_seedbin[ 2 ], + 130, std::string("Background ESeed_noSpdHit")); + + m_backgrEPrsSpd2D=defHisto(int(m_prsbin[ 0 ]),m_prsbin[ 1 ],m_prsbin[ 2 ], + 115, std::string("Background_Prs_SpdHit")); + m_backgrChi2Spd2D=defHisto(int(m_chi2bin[ 0 ]),m_chi2bin[ 1 ],m_chi2bin[ 2 ], + 125, std::string("Background_Chi2Tk_SpdHit")); + m_backgrSeedSpd2D=defHisto(int(m_seedbin[ 0 ]),m_seedbin[ 1 ],m_seedbin[ 2 ], + 135, std::string("Background_ESeed_SpdHit")); + } + + if( m_split ){ + Warning( "No area spliting allowed for CaloFuturePhotonChecker").ignore(); + m_split = false; + } + return StatusCode::SUCCESS; +} +// ============================================================================ + +// ============================================================================ +/** standard algorithm finalization + * @see CaloFutureAlgorithm + * @see Algorithm + * @see IAlgorithm + * @return status code + */ +// ============================================================================ + +StatusCode CaloFuturePhotonChecker::finalize(){ + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "==> Finalize" << endmsg; + + info() << "************* Photon Monitoring *****************"<<endmsg; + info() << "Number of Events Analyzed : " << m_nEvents << endmsg; + info() + //<< "MCPhotons (Signal def.) in sample: "<<m_nMCPhotons<<" - " + <<m_nPhotons<<" Photons (Signal def.) out of "<<m_nCandidates<<" hypos processed." + <<" - "<<m_nWrongs<<" hypos rejected."<<endmsg; + char line[70]; + info() << endmsg; + info() << " Et(GeV) | Efficiency | Purity "<<endmsg; + info() << "----------------------------------------------"<<endmsg; + for (int i=0; i<m_nbinpt ; ++i){ + double pt= m_ptmin+double(i)*(m_ptmax-m_ptmin)/double(m_nbinpt); + double eff=(m_mc_g[i]>0) ? double(m_rec_sig[i])/double(m_mc_g[i]) : 0.; + double pur=(m_rec_sig[i]+m_rec_bkg[i]>0) ? m_rec_sig[i]/(m_rec_sig[i]+m_rec_bkg[i]) : 0. ; + sprintf(line," [ %5.2f - %5.2f ] | %4.2f | %4.2f ", + pt/1000.,(pt+(m_ptmax-m_ptmin)/double(m_nbinpt))/1000.,eff,pur); + + info() << line <<endmsg; + + fill(m_efficiency,pt,eff); + fill(m_purity,pt,pur); + } + info() << endmsg; + info() << " L>= | Total | No Conv | Conv "<<endmsg; + info() << " | Eff Pur | Eff Pur | Eff Pur "<<endmsg; + info() << " -----------------------------------------"<<endmsg; + for (int i=0; i<m_nbinlh ; ++i){ + double eff=(m_lh_mcg>0) ? m_lh_recsig[i]/m_lh_mcg : 0.; + double effnoconv=(m_lh_mcg_noconv>0) ? m_lh_recsig_noconv[i]/m_lh_mcg_noconv : 0.; + double effconv=(m_lh_mcg_conv>0) ? m_lh_recsig_conv[i]/m_lh_mcg_conv : 0.; + double pur=(m_lh_recsig[i]+m_lh_recbkg[i]>0) ? m_lh_recsig[i]/(m_lh_recsig[i]+m_lh_recbkg[i]) : 0. ; + double purnoconv = + (m_lh_recsig_nospd[i]+m_lh_recbkg_nospd[i]>0) ? m_lh_recsig_nospd[i]/(m_lh_recsig_nospd[i]+m_lh_recbkg_nospd[i]) : 0. ; + double purconv=(m_lh_recsig_spd[i]+m_lh_recbkg_spd[i]>0) ?m_lh_recsig_spd[i]/(m_lh_recsig_spd[i]+m_lh_recbkg_spd[i]) : 0. ; + + fill(m_effpur,pur,eff,1.); + fill(m_effpur_nospd,purnoconv,effnoconv,1.); + fill(m_effpur_spd,purconv,effconv,1.); + + sprintf(line," %3.2f | %3.2f %3.2f | %3.2f %3.2f | %3.2f %3.2f", + double(i)/double(m_nbinlh),eff,pur,effnoconv,purnoconv,effconv,purconv); + + info() << line <<endmsg; + + } + info() << "*************************************************"<<endmsg; + + return Consumer::finalize() ; +} +// ============================================================================ + +// ============================================================================ +/** standard algorithm execution + * @see CaloFutureAlgorithm + * @see Algorithm + * @see IAlgorithm + * @return status code + */ +// ============================================================================ + +void CaloFuturePhotonChecker::operator()(const Input& hypos, const MCPs& mcParts, + const Table& table, const MCTable& gtable, + const IDTable& idTable) const { + + // increment number of events + m_nEvents++; + + // // get MC photons + // if( !exist<MCPs>(LHCb::MCParticleLocation::Default)) + // return Warning("NO MC information",StatusCode::SUCCESS); + // MCPs* mcParts = get<MCPs>(LHCb::MCParticleLocation::Default); + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "MC Particles extracted from event : " << mcParts.size() << endmsg; + + // Loop over each mc particle + for( const auto& part: mcParts ){ + + if ( !(m_gammaID == part->particleID()) ) continue; // select MC-gamma + if ( part->momentum().pz() < 0.) continue; // Pz Acceptance + if ( part->momentum().pt() < m_etmin ) continue; // Et acceptance + + // Origin vertex + const auto vertex = part->originVertex(); + if ( vertex == nullptr ) continue; // ask for a vertex + if ((m_dz>0) && (fabs(vertex->position().Z())>m_dz)) continue; // origin vertex acceptance ... in z + if ((m_dr>0) && (vertex->position().Rho()>m_dr) ) continue; // ... and in (x,y) + + // Ecal acceptance + Line line( vertex->position(), part->momentum().Vect() ); + const auto cross = intersection(line, m_ecalPlane); + const Gaudi::XYZPoint hit(cross); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "MC part momentum " << part->momentum() + << " crosses Ecal Plane at point "<< cross << " -> cellID : " << m_ecal->Cell( hit ) << endmsg; + if( !m_ecal->valid( m_ecal->Cell( hit ) ) ) continue; // Ecal acceptance. + + // Conversion + Gaudi::XYZPoint decay(0., 0., 1.*Gaudi::Units::km); + const auto decays = part->endVertices(); + for( const auto& vertex: decays ){ + if( vertex->position().z() < decay.Z() ) decay = vertex->position(); + } + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "MC gamma endVertex.z() " << decay.Z() << endmsg; + + // belong to a merged pi0 ? + if (isMergedPi0(part)) { + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() <<"Merged Pi0 photons removed from Signal sample"<<endmsg; + continue; + } + m_nMCPhotons++; + + int ibin = int(m_nbinpt*( part->momentum().pt() - m_ptmin)/(m_ptmax-m_ptmin)); + if( ibin>=0 && ibin<m_nbinpt ){ + // efficiency / purity versus pt + m_mc_g[ibin]++; + // efficiency / purity versus likelihood + m_lh_mcg++; + if( decay.Z() > m_zConv ){ + m_lh_mcg_noconv++; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " Not converted " << m_zConv << endmsg; + } + else { + m_lh_mcg_conv++; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " converted " << m_zConv << endmsg; + } + } + } // end loop over mcp + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " MC part all/no-conv/conv" << m_lh_mcg << "/"<<m_lh_mcg_noconv<<"/"<<m_lh_mcg_conv<< endmsg; + + + // loop over hypos + for( const auto& hypo: hypos ){ + + // skip nulls + if( hypo == nullptr ){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() <<"empty CaloHypo : skipping"<<endmsg; + continue ; + } + + LHCb::CaloMomentum momentum( hypo ); + m_nCandidates++; + + // Transverse Momentum + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "==> Processing new CaloHypo : Et=" << momentum.momentum().pt() << endmsg; + if( momentum.momentum().pt() < m_etmin ) continue; + if (hypo->clusters().size()!=1){ + warning() <<"Photon Hypothesis : number of clusters!=1 ..."<<endmsg; + continue; + } + + const auto cluster = hypo->clusters().front(); + if( cluster == 0 ) + { Warning( " *CaloCluster* points to NULL ").ignore();continue; } + + const auto entries = cluster->entries(); + if( entries.empty() ){Warning( " *CaloCluster* empty ").ignore();continue;} + + const auto iseed = LHCb::ClusterFunctors::locateDigit( entries.begin(), entries.end(), LHCb::CaloDigitStatus::SeedCell); + if( iseed == entries.end() ){Warning(" *SeedCell* not found ").ignore();continue;} + + const auto seed = iseed->digit(); + if( 0 == seed ){Warning( " SeedCell *Digit* points to NULL! ").ignore();continue;} + + // seed cell area + const auto m_area = seed->cellID().area() ; + + // Energy + const double energy = momentum.momentum().e(); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "- Energy [MeV]=" << energy << endmsg; + + // Chi2 + const auto range = table.relations( cluster ); + const double chi2 = range.empty() ? 1.e+6 : range.front().weight(); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " - Chi2 ="<<chi2<<endmsg; + + // Cell seed + const double eSeed = energy>0. ? (seed->e())/energy : -1.; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug()<<" - Seed Energy ="<<eSeed<<endmsg; + + //Spd hit and Prs deposit + Line line( Gaudi::XYZPoint(0.,0.,0.) , momentum.momentum().Vect() ); + const auto spdPoint = intersection(line, m_spdPlane); + const auto prsPoint = intersection(line, m_prsPlane); + const auto cellSpd = m_spd->Cell( spdPoint ); + const auto cellPrs = m_prs->Cell( prsPoint ); + + double eSpd=0.; + double ePrs=0.; + + // Get CaloFutureCell Deposits in the SPD and PRS + if( !(LHCb::CaloCellID() == cellSpd) ){ + for( const auto& digit: hypo->digits() ){ + if( digit->cellID() == cellSpd ){ + eSpd = digit->e(); + } + } + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " - SPD " << cellSpd << " Energy =" << eSpd << endmsg; + } + + if( !(LHCb::CaloCellID() == cellPrs) ){ + for( const auto& digit: hypo->digits() ){ + if( digit->cellID() == cellPrs ){ + ePrs = digit->e(); + } + } + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " - PRS " << cellPrs << " Energy =" << ePrs << endmsg; + } + + // // *** + // double likelihood = -1.; + // if( NULL != idTable ){ + // const auto idRange = idTable->relations( hypo ) ; + // if( !idRange.empty() ) likelihood = idRange.front().to(); + // } + const auto idRange = idTable.relations( hypo ) ; + const double likelihood = idRange.empty() ? -1. : idRange.front().to(); + if(likelihood<0.){m_nWrongs++;} + + + // MCTruth Information + Gaudi::XYZPoint decay( 0., 0., 1.*Gaudi::Units::km ); + double wmax=-1.e6; + double dr=1.e+6; + double dz=1.e+6; + double de=1.e+6; + bool isSignal=false; + bool isPhoton=false; + bool isMerged=false; + + for( const auto& mc: gtable.relations(cluster) ){ + const auto mcpart = mc.to(); + if( mcpart == 0 ) continue; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "mctruth : --> pid=" << mcpart->particleID().pid() << " weight=" << mc.weight() << endmsg; + if( !(m_gammaID == mcpart->particleID()) ) continue; + if( mc.weight() < wmax ) continue; + wmax = mc.weight(); + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) { + debug() << "A MC-gamma matches the hypo " << endmsg; + debug() << " Energy : " << mcpart->momentum().e() << endmsg; + } + + isPhoton = true; + const auto vertex = mcpart->originVertex(); + if( vertex == 0 ){ + warning() << "MC-gamma has no origin vertex !" << endmsg; + continue; + } + + // selection + dr = vertex->position().Rho(); + dz = vertex->position().z(); + de = fabs(energy - mcpart->momentum().e())/energy; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Gamma parameters : dr=" << dr << " - dz=" << dz << " - de=" << de << endmsg; + + for( const auto& v: mcpart->endVertices() ){ + if(v->position().z() < decay.Z()){ + decay = v->position(); + } + } + + // Check against truth, register if it's indeed from Pi0 + if( isMergedPi0(mcpart) ) isMerged=true; + } + + // Collect good signal + if ( de < m_de && ((m_dr<0)||(dr<m_dr)) && ((m_dz<0)||(dz<m_dz)) && isPhoton && !isMerged){ + m_nPhotons++; + isSignal = true; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Candidate is Signal according to MC" << endmsg; + } else { + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() <<"Candidate is Background according to MC (photon, merged)" << isPhoton << " " << isMerged << endmsg; + } + + // Efficiency and purity versus pt + if( likelihood > m_lhcut ){ + int ibin = int(m_nbinpt*(momentum.momentum().pt()-m_ptmin)/(m_ptmax-m_ptmin)); + if( ibin>=0 && ibin<m_nbinpt ){ + if (isSignal) {m_rec_sig[ibin]++;} + else {m_rec_bkg[ibin]++;} + } + } + + // Efficiency and purity versus likelihood + int lhbin = int(likelihood*double(m_nbinlh)); + for( int l=0; l<lhbin; l++ ){ + if (isSignal) { + m_lh_recsig[l]++; + if (eSpd>1.){m_lh_recsig_spd[l]++;} + else {m_lh_recsig_nospd[l]++;} + if (decay.Z()>m_zConv) {m_lh_recsig_noconv[l]++;} + else {m_lh_recsig_conv[l]++;} + } else { + m_lh_recbkg[l]++; + if (eSpd>1.){m_lh_recbkg_spd[l]++;} + else {m_lh_recbkg_nospd[l]++;} + } + } + + // Fill General Monitoring histograms + if (isSignal){ + if (eSpd>1.){ + fill(m_lhSigSpd,likelihood,1.); + } else{ + fill(m_lhSig,likelihood,1.); + } + } + else{ + if (eSpd>1.){ + fill(m_lhBkgSpd,likelihood,1.); + } else{ + fill(m_lhBkg,likelihood,1.); + } + } + + if (m_pdf) { + double eTransf = transform ( energy ); + if (isSignal){ + if (eSpd>1.){ + fill(m_signalEPrsSpd2D [ m_area ], ePrs , eTransf,1.); + fill(m_signalChi2Spd2D [ m_area ], chi2 , eTransf,1.); + fill(m_signalSeedSpd2D [ m_area ], eSeed, eTransf,1.); + } else { + fill(m_signalEPrs2D [ m_area ], ePrs , eTransf,1.); + fill(m_signalChi22D [ m_area ], chi2 , eTransf,1.); + fill(m_signalSeed2D [ m_area ], eSeed, eTransf,1.); + } + } else { + if (eSpd>1.){ + fill(m_backgrEPrsSpd2D [ m_area ], ePrs , eTransf,1.); + fill(m_backgrChi2Spd2D [ m_area ], chi2 , eTransf,1.); + fill(m_backgrSeedSpd2D [ m_area ], eSeed, eTransf,1.); + } + else { + fill(m_backgrEPrs2D [ m_area ], ePrs , eTransf,1.); + fill(m_backgrChi22D [ m_area ], chi2 , eTransf,1.); + fill(m_backgrSeed2D [ m_area ], eSeed, eTransf,1.); + } + } + } + } // End loop over hypo + + return; // StatusCode::SUCCESS; +} + +// ============================================================================= + +std::vector<AIDA::IHistogram2D*> CaloFuturePhotonChecker::defHisto( + const unsigned int bin, const double xmin, const double xmax, + const unsigned int nhisto, std::string hname){ + + std::vector<AIDA::IHistogram2D*> histoList; + char histoname[60]; + + for (unsigned int area=0; area<3; ++area){ + AIDA::IHistogram2D* histo; + sprintf(histoname,"%s_%i",hname.c_str(),nhisto+area); + histo = book2D(histoname,histoname, + (int)(xmin),(int)(xmax),bin, + 0., 6.,6); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() <<"booking Histo ..."<<histoname<<endmsg; + histoList.push_back(histo); + } + return histoList; +} + + +// ============================================================================= + +// Return True if the given mcparticle +bool CaloFuturePhotonChecker::isMergedPi0( const LHCb::MCParticle* mcpart ) const { + bool isMerged = false; + const auto mother = mcpart->mother(); + if( mother != nullptr ){ + if( m_pi0ID == mother->particleID() ){ + const auto decayPi0 = mcpart->originVertex(); + const auto products = decayPi0->products(); + if( products.size() == 2 ){ + for( const auto& pi0daughter: products ){ + if( mcpart == pi0daughter ) {continue;} + const Line line1( decayPi0->position(), mcpart->momentum().Vect() ); + const Line line2( decayPi0->position(), pi0daughter->momentum().Vect() ); + const auto hit1 = intersection(line1, m_ecalPlane); + const auto hit2 = intersection(line2, m_ecalPlane); + const auto distance = (hit1 - hit2).R(); + const double param = m_mergedDist*(m_ecal->cellSize(m_ecal->Cell( hit1 ))+ + m_ecal->cellSize(m_ecal->Cell( hit2 )))/2.; + if( distance<param ){ + isMerged = true; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Pi0->Merged Photon : distance=" << distance + << " < Criteria=" << param << " mm" << endmsg; + } + } + } + } + } + return isMerged; +} diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFuturePhotonChecker.h b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePhotonChecker.h new file mode 100644 index 0000000000000000000000000000000000000000..289fd8f8784491a3780118ed0fbd0728dd2fc72b --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePhotonChecker.h @@ -0,0 +1,146 @@ +#ifndef CALOFUTUREPHOTONCHECKER_H +#define CALOFUTUREPHOTONCHECKER_H 1 + +// Includes +#include "GaudiAlg/Consumer.h" +#include "LHCbMath/Line.h" +#include "Event/Track.h" +#include "Event/MCParticle.h" +#include "Relations/RelationWeighted.h" +#include "Relations/Relation.h" +#include "CaloFutureMoniAlg.h" + +// Aliases +using Input = LHCb::CaloHypo::Container; +using MCPs = LHCb::MCParticles; +using Table = Relations::RelationWeighted<LHCb::CaloCluster,LHCb::Track,float>; +using MCTable = Relations::RelationWeighted<LHCb::CaloCluster,LHCb::MCParticle,float>; +using IDTable = Relations::Relation<LHCb::CaloHypo,float>; +using Line = Gaudi::Math::Line<Gaudi::XYZPoint,Gaudi::XYZVector>; + + +// ============================================================================= + +/** @class CaloFuturePhotonChecker CaloFuturePhotonChecker.h + * + * Photon Selection Monitoring + * (LHCb 2004-03) + * + * @author Frederic Machefert frederic.machefert@in2p3.fr + * @date 2004-15-04 + */ + +class CaloFuturePhotonChecker final +: public Gaudi::Functional::Consumer<void(const Input&, const MCPs&, const Table&, const MCTable&, const IDTable&), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureMoniAlg>> +{ +public: + // GaudiAlgorithm + StatusCode initialize() override; + StatusCode finalize () override; + + // Gaudi::Functional + void operator()(const Input&, const MCPs&, const Table&, const MCTable&, const IDTable&) const override; + + CaloFuturePhotonChecker( const std::string& name, ISvcLocator* pSvc ); + +protected: + std::vector<AIDA::IHistogram2D*> defHisto(const unsigned int, + const double, const double, + const unsigned int, + const std::string); + + bool isMergedPi0( const LHCb::MCParticle* ) const; + +private: + // FutureCounters + mutable unsigned int m_nEvents = 0; + mutable unsigned int m_nCandidates = 0; + mutable unsigned int m_nPhotons = 0; + mutable unsigned int m_nMCPhotons = 0; + mutable unsigned int m_nWrongs = 0; + + // more counters + mutable std::vector<double> m_mc_g; + mutable std::vector<double> m_rec_bkg; + mutable std::vector<double> m_rec_sig; + mutable double m_lh_mcg; + mutable std::vector<double> m_lh_recsig; + mutable std::vector<double> m_lh_recbkg; + mutable double m_lh_mcg_conv; + mutable std::vector<double> m_lh_recsig_conv; + mutable std::vector<double> m_lh_recsig_spd; + mutable std::vector<double> m_lh_recbkg_spd; + mutable double m_lh_mcg_noconv; + mutable std::vector<double> m_lh_recsig_noconv; + mutable std::vector<double> m_lh_recsig_nospd; + mutable std::vector<double> m_lh_recbkg_nospd; + + // Detector Information + DeCalorimeter* m_ecal = nullptr; + DeCalorimeter* m_spd = nullptr; + DeCalorimeter* m_prs = nullptr; + + Gaudi::Plane3D m_ecalPlane; + Gaudi::Plane3D m_prsPlane; + Gaudi::Plane3D m_spdPlane; + + double m_zConv = 0.; + + // Tools + std::string m_IDTableName = LHCb::CaloFutureIdLocation::PhotonID; + + // Particle Properties + std::string m_gammaName {"gamma"}; + LHCb::ParticleID m_gammaID {0}; + std::string m_pi0Name {"pi0"}; + LHCb::ParticleID m_pi0ID {0}; + + // histogramming related variables + Gaudi::Property<bool> m_pdf {this, "Pdf", false}; + Gaudi::Property<std::vector<double>> m_prsbin {this, "EPrsBin", {50,0.,200.}}; + Gaudi::Property<std::vector<double>> m_chi2bin {this, "Chi2Bin", {26,0.,104.}}; + Gaudi::Property<std::vector<double>> m_seedbin {this, "SeedBin", {50,0.,1. }}; + + // Signal/background definitions + Gaudi::Property<float> m_etmin { this, "Etmin" , 200.*Gaudi::Units::MeV}; + Gaudi::Property<float> m_dr { this, "Dr" , -1.}; + Gaudi::Property<float> m_dz { this, "Dz" , -1.}; + Gaudi::Property<float> m_de { this, "DE" , 0.25}; + Gaudi::Property<float> m_mergedDist { this, "MergedDist", 1.5}; + + // histograms + + AIDA::IHistogram1D* m_lhSig = nullptr; + AIDA::IHistogram1D* m_lhSigSpd = nullptr; + AIDA::IHistogram1D* m_lhBkg = nullptr; + AIDA::IHistogram1D* m_lhBkgSpd = nullptr; + + Gaudi::Property<int> m_nbinlh {this, "LhNBin", 20}; + AIDA::IHistogram2D* m_effpur = nullptr; + AIDA::IHistogram2D* m_effpur_spd = nullptr; + AIDA::IHistogram2D* m_effpur_nospd = nullptr; + + Gaudi::Property<int> m_nbinpt { this, "PtNBin" , 20}; + Gaudi::Property<float> m_lhcut { this, "LhCut" , 0.3}; + Gaudi::Property<float> m_ptmin { this, "PtMinHisto", 0. *Gaudi::Units::MeV}; + Gaudi::Property<float> m_ptmax { this, "PtMaxHisto", 10.*Gaudi::Units::GeV}; + AIDA::IHistogram1D* m_efficiency = nullptr; + AIDA::IHistogram1D* m_purity = nullptr; + + std::vector<AIDA::IHistogram2D*> m_signalEPrs2D; + std::vector<AIDA::IHistogram2D*> m_backgrEPrs2D; + std::vector<AIDA::IHistogram2D*> m_signalChi22D; + std::vector<AIDA::IHistogram2D*> m_backgrChi22D; + std::vector<AIDA::IHistogram2D*> m_signalSeed2D; + std::vector<AIDA::IHistogram2D*> m_backgrSeed2D; + + std::vector<AIDA::IHistogram2D*> m_signalEPrsSpd2D; + std::vector<AIDA::IHistogram2D*> m_backgrEPrsSpd2D; + std::vector<AIDA::IHistogram2D*> m_signalChi2Spd2D; + std::vector<AIDA::IHistogram2D*> m_backgrChi2Spd2D; + std::vector<AIDA::IHistogram2D*> m_signalSeedSpd2D; + std::vector<AIDA::IHistogram2D*> m_backgrSeedSpd2D; +}; + +#endif // CALOFUTUREPHOTONCHECKER_H diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Checker.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Checker.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8f96f27ab33458efe390e663b6c7ff7e48cd981a --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Checker.cpp @@ -0,0 +1,157 @@ +// Includes +#include "GaudiAlg/Consumer.h" +// #include "Relations/IRelationWeighted.h" +#include "Relations/RelationWeighted.h" +#include "Kernel/IParticlePropertySvc.h" +#include "Kernel/ParticleProperty.h" +#include "Event/CaloHypo.h" +#include "Event/MCParticle.h" +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureUtils/CaloMomentum.h" +#include "CaloFutureUtils/ClusterFunctors.h" +#include "CaloFutureMoniAlg.h" +#include "Relations/RelationWeighted1D.h" + +// ============================================================================ + +/** @class CaloFuturePi0Checker CaloFuturePi0Checker.cpp + * + * Simple MC pi0 monitoring algorithm + * It produces 2 histograms + * <ol> + * <li> "Raw" mass distribution of 2 photons </li> + * <li> Mass distribution of 2 photons after Pt cut for each photon </li> + * <li> Mass distribution of 2 photons after Pt cut for combination </li> + * </ol> + * + * @see CaloFutureAlgorithm + * @see Algorithm + * @see IAlgorithm + * + * @author Vanya BELYAEV Ivan.Belyaev@itep.ru + * @date 02/11/2001 + */ + +using Input = LHCb::RelationWeighted1D<LHCb::CaloCluster,LHCb::MCParticle,float>; +using Inputs = LHCb::CaloHypo::Container; +using Photon = const LHCb::CaloHypo; + +class CaloFuturePi0Checker final +: public Gaudi::Functional::Consumer<void(const Input&, const Inputs&), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureMoniAlg>> +{ +public: + StatusCode initialize() override; + void operator()(const Input&, const Inputs&) const override; + + CaloFuturePi0Checker( const std::string &name, ISvcLocator *pSvcLocator ); + +private: + LHCb::ClusterFunctors::ClusterFromCaloFuture m_calo = DeCalorimeterLocation::Ecal; + + LHCb::ParticleID m_pi0ID{0}; + + Gaudi::Property<float> m_cut { this, "Cut", float(50 * Gaudi::Units::perCent), "photon purity cut"}; + + Gaudi::Property<std::string> m_pi0Name {this, "Ancestor", "pi0"}; +}; + +// ============================================================================= + +DECLARE_COMPONENT( CaloFuturePi0Checker ) + +// ============================================================================= + +CaloFuturePi0Checker::CaloFuturePi0Checker( const std::string &name, ISvcLocator *pSvcLocator ) +: Consumer( name, pSvcLocator, { + KeyValue{ "Input" , "Relations/"+LHCb::CaloClusterLocation::Default }, + KeyValue{ "Inputs", LHCb::CaloHypoLocation::Photons } +}){ + // set the appropriate defualt value for detector data + setDetData( DeCalorimeterLocation::Ecal ); +} + +// ============================================================================= + +StatusCode CaloFuturePi0Checker::initialize(){ + StatusCode sc = Consumer::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; // error already printedby GaudiAlgorithm + + // re-initialize the Ecal cluster selector + m_calo.setCaloFuture( detData() ); + + // locate particle eproperty service + auto ppS = svc<LHCb::IParticlePropertySvc>( "LHCb::ParticlePropertySvc", true ); + if ( 0 == ppS ) return StatusCode::FAILURE; + + const auto pp = ppS->find( m_pi0Name ); + if ( pp == nullptr ) return Error( "Could not locate particle '"+m_pi0Name+"'" ); + m_pi0ID = pp->pid(); + + hBook1( "1", "Gamma-Gamma mass " , 0, 1, 500 ); + hBook1( "2", "Gamma-Gamma mass (MCpi0 match)" , 0, 1, 500 ); + if( m_split ){ + Warning( "No area spliting allowed for CaloFuturePi0Checker").ignore(); + m_split = false; + } + return StatusCode::SUCCESS; +} + +// ============================================================================= + +void CaloFuturePi0Checker::operator()(const Input& table, const Inputs& photons ) const { + + using namespace LHCb::ClusterFunctors; + + // loop over the first photon + for( auto g1 = photons.begin(); photons.end() != g1; ++g1 ){ + Photon *photon1 = *g1; + if ( photon1 == nullptr ) continue; + LHCb::CaloMomentum momentum1( photon1 ); + + // get Ecal cluster + const auto clusters1 = photon1->clusters(); + if ( clusters1.empty() ) continue; + const auto cluster1 = ( 1 == clusters1.size() ) ? clusters1.begin() : + std::find_if( clusters1.begin(), clusters1.end(), m_calo ); + if ( clusters1.end() == cluster1 ) continue; + + // get all MCtruth information for this cluster + const float cut1 = (float) ((*cluster1)->e() * m_cut); + const auto range1 = table.relations( *cluster1, cut1, true ); + + // loop over the second photon + for( auto g2 = g1 + 1; photons.end() != g2; ++g2 ){ + Photon *photon2 = *g2; + if ( photon2 == nullptr ) continue; + LHCb::CaloMomentum momentum2( photon2 ); + + // get Ecal cluster + const auto clusters2 = photon2->clusters(); + if ( clusters2.empty() ) continue; + auto cluster2 = ( 1 == clusters2.size() ) ? clusters2.begin() : + std::find_if( clusters2.begin(), clusters2.end(), m_calo ); + if ( clusters2.end() == cluster2 ) continue; + + // get all MCtruth information for this cluster + const float cut2 = (float)((*cluster2)->e() * m_cut); + const auto range2 = table.relations( *cluster2, cut2, true ); + + // double loop for search the common ancestor + LHCb::MCParticle *pi0 = nullptr; + for( auto mc1 = range1.begin();( pi0 == nullptr ) && ( range1.end() != mc1 ); ++mc1 ){ + if ( mc1->to() == nullptr ) continue; + for ( auto mc2 = range2.begin(); ( pi0 == nullptr ) && ( range2.end() != mc2 ); ++mc2 ){ + if ( mc1->to() != mc2->to() ) continue; // common ancestor? + if ( m_pi0ID == mc1->to()->particleID() ) pi0 = mc1->to(); + } // end of second MC loop + } // end of first MC loop + + const double mass = (momentum1.momentum()+momentum2.momentum()).mass(); + hFill1( "1", mass/Gaudi::Units::GeV ); + if ( pi0 == nullptr ) continue; + hFill1( "2", mass/Gaudi::Units::GeV ); + } // end of loop over second photon + } // end of loop over first photon + return; // StatusCode::SUCCESS; +} diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Monitor.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Monitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..037c5b97b88a98441753b7e963e2686cea976557 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Monitor.cpp @@ -0,0 +1,206 @@ +// Includes +#include "GaudiAlg/Consumer.h" +#include <vector> +#include "Event/Particle.h" +#include "Event/CaloHypo.h" +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureUtils/CaloMomentum.h" +#include "CaloFutureUtils/CaloFutureParticle.h" +#include "CaloFutureInterfaces/ICaloFutureHypo2CaloFuture.h" +#include "CaloFutureMoniAlg.h" + +namespace { + // hack to allow for tools with non-const interfaces... + template <typename IFace> + IFace* fixup(const ToolHandle<IFace>& iface) { return &const_cast<IFace&>(*iface); } +} + +// ============================================================================= + +/** @class CaloFuturePi0Monitor CaloFuturePi0Monitor.cpp + * + * Simple pi0 monitoring algorithm + * + * @see CaloFutureMoniAlg + * @see GaudiHistoAlg + * @see GaudiAlgorithm + * @see Algorithm + * @see IAlgorithm + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 02/11/2001 + */ + +using Input = LHCb::CaloHypo::Container; + +class CaloFuturePi0Monitor final +: public Gaudi::Functional::Consumer<void(const Input&), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureMoniAlg>> +{ +public: + StatusCode initialize() override; + void operator()(const Input&) const override; + + CaloFuturePi0Monitor( const std::string &name, ISvcLocator *pSvcLocator ); + +private: + DeCalorimeter* m_calo = nullptr; + ToolHandle<ICaloFutureHypo2CaloFuture> m_toSpd{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Spd", this}; + ToolHandle<ICaloFutureHypo2CaloFuture> m_toPrs{"CaloFutureHypo2CaloFuture/CaloFutureHypo2Prs", this}; + + bool valid_photon(const LHCb::CaloHypo* g) const; + + Gaudi::Property<float> m_ptPhoton { this, "PhotonPtFilter" , 250 * Gaudi::Units::MeV}; + Gaudi::Property<float> m_ptMaxPhoton { this, "PhotonMaxPtFilter" , 0}; + Gaudi::Property<float> m_isol { this, "IsolationFilter" , 4}; + Gaudi::Property<float> m_prsPhoton { this, "PhotonPrsFilterMin", 10*Gaudi::Units::MeV}; + Gaudi::Property<float> m_yCut { this, "RejectedYBand" , 300}; + Gaudi::Property<bool> m_conv { this, "AllowConverted" , false}; +}; + +// ============================================================================= + +DECLARE_COMPONENT( CaloFuturePi0Monitor ) + +// ============================================================================= + +CaloFuturePi0Monitor::CaloFuturePi0Monitor( const std::string &name, ISvcLocator *pSvcLocator ) +: Consumer( name, pSvcLocator, KeyValue{ "Input", "" } ) +{ + m_multMax = 150; + const auto Input = LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation("Photons",context()); + updateHandleLocation( *this, "Input", Input ); +} + +// ============================================================================= + +StatusCode CaloFuturePi0Monitor::initialize(){ + StatusCode sc = Consumer::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; // error already printedby GaudiAlgorithm + hBook1( "1", "(gg) multiplicity " + inputLocation() , m_multMin , m_multMax , m_multBin ); + hBook1( "2", "(gg) energy " + inputLocation() , m_energyMin, m_energyMax, m_energyBin ); + hBook1( "3", "(gg) et " + inputLocation() , m_etMin , m_etMax , m_etBin ); + hBook1( "4", "(gg) mass " + inputLocation() , m_massMin , m_massMax , m_massBin ); + hBook1( "5", "(gg) combinatorial background" + inputLocation() , m_massMin , m_massMax , m_massBin ); + hBook1( "6", "bkg-substracted (gg) mass " + inputLocation() , m_massMin , m_massMax , m_massBin ); + hBook1( "7", "(gg) mass for |y|-gamma > " + Gaudi::Utils::toString(m_yCut) + " " + + inputLocation() , m_massMin , m_massMax , m_massBin ); + hBook2( "8", "(gg) mass per cell " + inputLocation(), 0, 6016, 6016, m_massMin , m_massMax , m_massBin ); + + // Get, retrieve, configure tools + m_calo = getDet<DeCalorimeter>(DeCalorimeterLocation::Ecal); + if(!( m_toSpd.retrieve() && m_toPrs.retrieve() )){ + error() << "Unable to retrive one of the ToolHandles" << endmsg; + return StatusCode::FAILURE; + } + m_toSpd->setCalos( "Ecal" ,"Spd"); + m_toPrs->setCalos( "Ecal" ,"Prs"); + + // set mass window to histo range + m_massFilterMin = m_massMin; + m_massFilterMax = m_massMax; + + return StatusCode::SUCCESS; +} + +// ============================================================================= + +void CaloFuturePi0Monitor::operator()(const Input& photons) const { + + if ( !produceHistos() ) return; + if ( photons.empty() ) return; + + // Params for lookup later down the loop + const auto& cells = m_calo->cellParams(); + + // loop over the first photon + initFutureCounters(); + for( auto g1 = photons.begin(); photons.end() != g1; ++g1 ){ + if( !valid_photon(*g1) ) continue; + LHCb::CaloMomentum momentum1( *g1 ); + Gaudi::LorentzVector v1( momentum1.momentum() ); + + // loop over the second photon + for( auto g2 = std::next(g1); photons.end() != g2; ++g2 ){ + if( !valid_photon(*g2) ) continue; + LHCb::CaloMomentum momentum2( *g2 ); + if( std::max(momentum1.pt(),momentum2.pt()) < m_ptMaxPhoton) continue; + Gaudi::LorentzVector v2( momentum2.momentum() ); + + // background shape from (x,y)->(-x,-y) symmetrized g2 + Gaudi::LorentzVector v2Sym( v2 ); + v2Sym.SetPx( -v2.Px() ); + v2Sym.SetPy( -v2.Py() ); + Gaudi::LorentzVector bkg( v1 + v2Sym ); + Gaudi::XYZPoint p2Sym( -(*g2)->position()->x() , -(*g2)->position()->y() , (*g2)->position()->z() ); + bool isBkg = ( bkg.e() > m_eFilter && + bkg.pt() > m_etFilter && + bkg.mass() > m_massFilterMin && + bkg.mass() < m_massFilterMax ); + + // check pi0 + Gaudi::LorentzVector pi0( v1 + v2 ); + bool isPi0 = ( pi0.e() > m_eFilter && + pi0.pt() > m_etFilter && + pi0.mass() > m_massFilterMin && + pi0.mass() < m_massFilterMax ); + + if( !isPi0 && !isBkg) continue; + + // Get cellIDs + auto id1 = LHCb::CaloCellID(); + auto id2 = LHCb::CaloCellID(); + if ( (*g1)->clusters().size() > 0 ){ + const auto cluster = *((*g1)->clusters().begin()); + if( cluster != 0 ) id1 = cluster->seed(); + } + if ( (*g2)->clusters().size() > 0 ){ + const auto cluster = *((*g2)->clusters().begin()); + if( cluster != 0 ) id2 = cluster->seed(); + } + + // define pi0 area + const auto id = (id1.area() == id2.area() ) ? id1 : LHCb::CaloCellID(); + + // isolation criteria + Gaudi::XYZPoint p1( (*g1)->position()->x() , (*g1)->position()->y() , (*g1)->position()->z() ); + Gaudi::XYZPoint p2( (*g2)->position()->x() , (*g2)->position()->y() , (*g2)->position()->z() ); + const auto vec = p2 - p1; + const auto vecSym = p2Sym - p1; + const auto cSize = std::max( m_calo->cellSize(id1), m_calo->cellSize(id2) ); + const auto isol = (cSize > 0) ? vec.Rho() / cSize : 0; + const auto isolSym = (cSize > 0) ? vecSym.Rho() / cSize : 0; + const auto y1 = m_calo->cellCenter(id1).Y(); + const auto y2 = m_calo->cellCenter(id2).Y(); + + if( isPi0 && isol > m_isol){ + count(id); + hFill1(id, "2", pi0.e() ); + hFill1(id, "3", pi0.pt() ); + hFill1(id, "4", pi0.mass()); + hFill1(id, "6", pi0.mass(), 1.); + if( fabs(y1) > m_yCut && fabs(y2) > m_yCut )hFill1("7",pi0.mass(), 1.); + int index = cells.index( id ); + hFill2("8", index, pi0.mass() ); + } + if( isBkg && isolSym > m_isol){ + hFill1(id, "5", bkg.mass()); + hFill1(id, "6", bkg.mass(), -1.); + } + } + } + fillFutureCounters("1"); + return; // StatusCode::SUCCESS; +} + +// ============================================================================= + +bool CaloFuturePi0Monitor::valid_photon(const LHCb::CaloHypo* g) const { + // Return True if this photon is valid to continue the computation + if( g == nullptr ) return false; + if( !m_conv && fixup(m_toSpd)->multiplicity( *g , "Spd" ) > 0 ) return false; + if( fixup(m_toPrs)->energy ( *g, "Prs" ) < m_prsPhoton ) return false; + LHCb::CaloMomentum momentum( g ); + if(momentum.pt() < m_ptPhoton) return false; + return true; +} diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Ntp.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Ntp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c48e61e94876d923add9c0e5e510b8a946e6004f --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Ntp.cpp @@ -0,0 +1,349 @@ +// Includes +// #include "Event/CaloFutureHypo.h" +#include "CaloFutureUtils/CaloMomentum.h" +#include "CaloFuturePi0Ntp.h" +#include "CaloFutureMoniUtils.h" + +namespace { + /// hack to allow for tools with non-const interfaces... + template <typename IFace> + IFace* fixup(const ToolHandle<IFace>& iface) { return &const_cast<IFace&>(*iface); } +} +// ============================================================================= + +DECLARE_COMPONENT( CaloFuturePi0Ntp ) + +namespace { + // Return new 4D LorentzVector with first-3 spatial components normalized to 1 + // and the last component equal to 1. The space norm ==1, the 4dnorm==0. + Gaudi::LorentzVector normalize( Gaudi::XYZPoint v3 ){ + return Gaudi::LorentzVector{ v3.X()/v3.R(), v3.Y()/v3.R(), v3.Z()/v3.R(), 1. }; + } +} + +// ============================================================================= + +CaloFuturePi0Ntp::CaloFuturePi0Ntp( const std::string &name, ISvcLocator *pSvcLocator ) +: Consumer( name, pSvcLocator, { KeyValue{ "InputODIN", LHCb::ODINLocation::Default }, + KeyValue{ "InputL0" , LHCb::L0DUReportLocation::Default }, + KeyValue{ "Locations", LHCb::CaloHypoLocation::Photons }, + KeyValue{ "VertexLoc", "" } } ) +{} + +// ============================================================================= + +StatusCode CaloFuturePi0Ntp::initialize(){ + StatusCode sc = GaudiTupleAlg::initialize(); + if ( sc.isFailure() ) return sc; + + // retrieve & configure tools + m_calo = getDet<DeCalorimeter>(DeCalorimeterLocation::Ecal); + if(!( m_counterStat.retrieve() + && m_odin.retrieve() + && m_toSpd.retrieve() + && m_toPrs.retrieve() )){ + error() << "Unable to retrive one of the ToolHandles" << endmsg; + return StatusCode::FAILURE; + } + m_toSpd->setCalos( "Ecal" ,"Spd"); + m_toPrs->setCalos( "Ecal" ,"Prs"); + + // set vertex location + auto vertLoc = inputLocation<3>(); // <-- Careful with the index, 'VertexLoc' is 4th. + if(vertLoc.empty()) { + vertLoc = ( m_usePV3D ? LHCb::RecVertexLocation::Velo3D + : LHCb::RecVertexLocation::Primary ); + updateHandleLocation( *this, "VertexLoc", vertLoc ); + } + + return StatusCode::SUCCESS; +} + + +// ============================================================================= +// standard execution method +// ============================================================================= + +void CaloFuturePi0Ntp::operator()(const ODIN& odin, const L0& l0, const Hypos& hypos, + const Vertices& verts) const { + + // Collect global info (in pre-Functional implementation, some are optionals) + m_odin->getTime(); + const auto run = odin.runNumber(); + const auto evt = (double) odin.eventNumber(); + const auto tty = odin.triggerType(); + const auto nSpd = (int) l0.dataValue("Spd(Mult)"); + const auto nVert = verts.size(); + if(m_counterStat->isQuiet()) counter("#PV="+ Gaudi::Utils::toString(nVert) + " ["+ inputLocation<3>()+"]")+=1; + + // Start looping over hypos + bool ok = false; + for( auto g1 = hypos.begin(); hypos.end() != g1; ++g1 ){ + const auto p1 = *g1; + if ( p1 == nullptr ) continue; + + LHCb::CaloMomentum mt1( p1 ); + if( !inRange( m_ppt , mt1.pt() ) )continue; + if( !inRange( m_conv , fixup(m_toSpd)->multiplicity ( *p1 , "Spd") ) )continue; + if( !inRange( m_prsE , fixup(m_toPrs)->energy ( *p1 , "Prs" ) ) )continue; + + const auto v1 = momentum(p1); + const auto point1 = position3d(p1); + const auto prs1 = fixup(m_toPrs)->energy( *p1 , "Prs" ); + const auto spd1 = fixup(m_toSpd)->multiplicity( *p1 , "Spd"); + const auto cl1 = firstCluster(p1); + if( cl1 == 0 ) continue; // SmartRef not overload with nullptr yet + + const auto id1 = cl1->seed(); + const auto pos1 = position3d(cl1); + const auto c1 = position4d(cl1); + const auto cc1 = normalize(pos1) * cl1->e(); + const auto ccc1 = normalize(point1) * cl1->e(); + + // loop over the second photon + for( auto g2 = g1 + 1; hypos.end() != g2; ++g2 ){ + const auto p2 = *g2; + if ( p2 == nullptr ) continue; + + LHCb::CaloMomentum mt2( p2 ); + if( !inRange( m_ppt , mt2.pt() ) )continue; + if( !inRange( m_conv , fixup(m_toSpd)->multiplicity ( *p2 , "Spd") ) )continue; + if( !inRange( m_prsE , fixup(m_toPrs)->energy ( *p2 , "Prs" ) ) )continue; + + const auto v2 = momentum(p2); + const auto point2 = position3d(p2); + const auto pi0 = v1 + v2; + + // background shape from (x,y)->(-x,-y) symmetrized g2 + Gaudi::LorentzVector v2Sym( v2 ); + v2Sym.SetPx( -v2.Px() ); + v2Sym.SetPy( -v2.Py() ); + const auto bkg = v1 + v2Sym; + Gaudi::XYZPoint p2Sym( -p2->position()->x() , -p2->position()->y() , p2->position()->z() ); + + bool isBkg = inRange(m_e, bkg.e()) + && inRange(m_pt, bkg.pt()) + && inRange(m_mass, bkg.mass()); + bool isPi0 = inRange(m_e, pi0.e()) + && inRange(m_pt, pi0.pt()) + && inRange(m_mass, pi0.mass()); + + if( !isPi0 && !isBkg ) continue; + + // Get cellIDs + const auto cl2 = firstCluster(p2); + const auto id2 = cl2->seed(); + if( cl2 == 0 ) continue; // SmartRef not overload with nullptr yet + + // isolation criteria + const auto vec = point2 - point1; + const auto vecSym = p2Sym - point1; + const auto cSize = std::max(m_calo->cellSize(id1), m_calo->cellSize(id2)); + const auto isol = (cSize > 0) ? vec.Rho() / cSize : 0; + const auto isolSym = (cSize > 0) ? vecSym.Rho() / cSize : 0; + + isPi0 = isPi0 && inRange( m_isol, isol ); + isBkg = isBkg && inRange( m_isol, isolSym ); + + if( (isPi0 ) || (m_bkg && isBkg ) ){ + + const auto prs2 = fixup(m_toPrs)->energy ( *p2 , "Prs" ); + const auto spd2 = fixup(m_toSpd)->multiplicity ( *p2 , "Spd"); + const auto spd = (spd1>0)*2 + (spd2>0)*1; + const auto pi0m = isPi0 ? pi0.mass() : 0.; + const auto bkgm = isBkg ? bkg.mass() : 0.; + const auto typ = (isPi0)*1 + (isBkg)*2; + const auto c2 = position4d(cl2); + const auto pos2 = position3d(cl2); + const auto cc2 = normalize(pos2) * cl2->e(); + const auto ccc2 = normalize(point2) * cl2->e(); + + // cluster mass + const auto cc = cc1 + cc2; + const auto ccc = ccc1 + ccc2; + const auto ccmas = (isPi0) ? cc.mass() : 0; + const auto cccmas = (isPi0) ? ccc.mass() : 0; + + if(m_counterStat->isQuiet()) counter("candidates for #PV="+ Gaudi::Utils::toString(nVert) + " ["+ inputLocation<3>()+"]")+=1; + + // Write tuple on-demand + if( m_tuple ){ + auto ntp = nTuple(500, "pi0_tupling", CLID_ColumnWiseTuple); + ntp->column( "p1" , v1 ); + ntp->column( "p2" , v2 ); + ntp->column( "r1" , point1 ); + ntp->column( "r2" , point2 ); + ntp->column( "prs1" , prs1 ); + ntp->column( "prs2" , prs2 ); + ntp->column( "spd" , spd ); + ntp->column( "id1" , id1.index() ); + ntp->column( "id2" , id2.index() ); + ntp->column( "cl1" , c1 ); + ntp->column( "cl2" , c2 ); + ntp->column( "mass" , pi0m ); + ntp->column( "type" , typ ); + ntp->column( "p" , pi0 ); + ntp->column( "clmass" , ccmas ); + ntp->column( "clEmass", cccmas ); + if(m_bkg)ntp->column("bkg",bkgm ); + // odin info + ntp->column("run" , run ); + ntp->column("event" , (double) evt ); + ntp->column("triggertype", tty ); + // #vertices + ntp->column("Nvertices", nVert); + // #SpdMult + ntp->column("spdMult", nSpd); + ok = ntp->write().isSuccess(); + } + if( !isPi0 ) continue; + // histograms for tuning + if( m_histo ){ + hTuning("Cluster" , nSpd, spd, prs1, prs2, ccc1, id1, ccc2, id2, nVert ); + hTuning("Corrected", nSpd, spd, prs1, prs2, v1 , id1, v2 , id2, nVert ); + } + if( m_trend && spd == 0){ + std::string sNpv = "PV" + Gaudi::Utils::toString( nVert ) +"/"; + std::string sRun = "r" + Gaudi::Utils::toString( run ) +"/"; + std::string base = "Trend/"; + plot1D(pi0m, base+"allPV/allRun/mass" ,"di-photon mass spectrum for all run & allPV" , m_hMin, m_hMax, m_hBin); + plot1D(pi0m, base+"allPV/"+sRun+"mass","di-photon mass spectrum for all PV & run = "+sRun, m_hMin, m_hMax, m_hBin); + if(id1.area() == id2.area()){ + const auto sarea = id1.areaName() ; + plot1D(pi0m, base+"allPV/"+sRun+sarea,"di-photon mass spectrum for all PV & run = "+sRun, m_hMin, m_hMax, m_hBin); + } + plot1D(pi0m, base+sNpv+sRun+"mass","di-photon mass spectrum for PV="+sNpv+" (run = "+sRun+")", m_hMin, m_hMax, m_hBin); + plot1D(pi0m, base+sNpv+"allRun/mass","di-photon mass spectrum for PV="+sNpv+" (all run)" , m_hMin, m_hMax, m_hBin); + } + } + } + } + if(ok && m_counterStat->isQuiet()) counter("Events in tuple") += 1; + else Warning("Error with ntupling", StatusCode::SUCCESS).ignore(); + return; +} + +//============================================================================== + +void CaloFuturePi0Ntp::hTuning(std::string base, int event_nSpd, int spd, double prs1, double prs2, + const Gaudi::LorentzVector c1, const LHCb::CaloCellID id1, + const Gaudi::LorentzVector c2, const LHCb::CaloCellID id2,int nVert) const { + + + std::string s1 = id1.areaName() ; + std::string s2 = id2.areaName() ; + std::string sarea = ( id1.area() > id2.area() )? s1+s2 : s2+s1; + // log(E) bins + int ble1 = int( (log( c1.e() )/m_leBin) ); + int ble2 = int( (log( c2.e() )/m_leBin) ); + // Et bins + int bet1 = int( c1.Pt() / m_etBin ); + int bet2 = int( c2.Pt() / m_etBin ); + // theta bins + int bth1 = int( c1.Theta() / m_thBin/pow(2.,(double)2-id1.area() )); + int bth2 = int( c2.Theta() / m_thBin/pow(2.,(double)2-id2.area() )); + + // spd bins + int spdslot = int( event_nSpd / m_spdBin ); + + std::string sspd; + if ( spd==0 ) sspd = "gg"; + else if (spd==1 || spd == 2) sspd = "gee"; + else if( spd==3) sspd = "eeee"; + + int prs = 0; + if( prs1 > 5)prs += 1; + if( prs2 > 5)prs += 1; + + const std::string sprs = "prs" + Gaudi::Utils::toString( prs ); + + const auto di = c1+c2; + + // pi0->gg versus nPV + std::string sVert = "PV" + Gaudi::Utils::toString( nVert ); + plot1D(di.mass(), base+"/"+sVert+"/all" , base+"/all #PV="+Gaudi::Utils::toString( nVert ) , m_hMin, m_hMax, m_hBin); + plot1D(di.mass(), base+"/"+sVert+"/"+sspd+"/all" , + base+"/"+sspd+"/all #PV="+Gaudi::Utils::toString( nVert ) , m_hMin, m_hMax, m_hBin); + const double Y1 = m_calo->cellCenter( id1 ).Y(); + const double Y2 = m_calo->cellCenter( id2 ).Y(); + if( fabs(Y1)<300 && fabs(Y2)<300){ + plot1D(di.mass(), base+"/"+sVert+"/band" , base+"/band #PV="+Gaudi::Utils::toString( nVert ) , m_hMin, m_hMax, m_hBin); + plot1D(di.mass(), base+"/"+sVert+"/"+sspd+"/band" , + base+"/"+sspd+"/band #PV="+Gaudi::Utils::toString( nVert ) , m_hMin, m_hMax, m_hBin); + } + + // pi0->gg versus spdMult + std::string nSpd = "Spd" + Gaudi::Utils::toString( spdslot*m_spdBin ); + plot1D(di.mass(), base+"/"+nSpd+"/all" , base+"/all #Spd="+Gaudi::Utils::toString( spdslot*m_spdBin ),m_hMin,m_hMax,m_hBin); + plot1D(di.mass(), base+"/"+nSpd+"/"+sspd+"/all" , + base+"/"+sspd+"/all #Spd="+Gaudi::Utils::toString( spdslot*m_spdBin ),m_hMin,m_hMax,m_hBin); + + if( fabs(Y1)<300 && fabs(Y2)<300){ + plot1D(di.mass(),base+"/"+nSpd+"/band",base+"/band #Spd="+Gaudi::Utils::toString( spdslot*m_spdBin ),m_hMin,m_hMax,m_hBin); + plot1D(di.mass(),base+"/"+nSpd+"/"+sspd+"/band", + base+"/"+sspd+"/band #Spd="+Gaudi::Utils::toString( spdslot*m_spdBin ),m_hMin,m_hMax,m_hBin); + } + + // highPt selection + if( spd == 0 && di.Pt() > 2000 && c1.Pt()>800 && c2.Pt() >800) + plot1D(di.mass(), base+"/all_highPt_sel1" , base+"/all highPt sel1 spd == 0" , m_hMin, m_hMax, m_hBin); + if( spd == 0 && ((c1.Pt()>1050 && c2.Pt() >250) || (c2.Pt()>1050 && c1.Pt() >250)) ) + plot1D(di.mass(), base+"/all_highPt_sel2" , base+"/all highPt sel2 spd == 0" , m_hMin, m_hMax, m_hBin); + + + plot1D(di.mass(), base+"/all" , base+"/all" , m_hMin, m_hMax, m_hBin); + plot1D(di.mass(), base+"/"+sarea+"/all" , base+"/"+sarea+"/all" , m_hMin, m_hMax, m_hBin); + plot1D(di.mass(), base+"/"+sarea+"/"+sspd+"/all" , base+"/"+sarea+"/"+sspd+"/all" , m_hMin, m_hMax, m_hBin); + plot1D(di.mass(), base+"/"+sarea+"/"+sspd+"/"+sprs+"/all" , base+"/"+sarea+"/"+sspd+"/"+sprs+"/all" , m_hMin, m_hMax, m_hBin); + + + std::string u = base +"/" + sarea +"/"+ sspd +"/" + sprs +"/Energy/all"; + std::string u1 = base +"/" + sarea +"/"+ sspd +"/" + sprs +"/Energy/b"+Gaudi::Utils::toString( (double) ble1 * m_leBin ); + std::string u2 = base +"/" + sarea +"/"+ sspd +"/" + sprs +"/Energy/b"+Gaudi::Utils::toString( (double) ble2 * m_leBin ); + plot1D( di.mass(), u1 , u1 , m_hMin, m_hMax, m_hBin); + if( u2 != u1 ) plot1D( di.mass(), u2,u2,m_hMin, m_hMax, m_hBin ); + plot1D( di.mass(), u , u , m_hMin, m_hMax, m_hBin); + + if( (prs1 < 5 && spd == 0 ) || (prs2<5 && spd == 0 ) ){ + std::string tu = base +"/" + sarea +"/EcalTuning/Energy/"; + std::string bin; + if( prs1 < 5 )bin = Gaudi::Utils::toString( (double) ble1*m_leBin ); + else if( prs2<5 )bin = Gaudi::Utils::toString( (double) ble2*m_leBin ); + plot1D( di.mass(), tu+bin , tu+bin , m_hMin, m_hMax, m_hBin ); + plot1D( di.mass(), tu+"all", tu+"all", m_hMin, m_hMax, m_hBin ); + } + + + std::string uu = base +"/" + sarea +"/"+ sspd +"/" + sprs +"/Pt/all"; + std::string uu1 = base +"/" + sarea +"/"+ sspd +"/" + sprs +"/Pt/b"+Gaudi::Utils::toString( (double) bet1 * m_etBin ); + std::string uu2 = base +"/" + sarea +"/"+ sspd +"/" + sprs +"/Pt/b"+Gaudi::Utils::toString( (double) bet2 * m_etBin ); + plot1D( di.mass(), uu1 , uu1 , m_hMin, m_hMax, m_hBin); + if( uu2 != uu1) plot1D( di.mass(), uu2,uu2,m_hMin, m_hMax, m_hBin); + plot1D( di.mass(), uu , uu , m_hMin, m_hMax, m_hBin); + if( (prs1 < 5 && spd == 0) || (prs2<5 && spd == 0) ){ + std::string tu = base +"/" + sarea +"/EcalTuning/Pt/"; + std::string bin; + if( prs1 < 5 ) bin = Gaudi::Utils::toString( (double) bet1*m_etBin ); + else if( prs2<5 ) bin = Gaudi::Utils::toString( (double) bet2*m_etBin ); + plot1D( di.mass(), tu+bin , tu+bin , m_hMin, m_hMax, m_hBin ); + plot1D( di.mass(), tu+"all", tu+"all", m_hMin, m_hMax, m_hBin ); + } + + + std::string uuu = base +"/" + sarea +"/"+ sspd +"/" + sprs + "/Theta/all"; + std::string uuu1 = base +"/" + sarea +"/"+ sspd +"/" + sprs + + "/Theta/b"+Gaudi::Utils::toString( (double) bth1 * m_thBin*pow(2.,(double)2-id1.area())); + std::string uuu2 = base +"/" + sarea +"/"+ sspd +"/" + sprs + + "/Theta/b"+Gaudi::Utils::toString( (double) bth2 * m_thBin*pow(2.,(double)2-id2.area())); + plot1D( di.mass(), uuu1 , uuu1 , m_hMin, m_hMax, m_hBin); + if( uu2 != uu1) plot1D( di.mass(), uuu2,uuu2,m_hMin, m_hMax, m_hBin); + plot1D( di.mass(), uuu , uuu , m_hMin, m_hMax, m_hBin); + if( (prs1 < 5 && spd == 0) || (prs2<5 && spd == 0 ) ){ + std::string tu = base +"/" + sarea +"/EcalTuning/Theta/"; + std::string bin; + if( prs1 < 5 )bin = Gaudi::Utils::toString( (double) bth1 * m_thBin*pow(2.,(double) 2-id1.area()) ); + else if( prs2<5 )bin = Gaudi::Utils::toString( (double) bth2 * m_thBin*pow(2.,(double) 2-id2.area()) ); + plot1D( di.mass(), tu+bin , tu+bin , m_hMin, m_hMax, m_hBin ); + plot1D( di.mass(), tu+"all", tu+"all", m_hMin, m_hMax, m_hBin ); + } +} diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Ntp.h b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Ntp.h new file mode 100644 index 0000000000000000000000000000000000000000..023bab7fcef4fc52b6c505f36761331b82086b0b --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFuturePi0Ntp.h @@ -0,0 +1,70 @@ +// Includes +#include "GaudiAlg/Consumer.h" +#include "GaudiAlg/GaudiTupleAlg.h" +#include "GaudiKernel/IEventTimeDecoder.h" +#include "Event/L0DUReport.h" +#include "Event/ODIN.h" +#include "Event/RecVertex.h" +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureInterfaces/ICaloFutureHypo2CaloFuture.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" + +// List of Consumers dependencies +namespace { + using ODIN = LHCb::ODIN; + using L0 = LHCb::L0DUReport; + using Hypos = LHCb::CaloHypo::Container; + using Vertices = LHCb::RecVertices; +} + +// ============================================================================= + +class CaloFuturePi0Ntp final +: public Gaudi::Functional::Consumer<void(const ODIN&, const L0&, const Hypos&, const Vertices&), + Gaudi::Functional::Traits::BaseClass_t<GaudiTupleAlg>> +{ +public: + /// standard algorithm initialization + CaloFuturePi0Ntp( const std::string& name, ISvcLocator* pSvcLocator ); + StatusCode initialize() override; + void operator()(const ODIN&, const L0&, const Hypos&, const Vertices&) const override; + +private: + void hTuning(std::string, int, int, double, double, + const Gaudi::LorentzVector, const LHCb::CaloCellID , + const Gaudi::LorentzVector, const LHCb::CaloCellID , int nVert) const; + + // Tools + DeCalorimeter* m_calo = nullptr; + ToolHandle<IFutureCounterLevel> m_counterStat { "FutureCounterLevel" }; + ToolHandle<IEventTimeDecoder> m_odin { "OdinTimeDecoder/OdinDecoder", this }; + ToolHandle<ICaloFutureHypo2CaloFuture> m_toSpd { "CaloFutureHypo2CaloFuture/CaloFutureHypo2Spd" , this }; + ToolHandle<ICaloFutureHypo2CaloFuture> m_toPrs { "CaloFutureHypo2CaloFuture/CaloFutureHypo2Prs" , this }; + + Gaudi::Property<std::pair<double,double>> m_ppt + {this, "PhotonPt", {250., 15000.}}; + + Gaudi::Property<std::pair<double,double>> m_isol + {this, "Isolation", {0., 9999.}, "Warning: a cut biases the pi0 mass"}; + + Gaudi::Property<std::pair<int , int>> m_conv { this, "Conversion", { 1 , 1}}; + Gaudi::Property<std::pair<double, double>> m_prsE { this, "PrsE" , { 0. , 9999.}}; + Gaudi::Property<std::pair<double, double>> m_pt { this, "Pt" , { 200., 15000}}; + Gaudi::Property<std::pair<double, double>> m_e { this, "E" , { 0. , 500000}}; + Gaudi::Property<std::pair<double, double>> m_mass { this, "Mass" , { 50. , 900.}}; + + Gaudi::Property<float> m_leBin {this, "leBin", 0.25}; + Gaudi::Property<float> m_etBin {this, "etBin", 150.}; + Gaudi::Property<float> m_thBin {this, "thBin", 0.005}; + + Gaudi::Property<float> m_hMin { this, "hMin" , 0.}; + Gaudi::Property<float> m_hMax { this, "hMax" , 900.}; + Gaudi::Property<int> m_hBin { this, "hBin" , 450}; + Gaudi::Property<int> m_spdBin { this, "spdBin" , 50}; + Gaudi::Property<bool> m_tuple { this, "Tuple" , true}; + Gaudi::Property<bool> m_histo { this, "Histo" , true}; + Gaudi::Property<bool> m_trend { this, "Trend" , false}; + Gaudi::Property<bool> m_usePV3D { this, "UsePV3D" , false}; + Gaudi::Property<bool> m_bkg { this, "Background", false}; + +}; diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureProtoElectronMonitor.cpp b/CaloFuture/CaloFutureMoniDst/src/CaloFutureProtoElectronMonitor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7eef17de49bbeea6356826b236ae96c92a6ab659 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureProtoElectronMonitor.cpp @@ -0,0 +1,219 @@ +// Includes +#include "CaloFutureUtils/CaloMomentum.h" +#include "CaloFutureProtoElectronMonitor.h" + +namespace { + /// hack to allow for tools with non-const interfaces... + template <typename IFace> + IFace* fixup(const ToolHandle<IFace>& iface) { return &const_cast<IFace&>(*iface); } +} +//----------------------------------------------------------------------------- +// Implementation file for class : CaloFutureProtoElectronMonitor +// +// 2009-12-11 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( CaloFutureProtoElectronMonitor ) + + +//============================================================================== +// Standard constructor, initializes variables +//============================================================================== + +CaloFutureProtoElectronMonitor::CaloFutureProtoElectronMonitor( const std::string& name, + ISvcLocator* pSvcLocator) +: Consumer( name , pSvcLocator, + KeyValue{ "Input", LHCb::ProtoParticleLocation::Charged } +) +{ + declareProperty("ExtrapolatorType" , m_extrapolator ) ; + + // Protected vars in parent + m_massFilterMax = 100; + m_multMax = 100; + m_massMin = 0; + m_massMax = 5000; + m_massBin = 500; +} + +//============================================================================== +// Initialization +//============================================================================== + +StatusCode CaloFutureProtoElectronMonitor::initialize() { + StatusCode sc = Consumer::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; // error printed already by GaudiAlgorithm + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "==> Initialize" << endmsg; + + if( !m_tracks.empty() )info() << "Will only look at track type(s) = " << m_tracks.value() << endmsg; + else + info() << "Will look at any track type" << endmsg; + + // Get, retrieve, configure tools + if(!( m_caloElectron.retrieve() && m_extrapolator.retrieve() )){ + error() << "Unable to retrive one of the ToolHandles" << endmsg; + return StatusCode::FAILURE; + } + + // histograms + hBook1( "1", "# of CaloElectron protoP " + inputLocation(), m_multMin , m_multMax , m_multBin ); + hBook1( "2", "CaloElectron protoP Energy " + inputLocation(), m_energyMin , m_energyMax , m_energyBin ); + hBook1( "3", "CaloElectron protoP Pt " + inputLocation(), m_etMin , m_etMax , m_etBin); + hBook2( "4", "CaloElectron protoP barycenter position x vs y " + + inputLocation(), m_xMin, m_xMax, m_xBin, m_yMin, m_yMax, m_yBin); + hBook2( "5", "Energy-weighted CaloElectron protoP barycenter position x vs y " + + inputLocation(),m_xMin,m_xMax, m_xBin, m_yMin, m_yMax, m_yBin); + hBook1( "6", "e/p " + inputLocation(), m_eOpMin , m_eOpMax , m_eOpBin ); + hBook1( "7", "Eprs " + inputLocation(), 0. , 300. , m_energyBin ); + if( m_pairing ){ + hBook1( "8", "m(track pair) " + inputLocation() , m_massMin , m_massMax , m_massBin ); + hBook1( "9", "m(clust pair) " + inputLocation() , m_massMin , m_massMax , m_massBin ); + hBook1( "10", "e/p for M(ee) < " + Gaudi::Utils::toString(m_massFilterMax) + + inputLocation(), m_eOpMin , m_eOpMax , m_eOpBin ); + } + return StatusCode::SUCCESS; +} + +//============================================================================== +// Main execution +//============================================================================== + +bool CaloFutureProtoElectronMonitor::valid_track(const LHCb::ProtoParticle* proto) const { + // Return false if the proto's track fails to meet requested track type + if(m_tracks.empty()) return true; + const auto ptype = (int) proto->track()->type(); + auto valid = [ptype](const auto trtype){return ptype==trtype;}; + return std::any_of( std::begin(m_tracks), std::end(m_tracks), valid ); +} + +void CaloFutureProtoElectronMonitor::operator()(const Input& protos) const { + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "==> Execute" << endmsg; + if ( !produceHistos() ) return; + + initFutureCounters(); + + // Loop over protoparticles + for( auto p = protos.begin(); protos.end() != p ; ++p ){ + const auto proto = *p; + + // Abort if track type mismatched + if( !valid_track(proto) ) continue; + + // Abort if electron casting fail + if( !fixup(m_caloElectron)->set(proto)) continue; + + // Abort if null hypo + const auto hypo = fixup(m_caloElectron)->electron(); + if ( hypo == nullptr ) continue; + + // Abort if energy too low + LHCb::CaloMomentum momentum( hypo ); + const double e = momentum.e(); + const double et = momentum.pt(); + if( e < m_eFilter ) continue; + if( et < m_etFilter ) continue; + const double ePrs = proto->info(LHCb::ProtoParticle::additionalInfo::CaloPrsE, 0.); + if( m_prsCut > 0 && ePrs < m_prsCut ) continue; + + // Retrieve the seed id + auto id = LHCb::CaloCellID(); + if ( hypo->clusters().size() > 0 ){ + SmartRef<LHCb::CaloCluster> cluster = *(hypo->clusters().begin()); + id = cluster->seed(); + } + double eOp = fixup(m_caloElectron)->eOverP(); + + // Fill histograms + count(id); + hFill1(id, "2", e ); + hFill1(id, "3", et ); + const auto position = hypo->position(); + if( position != nullptr ){ + hFill2(id, "4", position->x(),position->y() ); + hFill2(id, "5", position->x(),position->y() , e); + } + hFill1(id, "6", eOp ); + hFill1(id, "7", ePrs ); + + // perform electron pairing + if( !m_pairing ) continue; + + // For electron paring, need an extrapolator tool before continuing + if( m_extrapolator == 0 ){ + Warning("No extrapolator defined").ignore(); + continue; + } + + // Loop over second electron + for( auto pp = p+1 ; protos.end() != pp ; ++pp ){ + const auto proto2 = *pp; + + // Abort if track type mismatched + if( !valid_track(proto2) ) continue; + + // Abort if fail hypo, or duplicate + if( !fixup(m_caloElectron)->set(proto2) ) continue;; + const auto hypo2 = fixup(m_caloElectron)->electron(); + if ( hypo2 == nullptr ) continue; + if( hypo == hypo2 ) continue; + + // filtering proto2 + LHCb::CaloMomentum momentum2( hypo2 ); + const double e2 = momentum2.e(); + const double et2 = momentum2.pt(); + if(e2 < m_eFilter) continue; + if(et2 < m_etFilter) continue; + const double ePrs2 = proto2->info(LHCb::ProtoParticle::additionalInfo::CaloPrsE, 0.); + if( m_prsCut > 0 && ePrs2 < m_prsCut )continue; + + // Combine hypo + LHCb::CaloMomentum momentumSum( hypo ); + momentumSum.addCaloPosition( hypo2 ); + const double caloM = momentumSum.mass(); + + // Validate tracks + const auto t1 = proto->track(); + const auto t2 = proto2->track(); + if( t1 == nullptr || t2 == nullptr ) continue; + if( t1->charge()*t2->charge() != -1 ) continue; + auto st1 = t1->firstState(); + auto st2 = t2->firstState(); + + + // bool accept2 = m_tracks.empty() ? true : false; + // for(std::vector<int>::iterator itr = m_tracks.begin();m_tracks.end() != itr;++itr){ + // if( (int)t2->type() == *itr)accept2=true; + // } + // if( !accept2 )continue; + + // Propagation + StatusCode sc = m_extrapolator->propagate(st1, 0.); + if(sc.isFailure()) Warning("Propagation 1 failed").ignore(); + sc = m_extrapolator->propagate(st2, 0.); + if(sc.isFailure()) Warning("Propagation 2 failed").ignore(); + + // Finally, fill the histos + const auto p1 = st1.momentum(); + const auto p2 = st2.momentum(); + double m2 = p1.R()*p2.R(); + m2 -= p1.X()*p2.X(); + m2 -= p1.Y()*p2.Y(); + m2 -= p1.Z()*p2.Z(); + m2 *= 2; + const double m = (m2>0) ? sqrt(m2) : 0; + hFill1(id, "8", m ); + hFill1(id, "9", caloM ); + if( m2 < m_massFilterMax ){ + hFill1(id, "10", eOp ); + const double eOp2 = fixup(m_caloElectron)->eOverP(); + hFill1(id, "10", eOp2 ); + } + } + } + fillFutureCounters("1"); + return; +} +//============================================================================= diff --git a/CaloFuture/CaloFutureMoniDst/src/CaloFutureProtoElectronMonitor.h b/CaloFuture/CaloFutureMoniDst/src/CaloFutureProtoElectronMonitor.h new file mode 100644 index 0000000000000000000000000000000000000000..968fde0fe9354a0ce61d010f57ecfe1ab9cd9067 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/CaloFutureProtoElectronMonitor.h @@ -0,0 +1,61 @@ +#ifndef CALOFUTUREPROTOELECTRONMONITOR_H +#define CALOFUTUREPROTOELECTRONMONITOR_H 1 + +// Includes +#include "GaudiAlg/Consumer.h" +#include "Event/ProtoParticle.h" +#include "CaloFutureUtils/ICaloFutureElectron.h" +#include "TrackInterfaces/ITrackExtrapolator.h" +#include "CaloFutureMoniAlg.h" + +namespace { + using Input = LHCb::ProtoParticles; +} + +/** @class CaloFutureProtoElectronMonitor CaloFutureProtoElectronMonitor.h + * + * + * @author Olivier Deschamps + * @date 2009-12-11 + */ +class CaloFutureProtoElectronMonitor final +: public Gaudi::Functional::Consumer<void(const Input&), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureMoniAlg>> +{ +public: + /// Standard constructor + CaloFutureProtoElectronMonitor( const std::string& name, ISvcLocator* pSvcLocator ); + StatusCode initialize() override; + void operator()(const Input&) const override; + + /// C++11 non-copyable idiom + CaloFutureProtoElectronMonitor( const CaloFutureProtoElectronMonitor& ) = delete; + CaloFutureProtoElectronMonitor &operator=( const CaloFutureProtoElectronMonitor& ) = delete; + +private: + ToolHandle<ICaloFutureElectron> m_caloElectron { "CaloFutureElectron", this }; + ToolHandle<ITrackExtrapolator> m_extrapolator { "TrackRungeKuttaExtrapolator/Extrapolator", this }; + + bool valid_track(const LHCb::ProtoParticle* proto) const; + + Gaudi::Property<float> m_eOpMin + {this, "HistoEoPMin", 0.}; + + Gaudi::Property<float> m_eOpMax + {this, "HistoEoPMax", 3.}; + + Gaudi::Property<int> m_eOpBin + {this, "HistoEoPBin", 100}; + + Gaudi::Property<float> m_prsCut + {this, "PrsCut", 50.* Gaudi::Units::MeV}; + + Gaudi::Property<bool> m_pairing + {this, "ElectronPairing", false}; + + Gaudi::Property<std::vector<int>> m_tracks + {this, "TrackTypes", + {LHCb::Track::Types::Long, LHCb::Track::Types::Downstream}}; + +}; +#endif // CALOFUTUREPROTOELECTRONMONITOR_H diff --git a/CaloFuture/CaloFutureMoniDst/src/L0CaloFutureScale.cpp b/CaloFuture/CaloFutureMoniDst/src/L0CaloFutureScale.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ae2d861155cd52da75273f63b141ca99992487a6 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/L0CaloFutureScale.cpp @@ -0,0 +1,163 @@ +// Includes +#include "GaudiAlg/Consumer.h" +#include "CaloDet/DeCalorimeter.h" +#include "Event/CaloHypo.h" +#include "Event/CaloDataFunctor.h" +#include "Event/L0CaloCandidate.h" +#include "Event/L0DUBase.h" +#include "CaloFutureUtils/CaloMomentum.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "CaloFutureMoniAlg.h" + +// ============================================================================ + +namespace { + using Input = LHCb::CaloHypo::Container; + using Inputs = LHCb::L0CaloCandidates; + + // Return True if this candidate match with the reference cellID + bool l0calo_match( const LHCb::CaloCellID& id, const LHCb::L0CaloCandidate* cand ){ + const auto l0id = cand->id(); + // abort if area mismatched + if( l0id.area() != id.area() || abs((int)l0id.row()-(int)id.row())>1 || abs((int)l0id.col()-(int)id.col())>1) + return false; + // abort if type mismatched + const auto type = cand->type(); + if( type != L0DUBase::CaloType::Electron && type != L0DUBase::CaloType::Photon) + return false; + // This is the one, stop search + return true; + } +} + +//------------------------------------------------------------------------------ + +class L0CaloFutureScale final +: public Gaudi::Functional::Consumer<void(const Input&, const Inputs&), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureMoniAlg>> +{ +public: + /// standard algorithm initialization + StatusCode initialize() override; + void operator()(const Input&, const Inputs&) const override; + + L0CaloFutureScale( const std::string &name, ISvcLocator *pSvcLocator ); + +private: + Gaudi::Property<int> m_ratBin { this, "RatioMin", 0.2}; + Gaudi::Property<float> m_ratMax { this, "RatioMax", 1.7}; + Gaudi::Property<float> m_ratMin { this, "RatioBin", 150}; + + DeCalorimeter* m_ecal = nullptr; +}; + +// ============================================================================= + +DECLARE_COMPONENT( L0CaloFutureScale ) + +// ============================================================================= + +L0CaloFutureScale::L0CaloFutureScale( const std::string &name, ISvcLocator *pSvcLocator ) +: Consumer( name, pSvcLocator, { + KeyValue{ "Input" , "" }, + KeyValue{ "Inputs", LHCb::L0CaloCandidateLocation::Full }, +}) +{ + /* + * During genconf.exe, the default name "DefaultName" is not well-supported + * by the CaloFutureAlgUtils, returning the null string "" as a location path, + * which will raise exception in `updateHandleLocation` --> `setProperty`. + * To get around this, the location will only be updated outside the genconf. + */ + if( name != "DefaultName" ){ + const auto Input = LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation( name , context() ); + updateHandleLocation( *this, "Input", Input ); + } +} + +// ============================================================================= + +StatusCode L0CaloFutureScale::initialize(){ + StatusCode sc = Consumer::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; // error already printedby GaudiAlgorithm + hBook1( "0", "matched L0Calo type " + inputLocation(), 0 , 2 , 2 ); + h1binLabel("0",1,"L0Electron"); + h1binLabel("0",2,"L0Photon"); + + hBook1( "1", "L0Calo(Et)/CaloHypo(Et) " + inputLocation(), m_ratMin , m_ratMax , m_ratBin ); + hBook1( "2", "L0Calo(Et)/CaloCluster(Et) " + inputLocation(), m_ratMin , m_ratMax , m_ratBin ); + hBook1( "3", "CaloCluster/CaloHypo(Et) " + inputLocation(), m_ratMin , m_ratMax , m_ratBin ); + m_ecal = getDet<DeCalorimeter>( DeCalorimeterLocation::Ecal ); + return StatusCode::SUCCESS; +} + + +// ============================================================================= + +void L0CaloFutureScale::operator()(const Input& hypos, const Inputs& candidates) const { + + // produce histos ? + if ( !produceHistos() ) return; + + // check data + if ( hypos.empty() ){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Found empty hypos at " << inputLocation() << endmsg; + return; // StatusCode::SUCCESS; + } + + // Begin loop + initFutureCounters(); + for( const auto& hypo: hypos ){ + + // Abort if ET too low + LHCb::CaloMomentum momentum( hypo ); + const double et = momentum.pt(); + if(et < m_etFilter) continue; + + // Abort if no clusters found + if( hypo->clusters().size() == 0 ) continue; + + // Retrieve the first cluster ID + // SmartRef<LHCb::CaloCluster> cluster; + const auto cluster = *(hypo->clusters().begin()); + const auto id = cluster->seed(); + + // L0Calo matching + LHCb::L0CaloCandidate* cand = nullptr; + for( auto* cand0: candidates ){ + // This is the one, stop search + if( l0calo_match( id, cand )){ + cand = cand0; + break; + } + } + + // Abort if not found + if( cand == nullptr ){ + if( m_counterStat->isQuiet()) counter("Matching L0cluster not found")+=1; + continue; + } + + const auto l0et = cand->etCode(); + const auto type = cand->type(); + + // Calculate & fill histogram + if( m_counterStat->isQuiet()) counter("Matching L0type") += type; + double hratio = 20.*double(l0et) / et; + double cratio = 20.*double(l0et) / (cluster->e() * m_ecal->cellSine( id )) ; + double ratio = (cluster->e() * m_ecal->cellSine( id )) / et; + + count(id); + hFill1(id, "0", type ); + hFill1(id, "1", hratio ); + hFill1(id, "2", cratio ); + hFill1(id, "3", ratio ); + + if(doHisto("4"))fillCaloFuture2D("4", id, hratio, "L0Cluster(Et)/CaloHypo(Et) 2Dview" ); + if(doHisto("5"))fillCaloFuture2D("5", id, cratio, "L0Cluster(Et)/CaloCuster(Et) 2Dview" ); + if(doHisto("6"))fillCaloFuture2D("6", id, cratio, "CaloCluster(Et)/CaloHypo(Et) 2Dview" ); + } + + return; +} diff --git a/CaloFuture/CaloFutureMoniDst/src/SpdMonitorFuture.cpp b/CaloFuture/CaloFutureMoniDst/src/SpdMonitorFuture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9c220b59e0f48d6433a57a4b6381e9c9352c6d23 --- /dev/null +++ b/CaloFuture/CaloFutureMoniDst/src/SpdMonitorFuture.cpp @@ -0,0 +1,105 @@ +// Includes +#include "GaudiAlg/Consumer.h" +#include "Event/CaloDigit.h" +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureMoniAlg.h" + +// using namespace LHCb; +// using namespace Gaudi::Units; + +//============================================================================== +/** @file + * + * Implementation file for class SpdMonitorFuture + * + * SPD Monitoring + * + * @author Albert Puig apuignav@cern.ch + * @date 2007-15-07 + */ +//============================================================================== + +using Input = LHCb::CaloDigits; + +class SpdMonitorFuture final +: public Gaudi::Functional::Consumer<void(const Input&), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureMoniAlg>> +{ +public: + StatusCode initialize() override; + StatusCode finalize() override; + void operator()(const Input&) const override; + + SpdMonitorFuture( const std::string& name, ISvcLocator* pSvc ); + +private: + DeCalorimeter *m_detSpd = nullptr; + CaloVector<int> m_neighN; + mutable unsigned int m_nEvents = 0; +}; + +//============================================================================== + +DECLARE_COMPONENT( SpdMonitorFuture ) + +//============================================================================== + +SpdMonitorFuture::SpdMonitorFuture( const std::string &name, ISvcLocator *pSvcLocator ) +: Consumer( name, pSvcLocator, { + KeyValue{ "Input", LHCb::CaloDigitLocation::Spd }, +}){ + m_split=true; // Area splitting is the default ! +} + +//============================================================================== + +StatusCode SpdMonitorFuture::initialize() { + StatusCode sc = Consumer::initialize(); + if (sc.isFailure()) return sc; + // Loads the detectors + m_detSpd = getDet<DeCalorimeter>( DeCalorimeterLocation::Spd ); + // Histograms + bookCaloFuture2D( "1", "Spd occupancy", "Spd" ); + bookCaloFuture2D( "2", "Spd neighbor occupancy", "Spd" ); + + // Initialize neighbor matrix + for(unsigned int cellIt = 0; cellIt != m_detSpd->numberOfCells(); cellIt++){ + const auto& cell = m_detSpd->cellIdByIndex(cellIt); + const auto& neigh = m_detSpd->zsupNeighborCells(cell); + m_neighN.addEntry(neigh.size(), cell); + } + return StatusCode::SUCCESS; +} + +//============================================================================== + +StatusCode SpdMonitorFuture::finalize() { + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "==> Finalize" << endmsg; + info() << "Number of Events Analyzed : " << m_nEvents << endmsg; + return Consumer::finalize() ; +} + +//============================================================================== + +void SpdMonitorFuture::operator()(const Input& digitsSpd) const { + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "==> Execute " << endmsg; + + // Fill histos + for(const auto& digit: digitsSpd){ + if (digit==nullptr) continue; + const auto cell = digit->cellID(); + // histo1 + if(doHisto("1")) fillCaloFuture2D( "1", cell, 1.0 ); + // histo2 + if( doHisto("2") ){ + const auto neighs = m_detSpd->zsupNeighborCells(cell); + for(const auto neighCell: neighs){ + const auto value = (float) 1./float(m_neighN[cell]); + fillCaloFuture2D( "2", neighCell , value ); + } + } + } + m_nEvents++; + return; +} diff --git a/CaloFuture/CaloFuturePIDs/CMakeLists.txt b/CaloFuture/CaloFuturePIDs/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..d54a71d36a284aef23ba0130b1f5fdbdfcfbe943 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/CMakeLists.txt @@ -0,0 +1,29 @@ +################################################################################ +# Package: CaloFuturePIDs +################################################################################ +gaudi_subdir(CaloFuturePIDs v5r22) + +gaudi_depends_on_subdirs(CaloFuture/CaloFutureInterfaces + CaloFuture/CaloFutureUtils + GaudiAlg + Kernel/LHCbKernel + Kernel/LHCbMath + Kernel/Relations + Tr/TrackInterfaces) + +find_package(AIDA) +find_package(Boost) + +find_package(Boost) +find_package(ROOT) +include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS}) + +gaudi_add_module(CaloFuturePIDs + src/*.cpp + INCLUDE_DIRS AIDA Tr/TrackInterfaces + LINK_LIBRARIES CaloFutureUtils GaudiAlgLib LHCbKernel LHCbMathLib RelationsLib) + +gaudi_install_python_modules() + +gaudi_env(SET CALOFUTUREPIDSOPTS \${CALOFUTUREPIDSROOT}/options) + diff --git a/CaloFuture/CaloFuturePIDs/doc/release.notes b/CaloFuture/CaloFuturePIDs/doc/release.notes new file mode 100755 index 0000000000000000000000000000000000000000..aadb9f7bedda1ce329627c9cbe89bc38fb25bab3 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/doc/release.notes @@ -0,0 +1,532 @@ +!------------------------------------------------------------------------------ +! Package : CaloFuture/CaloFuturePIDs +! Responsible : Olivier Deschamps odescham@in2p3.fr +! Purpose : CaloFuturerimeter PIDs +!------------------------------------------------------------------------------ + +! 2016-08-16 - Olivier Deschamps + - implement counter() switch based on FutureCounterLevel tool + +!========================= CaloFuturePIDs v5r22 2016-03-17 ========================= +! 2016-03-05 - Olivier Deschamps + - CaloFuturePIDs configurable : add slots to configure the Accepted Track::Types + - src : add counter per track type in match algs + +! 2016-02-24 - Olivier Deschamps + - fix clang warning in friend declarations of ToolFactory (class->struct) + +!========================= CaloFuturePIDs v5r21 2016-01-28 ========================= +! 2016-25-01 - Olivier Deschamps + - CaloFuturePhotonMatch,CaloFutureElectronMatch, CaloFutureBremMatch tools : + - move m_position and m_plane data members to the base tool (CaloFutureTrackMatch) and invoke a BeginEvent reset + - this fixes the (rare) initialization issues producing difference in the offline versus online reconstruction + +!========================= CaloFuturePIDs v5r20p1 2015-10-13 ========================= +! 2015-08-12 - Gerhard Raven + - remove #include of obsolete Gaudi headers + +!========================= CaloFuturePIDs v5r20 2014-11-05 ========================= +! 2014-11-04 - Dima Golubkov + - CaloFutureElectronMatch : change back to extrapolation to the ZShowerMax plane + +!========================= CaloFuturePIDs v5r19 2014-09-08 ========================= +! 2014-07-25 - Dima Golubkov + - CaloFutureElectronMatch, CaloFutureBremMatch.cpp, CaloFuturePhotonMatch.cpp : decrease verbosity of tolerable errors to WARNING + +! 2014-07-23 - Olivier Deschamps for Dima + - CaloFutureElectronMatch : extrapolate the track to the CaloFutureHypo Z position instead of ZShowerMax plane + +!========================= CaloFuturePIDs v5r18p1 2014-07-14 ======================== +! 2014-06-27 - Olivier Deschamps + - Fix minor typo in a printout + +!========================= CaloFuturePIDs v5r18 2014-06-10 ========================= +! 2014-05-28 - Dmitry Golubkov + - CaloFutureTrackMatch.h : remove unused i_updateField() declaration + +! 2014-05-28 - Marco Cattaneo + - Fix some unprotected StatusCodes in CaloFutureTrackMatch.h + +!========================= CaloFuturePIDs v5r17 2014-05-13 ========================= +! 2014-05-06 - Marco Cattaneo + - Remove debug() from CaloFutureTrackAlg::_setProperty and CaloFutureTrackTool::_setProperty + This function is called in the constructor, when the OutputLevel is not initialised + +! 2014-04-15 - Oleg Stenyakin + - CaloFutureTrackMatch : fix warnings + +! 2014-04-14 - Oleg Stenyakin + - CaloFutureTrackMatch.{h,cpp} : the X-correction for the e+, e- track-cluster matching + for each zone of the ECAL is added. Parameters of the correction are loaded + from the CondDB by default, added protection if the Conditions are missing. + +!========================= CaloFuturePIDs v5r16 2014-03-18 ========================= +! 2014-03-06 - Olivier Deschamps + - python/Configuration.py : propagate OutputLevel value to calo sequences only when the property is explicity set + +!========================= CaloFuturePIDs v5r15 2013-10-24 ========================= +! 2013-10-09 - Olivier Deschamps + - python/CaloFuturePIDs/*.py : + - possibility to set-up a configuration without active Spd/Prs (NoSpdPrs = <False> flag) + - see CaloFutureReco releases.notes for detail + +!========================= CaloFuturePIDs v5r14 2013-06-03 ========================= +! 2013-05-13 - Marco Cattaneo + - Fix include paths following previous change + - Remove 'do nothing' finalize methods + +! 2013-05-10 - Olivier Deschamps + - move CaloFutureTrackAlg/Match/Tool.{cpp,h} from CaloFutureUtils + +!========================= CaloFuturePIDs v5r13 2012-11-28 ========================= +! 2012-11-22 - Marco Clemencic + - Added CMake configuration file. + +! 2012-10-17 - Marco Cattaneo + - In CaloFutureTrack2IDAlg, return Error from initialize if undefined Input, removes + need for Assert in execute + - Fix trivial icc remarks + +! 2012-10-08 - Marco Cattaneo + - In Configuration.py, remove setting of MeasureTime=true in sequencers, + should not be the default, and should in any case use TimingAuditor. + +!========================= CaloFuturePIDs v5r12 2012-03-27 ========================= +! 2012-03-15 - Marco Cattaneo + - Fix unprotected debug() MsgStreams + - Fix trivial icc remarks + - Fix UNINIT_CTOR defects + +!========================= CaloFuturePIDs v5r11 2011-12-15 ========================= +! 2011-12-09 - Olivier Deschamps + - CaloFuturePIDs/PIDs.py : fix external cluster setup + +!========================= CaloFuturePIDs v5r10 2011-11-08 ========================= +! 2011-09-30 - Olivier Deschamps for Victor Coco + - CaloFuturePhotonMatch : fix Hcal matching setup + +!========================= CaloFuturePIDs v5r9 2011-04-27 ========================= +! 2011-04-24 - Olivier Deschamps + - update CaloFutureProcessor configurable with 'ExternalClusters' slot + +!========================== CaloFuturePIDs v5r8 2010-09-24 ======================== +! 2010-09-20 - Olivier Deschamps + - CaloFuturePhotonIdALg : fix unchecked StatusCode + +! 2010-09-01 - Olivier Deschamps + - fix compilation warning on windows + +! 2010-08-27 - Olivier Deschamps + - python/PID.py : new class referencePDF() to feed HistogramDataSvc with default THS PDFs + - CaloFuturePhotonIDAlg : simplify using the new CaloFutureHypoEstimator tool + +!========================== CaloFuturePIDs v5r7 2010-08-25 ======================== +! 2010-08-17 - Olivier Deschamps + - new version of CaloFuturePhotonIDAlg (get data from condDB or THS) from F. Machefert + - python/PIDs.py : remove default hardcoded neutralID PDF + - python/Configuration.py : add PIDList to select the PID component(s) to be added to the caloPIDs sequence + + +!========================== CaloFuturePIDs v5r6p1 2010-06-21 ======================== +! 2010-06-04 - Rob Lambert + - Fixes for some windows warnings savannah 15808 + +!========================== CaloFuturePIDs v5r6 2010-05-21 ========================= +! 2010-05-20 - Olivier Deschamps + - python/Configuration.py : reduce verbosity + + +! 2010-05-19 - Gerhard Raven + - only summarize 'match' errors, do not print (see https://savannah.cern.ch/bugs/?67077) + +!========================== CaloFuturePIDs v5r5 2010-03-19 ========================= +! 2010-03-12 - Dmitry Golubkov + - CaloFutureID2DLL - enable CondDB by default, add protection if the Condition is missing + - BremPIDeAlg, FutureEcalPIDeAlg, FutureEcalPIDmuAlg, FutureHcalPIDeAlg, FutureHcalPIDmuAlg, FuturePrsPIDeAlg - set default Condition and histogram names + + +! 2010-03-08 - Olivier Deschamps + - Configurables : + - adapt to changes in CaloKernel/ConfUtils + - make all component context-dependent + - add few slots (SkipNeutral, SkipCharged ) + - add new components for neutral PIDs + + + - options : + - clean options (remove obsolete) -> options directory is now empty + + - src : + - new algorithm CaloFuturePhotonIdALg : produce <Hypo,Likelihood> relation table -> NeutralProtoPALg + -> remove obsolete CaloFuturePhotonEstimatorTool and CaloFutureSingleGammaTool + - use TrackRungeKuttaExtrapolator by default everywhere + - add counters to monitor algorithms I/O + + - TODO : + - CaloFuturePIDsConf : split the sequence by CaloFuturePIDs technique and add PIDsList configuration (to be synchronized with CaloFutureReclo/Processor) + + +! 2010-02-28 - Olivier Deschamps + - PhotonMatchAlg : remove forgotten lines overwritting the context dependent TES I/O + +!========================== CaloFuturePIDs v5r4 2010-02-15 ========================= +! 2009-11-17 - Olivier Deschamps + - PIDs.py : use RungeKutta extrapolator instead of HeraB for HLT processing + +! 2010-02-08 - Dmitry Golubkov + - CaloFutureID2DLL - optionally read the DLLs from CondDB + - cmt/requirements - version incremented to v5r4 + +!========================== CaloFuturePIDs v5r3 2010-01-21 ========================= +! 2010-01-13 - Marco Cattaneo + - Follow Gaudi fix #61116: GaudiCommon::Exception now returns void + +!========================== CaloFuturePIDs v5r2 2009-11-13 ========================= +! 2009-11-13 - Rob Lambert + - Tagged the package + +! 2009-10-30 - Olivier Deschamps + + - fix unchecked StatusCode + + +! 2009-10-30 - Vanya Belyaev + + - suppress few warnigs + +! 2009-10-25 - Vanya Belyaev + + - add ICaloFutureDigit4Track interface for all <CALOFUTURE>EnergyForTrack tools + + - CaloFutureEnergyForTrack.cpp + + fix the typo in property name + + - cmt/requirements + + version increment to v5r2 + +!========================== CaloFuturePIDs v5r1p1 2009-09-30 ========================= +! 2009-09-30 - Olivier Deschamps + - reduce CaloFutureTrackMatchAlg verbosity + +! 2009-09-03 - Olivier Deschamps + - reduce InCaloFutureAcceptance/CaloFutureTrackMatchAlg verbosity when no good tracks found (warning->debug) + - add protection against missing inputs + +!========================== CaloFuturePIDs v5r1 2009-09-03 ========================= +! 2009-09-03 - Marco Cattaneo + - Remove obsolete file src/CaloFuturePIDs_dll.cpp + +! 2009-09-01 - Vanya BELYAEV + - suppress warnings for consigurables + - cmt/requirements + version increment to v5r1 + +!========================== CaloFuturePIDs v5r0 2009-08-31 ========================= +! 2009-08-21 - Olivier Deschamps + - implement generic context-dependent TES I/O + +! 2009-08-10 - Vanya BELYAEV + + - polish the configurables + +! 2009-08-05 - Vanya BELYAEV + + - add the configurables + - version increment to v5r0 + +!========================== CaloFuturePIDs v4r17 2009-05-25 ========================= +! 2009-05-15 - Marco Cattaneo + - Fix untested StatusCode on Warning() and Error() calls + - Replace endreq with endmsg + +!========================== CaloFuturePIDs v4r16 2009-05-08 ========================= +! 2009-04-16 - Olivier Deschamps + - fix unchecked StatusCode + +!========================== CaloFuturePIDs v4r15 2009-03-11 ========================= +! 2009-03-11 - Victor Egorychev + - AddNeigbours in FutureEcalEnergyForTrack and HcalEnrgyForTrack changed to FALSE + +!========================== CaloFuturePIDs v4r14p1 2008-01-12 ======================= +! 2008-12-10 - Marco Cattaneo + - Fix gcc 4.3 compilation warnings + +!========================== CaloFuturePIDs v4r14 2008-11-21 ========================= +! 2008-10-10 - Olivier Deschamps + - fix unitialized variable in CaloFutureID2DLL.cpp + +!========================== CaloFuturePIDs v4r13 2008-07-18 ========================= +! 2008-07-17 - Olivier Deschamps + - duplicate PhotonPDF.opts for Hlt usage (HltPhotonPDF.opts) + +!========================== CaloFuturePIDs v4r12 2008-07-02 ========================= +! 2008-06-27 - Olivier Deschamps + - CaloFutureTrackMatchAlg and inCaloFutureAcceptanceAlg : protect against empty track container + - use default HLT locations for the HLT context in all algorithm/tool + + +! 2008-06-26 - Juan PALACIOS + - cmt/requirements + . Increase version to v4r12 + - src/CaloFuturePhotonEstimatorTool.cpp + - src/CaloFutureSingleGammaTool.cpp + - src/Linear.h + . Change all Gaudi::XYZLine and Gaudi::Line for Gaudi::Math::XYZLine and + Gaudi::Math::XYZLine respectively (adapting to Kernel/LHCbMath v3) + +!========================== CaloFuturePIDs v4r11 2008-06-04 ========================= +! 2008-06-04 - Marco Cattaneo + - Fix doxygen warning + +! 2008-06-03 Olivier Deschamps + - change incident type EndEvent to BeginEvent in CaloFutureEnergyForTrack.cpp + +!========================== CaloFuturePIDs v4r10 2008-05-13 ========================= +! 2008-05-13 Olivier Deschamps +- restore void _setProperty(..) instead of StatusCode setProperty(...) + +!========================== CaloFuturePIDs v4r9 2008-01-24 =================== +! 2008-01-24 - Victor Egorychev +- _setProperty was changed to setProperty +- fixed mistypo with AddNeigbours instead AddNeibours +- version was incremented to v4r9 + +!========================== CaloFuturePIDs v4r8 2007-09-20 =================== +! 2007-08-24 - Olivier Deschamps + - Fix most of the unchecked StatusCodes + +!========================== CaloFuturePIDs v4r7 2007-05-31 =================== +! 2007-05-31 - Marco Cattaneo + - Fix doxygen warnings + +! 2007-05-26 - Victor Egorychev +- DLL hist (DC06) for different BremPID added, needs ParamFiles v6r1 +- src/BremPIDeAlg.cpp + - new PIDs from DC06 added + - cmt/requirements + version increment to v4r7 + +!========================== CaloFuturePIDs v4r6 2007-03-02 ========================== +! 2007-03-02 - Marco Cattaneo + - Remove LHCbDefinitions includes + - Remove obsolete CaloFuturePIDs_load.cpp file + - Fix doxygen warnings and other minor cleanups + +!========================== CaloFuturePIDs v4r5p1 2006-11-27 =================== +! 2006-11-27 - Victor Egorychev + - src/CaloFutureID2DLL.cpp Warning " ... very priliminary version ... " was + removed + +!========================== CaloFuturePIDs v4r5 2006-11-07 =================== +! 2006-11-07 - Marco Cattaneo + - Change CALOFUTUREPIDOPTS variable to CALOFUTUREPIDSOPTS, to be standard.... + +! 2006-11-06 - Victor Egorychev +- DLL hist (DC06) for different types tracks for PIDe/mu added + (Ecal, Hcal, Prs). For BremPID - still old hist +- src/FutureEcalPIDeAlg.cpp + - new PIDs from DC06 added for Long, Downstream, TTrack tracks +- src/FutureHcalPIDeAlg.cpp + - new PIDs from DC06 added for Long, Downstream, TTrack tracks +- src/FuturePrsPIDeAlg.cpp + - new PIDs from DC06 added for Long, Downstream, TTrack tracks +- src/FutureEcalPIDmuAlg.cpp + - new PIDs from DC06 added for Long, Downstream, TTrack tracks +- src/FutureHcalPIDmuAlg.cpp + - new PIDs from DC06 added for Long, Downstream, TTrack tracks +- src/BremPIDeAlg.cpp + - old PIDs added for Long, Velo, Upstream tracks +- src/CaloFutureID2DLL.cpp + - hist for different track types added +- src/CaloFutureID2DLL.h + - hist for different track types added + - cmt/requirements + version increment to v4r5 + +! ========================= CaloFuturePIDs v4r4 2006-09-28 =================== +! 2006-09-28 - Victor Egorychev + - src/Linear.h + bug fix for invalid linear state extrapolation + - cmt/requirements + version increment to v4r4 + +! ========================= CaloFuturePIDs v4r3 2006-08-03 =================== +! 2006-08-03 - Chris Jones + - Add missing data initialisations in CaloFutureElectronMatch and CaloFuturePhotonMatch + +!========================== CaloFuturePIDs v4r2 2006-07-19 =================== +! 2006-07-19 - Marco Cattaneo + - ToString.h : remove all templates now in GaudiKernel/ToStream.h + +!========================== CaloFuturePIDs v4r1 2006-06-27 =================== +! 2006-06-27 - Olivier Deschamps + - CaloFutureReco/CaloFuturePIDs repackaging : + - add CaloFutureSingleGammaTool/CaloFuturePhotonEstimatorTool from CaloFutureReco/ + - increment the release number in cmt/requirements + +!========================== CaloFuturePIDs v4r0 2006-06-22 =================== +! 2006-06-22 - Vanya BELYAEV + - fix the inconsistencies in the configuration of + accepted types for "Brem"-related algorithms + +! 2006-06-21 - Vanya BELYAEV + - fix the problem for "Brem"-tools. + now it tries to get the fixed states: + AtTT, EndRich1, BegRich1, EndVelo, + othwrwise it used the state nearest to 2*meter (and x<4*meter). + Also use the explicite extrapolation + - Linear.h - explicite linear extrapolator. + The speed-up of BremMatch algorthm is approximately 2 times "9"->"4" + +! 2006-06-20 - Olivier Deschamps + - minor update (RelationWeighted1D -> 2D to please ChargedProtoPAlg) + +! 2006-06-19 - Vanya Belyaev + - First version for DC06 + +!========================== CaloFuturePIDs v3r0 2005-11-04 =================== +! 2005-11-04 - Olivier Deschamps + - Adapt to new Track Event Model (TrackEvent v1r4) + + modified file : + src/CaloFutureTrackPrsEval.h/cpp + src/CaloFutureTrackHcalEval.h/cpp + src/CaloFutureTrackEval.h/cpp + src/CaloFutureTrackEcalEval.h/cpp + src/CaloFutureTrack2IdAlg.cpp + src/CaloFutureTrack2EstimatorAlg.cpp + src/CaloFuturePIDsData.cpp + src/CaloFuturePhotonEstimatorTool.h/cpp + + - cmt/requirements + version increment to v3r0 + +!========================= CaloFuturePIDs v2r6 2005-06-02 =========================== +! 2005-06-02 - Marco Cattaneo + - Adapt Brunel.opts to new phase name Reco instead of BrunelReco + +!========================= CaloFuturePIDs v2r5p1 2005-05-23 ========================= +! 2005-05-10 - Vanya BELYAEV + + - src/CaloFuturePIDsData.cpp + 1) rename "match" -> "mat" as N-Tuple item name to please PAW + (thanks to Kirill VORONCHEV) + 2) add photon match estimator + 3) cosmetic modifications + + - src/CaloFuturePIDsData.h + remove the file + +!========================= CaloFuturePIDs v2r5 2005-05-09 =========================== +! 2005-05-08 - Vanya BELYAEV + Eliminate all *associators* + Now everything works directly with relation tables + (Assuming the proper instrumentation of "Data-On-Demand" service) + + - options/CaloFuturePIDsOnDemand.opt + new configuration file (TEST-PHASE) for "CaloFuturePIDs-On-Demand" + approach + - cmt/requirements + version increment to v2r5 + +!======================= CaloFuturePIDs v2r4p1 2005-03-08 ===================== +! 2005-03-08 - Marco Cattaneo + - Fix some doxygen warnings + - Remove unmatched "#pragma print on" in options to avoid resetting print + level in higher level options files + +!======================== CaloFuturePIDs v2r4 2004-09-08 ====================== +! 2004-09-02 - Vanya BELYAEV + make the preparation for HLT/Trigger development + - update for modifier CaloFutureInterfaces + - cmt/requirements + version increment to v2r4 + +!======================== CaloFuturePIDs v2r3 2004-04-27 ====================== +! 2004-04-27 - Vanya Belyaev + - src/CaloFuturePIDsData.cpp + fix stupid misprint in type name for associator + - cmt/requirements + increment the version to v2r3 + +!======================== CaloFuturePIDs v2r2 2004-04-19 ====================== +! 2004-04-19 - Marco Cattaneo + - Fix doxygen warnings + +! 2004-04-18 - Vanya Belyaev + - src/CaloFuturePhotonEstimatorTool.h,.cpp + the updated version of PhotonID tool from Frederic Machefert + - options/PhotonPDF.opts + the updated file with parameters + - cmt/requirements + increment the version to v2r2 + +!======================== CaloFuturePIDs v2r1 2004-03-18 ====================== +! 2004-03-17 - Vanya BELYAEV + - src/CaloFuturePhotonEstimatorTool.h,cpp + new tool for photon ID estimate from Frederic Machefert + The origina version from Frederic is udapted a bit to + new GaudiTool/CaloFutureTool methods and to + "typo"-fix ICaloFutureLikelyhood -> ICaloFutureLikelihood + - src/CaloFuturePIDsData.h/.cpp + new algorithm to fill NTuple needed to populate + the reference histograms for charged particle ID + + - src/CaloFuturePIDs_load.cpp - add new tool and new + algorithm to the list of + known components + + - cmt/requirements increment the version to v2r1 + + - options/PhotonPDF.opts + configuration of CaloFuturePhotonEstimatorTool/PhotonPID + ********** ATTENTION: tool name is choosen to be 'PhotonPID' ********* + +!======================== CaloFuturePIDs v2r0 2004-03-08 ====================== +! 2004-03-08 - Marco Cattaneo + - In CaloFutureTrack2Estimator.h/.cpp, CaloFutureTrack2Idalg.h/.cpp + . rename m_upstream to m_downstream + . rename UseUpstream property to UseDownstream + . use new isDownstream() method of TrStoredTrack instead of upstream() + + - In *.opts + . rename UseUpstream property to UseDownstream + +! 2004-02-17 - Vanya BELYAEV + + - update for reading the input histograms from + + $PARAMFILEROOT/data/CaloFuturePIDs.root + or + $PARAMFILEROOT/data/CaloFuturePIDs.root + + - remove 'text' histograms from options directory + + - cmt/requirements increment teh MAJOR version + +!======================== CaloFuturePIDs v1r2 2003-12-11 ====================== +! 2003-12-11 - Marco Cattaneo + - Move to Gaudi v13: + . requirements: use CaloFutureInterfaces v3r* + . CaloFutureTrack2IdAlg.cpp: adapt to AIDA 3.0 + +!======================== CaloFuturePIDs v1r1 2003-07-17 ====================== +! 2003-07-17 - Ivan BELYAEV + - src/CaloFutureTrackEval.cpp + fix an error (return m_bad valeu for zero energy deposition) + - cmt/requirements increase the version + +! 2003-07-17 - Ivan BELYAEV + - minor change if algorithms to speed-up a code a little bit + - options introduce a low/high limits for estimators to skip + 'bad' records + +!======================== CaloFuturePIDs v1r0 2003-04-17 ====================== +! 2003-04-17 - Marco Cattaneo + - Remove "#" from "#include" when it appears in doxygen comment lines of job + options, as this breaks the production tools + +! 2003-03-13 - Vanya BELYAEV + - new package diff --git a/CaloFuture/CaloFuturePIDs/python/CaloFuturePIDs/Configuration.py b/CaloFuture/CaloFuturePIDs/python/CaloFuturePIDs/Configuration.py new file mode 100644 index 0000000000000000000000000000000000000000..e29e2e0e5830225b6775c6bff5bea540e32a779d --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/python/CaloFuturePIDs/Configuration.py @@ -0,0 +1,191 @@ +#!/usr/bin/env gaudirun.py +# ============================================================================= +## Configurable for CaloFuturerimeter PID +# @author Vanya BELYAEV Ivan.Belyaev@nikhe.nl +# @date 2008-07-17 +# ============================================================================= +""" +Configurable for CaloFuturerimeter PID +""" +# ============================================================================= +__author__ = "Vanya BELYAEV Ivan.Belyaev@nikhef.nl" +__version__ = "CVS tag $Name: not supported by cvs2svn $, version $Revision: 1.4 $" +# ============================================================================= +__all__ = ( + 'HltCaloFuturePIDsConf' , + 'OffLineCaloFuturePIDsConf' , + 'CaloFuturePIDsConf' + ) +# ============================================================================= + +from LHCbKernel.Configuration import * +from Configurables import HistogramSvc + +from CaloKernel.ConfUtils import ( addAlgs , + printOnDemand , + prntCmp , + hltContext , + setTheProperty ) +from CaloFuturePIDs.PIDs import caloPIDs +from CaloFuturePIDs.PIDs import referencePIDs +import logging +_log = logging.getLogger ('CaloFuturePIDs') + +# ============================================================================= +## @class CaloFuturePIDsConf +# Configurable for CaloFuturerimeter PID +# @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl +# @date 2008-07-17 +class CaloFuturePIDsConf(LHCbConfigurableUser): + """ + Class/Configurable to define the calorimeter PID + """ + ## define the slots + __slots__ = { + ## + "Context" : '' # The context within which to run + , "MeasureTime" : False # Measure the time for sequencers + , "OutputLevel" : INFO # The global output level + ## + , 'Sequence' : '' # The sequencer to add the CALOFUTURE reconstruction algorithms to + , 'PIDList' : ['InAcceptance', + 'Match', + 'Energy', + 'Chi2', + 'DLL', + 'NeutralPID' + ] # List of PID fragments to be included (alternative full sequence per technique : [ 'EcalPID', 'BremPID', 'HcalPID', 'PrsPID', 'SpdPID', 'NeutralPID' ] ) + + , 'EnablePIDsOnDemand' : False # enable Reco-On-Demand + ## + , 'DataType' : 'MC09' # Data type + , 'TrackLocation' : '' # track location to be used (default use CaloFutureAlgUtils default) + , 'ClMatchTrTypes' : [] # Track types for Cluster matching (if not set the alg. default is used i.e. Long + Downstream + TTracks) + , 'CaloFuturePIDTrTypes' : [] # Track types for CaloFuturePID (if not set the alg. default is used i.e. Long + Downstream + TTracks) + , 'BremPIDTrTypes' : [] # Track types for BremPID (if not set the alg. default is used i.e. Long + Upstream + Velo) + , 'SkipNeutrals' : False # skip neutralID (already run in CaloFutureRecoConf by default) + , 'SkipCharged' : False # skip chargedID + , 'FastPID' : False # speed-up PID (lighter sequence) + , 'ExternalClusters' : '' # use non-default cluster container + , 'NoSpdPrs' : False # Upgrade configuration without Spd/Prs + , 'Verbose' : False + } + + ## Configure recontruction of CaloFuture Charged PIDs + def caloPIDs ( self ) : + """ + Configure recontruction of CaloFuture Charged PIDs + """ + cmp = caloPIDs ( self.getProp( 'Context' ) , + self.getProp( 'EnablePIDsOnDemand' ) , + self.getProp('PIDList'), + self.getProp('TrackLocation'), + self.getProp('ClMatchTrTypes'), + self.getProp('CaloFuturePIDTrTypes'), + self.getProp('BremPIDTrTypes'), + self.getProp('SkipNeutrals'), + self.getProp('SkipCharged'), + self.getProp('FastPID'), + self.getProp('ExternalClusters'), + self.getName(), + self.getProp('NoSpdPrs') + ) + + referencePIDs( self.getProp("DataType" ) ) + + _log.info ('Configured CaloFuture PIDs : %s ' % cmp.name() ) + ## + return cmp + + ## Check the configuration + def checkConfiguration ( self ) : + """ + Check the configuration + """ + _log.debug('CaloFuturePIDsConf: Configuration is not checked!') + + + + def printConf(self,verbose=False) : + if self.getProp('NoSpdPrs') : + _log.info("CaloFuturePIDsConf : upgrade configuration without Spd/Prs") + if self.getProp('Verbose') or verbose: + _log.info ( self ) + + + ## CaloFuturerimeter PID Configuration + def applyConf ( self ) : + """ + CaloFuturerimeter PID Configuration + """ + + self.printConf() + + pids = self.caloPIDs() + + setTheProperty ( pids , 'Context' , self.getProp('Context' ) ) + setTheProperty ( pids , 'MeasureTime' , self.getProp('MeasureTime') ) + if self.isPropertySet("OutputLevel") : + setTheProperty ( pids , 'OutputLevel' , self.getProp('OutputLevel') ) + + if self.getProp ( 'Sequence' ) : + addAlgs ( self.Sequence , pids ) + _log.info ('Configure main CaloFuture PIDs Sequence : %s '% self.Sequence.name() ) + if self.getProp('Verbose') : + _log.info ( prntCmp ( self.Sequence ) ) + else : + _log.info ('Configure CaloFuturerimeter PIDs blocks ' ) + if self.getProp('Verbose') : + _log.info ( prntCmp ( pids ) ) + + + if self.getProp( 'EnablePIDsOnDemand') : + _log.info ( printOnDemand () ) + + + + +# ============================================================================= +## @class HltCaloFuturePIDsConf +# Configurable for CaloFuturerimeter PID +# @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl +# @date 2008-07-17 +class HltCaloFuturePIDsConf(CaloFuturePIDsConf): + """ + Class/Configurable to define the calorimeter PID for Hlt + """ + __slots__ = {} + + ## Check the configuration + def checkConfiguration ( self ) : + """ + Check the configuration + """ + if not hltContext ( self.getProp('Context') ) : + raise AttributeError, 'Invalid context for HltCaloFuturePIDsConf' + +# ============================================================================= +## @class OffLineCaloFuturePIDsConf +# Configurable for CaloFuturerimeter PID +# @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl +# @date 2008-07-17 +class OffLineCaloFuturePIDsConf(CaloFuturePIDsConf): + """ + Class/Configurable to define the calorimeter PID for Off-Line + """ + __slots__ = {} + + ## Check the configuration + def checkConfiguration ( self ) : + """ + Check the configuration + """ + if hltContext ( self.getProp('Context') ) : + raise AttributeError, 'Invalid context for OffLineCaloFuturePIDsConf' + + + + +# ============================================================================= +# The END +# ============================================================================= diff --git a/CaloFuture/CaloFuturePIDs/python/CaloFuturePIDs/PIDs.py b/CaloFuture/CaloFuturePIDs/python/CaloFuturePIDs/PIDs.py new file mode 100644 index 0000000000000000000000000000000000000000..a1a6f303bcdb5b33f30a6d0a7e138f4b1228d9f7 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/python/CaloFuturePIDs/PIDs.py @@ -0,0 +1,522 @@ +#!/usr/bin/env python +# ============================================================================= +# $Id: PIDs.py,v 1.4 2010/03/08 01:31:33 odescham Exp $ +# ============================================================================= +## The major building blocks of CaloFuturerimeter PID +# @author Vanya BELYAEV Ivan.Belyaev@nikhe.nl +# @date 2008-07-17 +# ============================================================================= +""" +The major building blocks of CaloFuturerimeter PID +""" +# ============================================================================= +__author__ = "Vanya BELYAEV Ivan.Belyaev@nikhef.nl" +__version__ = "CVS tag $Name: v5r6 $, version $Revision: 1.4 $" +# ============================================================================= +from Gaudi.Configuration import * + +from Configurables import GaudiSequencer + +from CaloKernel.ConfUtils import ( hltContext , + getAlgo , + setTheProperty , + addAlgs + ) + + + +# ============================================================================= +## define "PhotonID" algorithm +def PhotonID ( context , enableRecoOnDemand, useTracks = True ) : + """ + define 'PhotonID' algorithm + """ + + + from Configurables import CaloFuturePhotonIdAlg + + ## photonID + pid = getAlgo ( CaloFuturePhotonIdAlg, + "PhotonID", + context, + "Rec/Calo/PhotonID", + enableRecoOnDemand + ) + + pid.Type = 'PhotonID' + pid.Tracking = useTracks + return pid + +# ============================================================================= +## define "MergedID" algorithm +def MergedID ( context , enableRecoOnDemand, useTracks = True ) : + """ + define 'MergedID' algorithm + """ + + from Configurables import CaloFuturePhotonIdAlg + + ## photonID + mid = getAlgo ( CaloFuturePhotonIdAlg, + "MergedID", + context, + "Rec/Calo/MergedID", + enableRecoOnDemand + ) + + mid.Type = 'MergedID' + mid.Tracking = useTracks + return mid + +# ============================================================================= +## define "MergedID" algorithm +def PhotonFromMergedID ( context , enableRecoOnDemand, useTracks = True ) : + """ + define 'PhotonFromMergedID' algorithm + """ + + from Configurables import CaloFuturePhotonIdAlg + + ## photonID + pmid = getAlgo ( CaloFuturePhotonIdAlg , + "PhotonFromMergedID", + context, + "Rec/Calo/PhotonFromMergedID", + enableRecoOnDemand + ) + + pmid.Type = 'PhotonFromMergedID' + pmid.Tracking = useTracks + return pmid + +# ============================================================================= +## define "inEcalAcceptance" algorithm +def inEcalAcc ( context , enableRecoOnDemand, trackLocation = "", matchTrTypes=[]) : + """ + + define 'inEcalFutureAcceptance' algorithm + + """ + + from Configurables import ( InEcalFutureAcceptance , + InEcalFutureAcceptanceAlg ) + + ## check if the track is in Ecal acceptance + inEcal = getAlgo ( InEcalFutureAcceptanceAlg , + 'InECALFuture' , + context , + "Rec/Calo/InAccEcal" , + enableRecoOnDemand ) + + if trackLocation : + inEcal.Inputs = trackLocation + + if matchTrTypes != [] : + inEcal.AcceptedType=matchTrTypes + + return inEcal + +## ============================================================================ +## define the minimal track match sequnce for photon recontruction +def trackMatch ( context , enableRecoOnDemand, trackLocation = "" , matchTrTypes=[], fastReco = False , clusterLocation = "" ) : + """ + + Define the minimal track match sequnce for photon reconstruction + + """ + + from Configurables import FuturePhotonMatchAlg + + seq = getAlgo ( GaudiSequencer , 'CaloFutureTrackMatch' , context ) + + + ## perform the actual track <-> cluster match + clmatch = getAlgo ( FuturePhotonMatchAlg , + 'FutureClusterMatch' , + context , + 'Rec/Calo/ClusterMatch' , + enableRecoOnDemand ) + + if clusterLocation != '' : + clmatch.Calos = clusterLocation + + +# log.info(" ========= trackLocation = " + trackLocation ) + + ## check if the track is in Ecal acceptance + inEcal = inEcalAcc ( context , enableRecoOnDemand , trackLocation,matchTrTypes) + + seq.Members = [ inEcal , clmatch ] + + setTheProperty ( seq , 'Context' , context ) + + if matchTrTypes != [] : + clmatch.AcceptedType=matchTrTypes + + + if trackLocation : + clmatch.Tracks = trackLocation + + log.debug ( "Configure Cluster Track Match : '%s' for '%s'" %(seq.name(), context) ) + + + return seq + + +# ================================================================================= +## define various CaloFuture PIDs evaluation +def caloPIDs ( context , enableRecoOnDemand , list , trackLocation = '' , matchTrTypes=[] , caloTrTypes=[] , bremTrTypes=[], + skipNeutrals = False , skipCharged = False , fastPID = False , clusterLocation = '', name = '', noSpdPrs=False) : + """ + Define various CaloFuture PIDs evaluation + """ + + + from Configurables import ( InSpdFutureAcceptance , + InSpdFutureAcceptanceAlg , + InPrsFutureAcceptance , + InPrsFutureAcceptanceAlg , + InEcalFutureAcceptance , + InEcalFutureAcceptanceAlg , + InBremFutureAcceptance , + FutureInBremFutureAcceptanceAlg , + InHcalFutureAcceptance , + InHcalFutureAcceptanceAlg ) + + from Configurables import ( FutureElectronMatchAlg , + BremMatchAlgFuture ) + + from Configurables import ( FutureTrack2SpdEAlg , + FutureTrack2PrsEAlg , + FutureTrack2EcalEAlg , + FutureTrack2HcalEAlg ) + + + from Configurables import ( FutureEcalChi22ID , + BremChi22IDFuture , + FutureClusChi22ID , + FuturePrsPIDeAlg , + FutureEcalPIDeAlg , + BremPIDeAlgFuture , + FutureHcalPIDeAlg , + FutureEcalPIDmuAlg , + FutureHcalPIDmuAlg , + CaloFuturePhotonIdAlg + ) + + ## SANITY CHECK FOR TRACK TYPES (caloTrTypes must be included in matchTrTypes) + defMatchTrTypes = [3,5,6] # Long / Downstream / TTracks + if matchTrTypes != [] : + defMatchTrTypes = matchTrTypes + for item in caloTrTypes : + if item not in defMatchTrTypes : + raise AttributeError, 'TrackTypes for ClusterMatching must include CaloFuturePID TrackTypes' + + if matchTrTypes != [] : + log.info(" ! Will use track types = % s for matching" % matchTrTypes) + if caloTrTypes != [] : + log.info(" ! Will use track types = % s for caloPID" % caloTrTypes) + if bremTrTypes != [] : + log.info(" ! Will use track types = % s for bremPID" % bremTrTypes) + + + + ## global PID sequence + _name = 'CaloFuturePIDs' + if name != context or context.upper() == 'OFFLINE': _name = _name+name + seq = getAlgo ( GaudiSequencer, _name, context ) + seq.Members = [] + + ## add Charged + if not skipCharged : + _name = 'ChargedPIDs' + if name != context or context.upper() == 'OFFLINE': _name = _name+name + + charged = getAlgo( GaudiSequencer , _name , context ) + + # inAcceptance + inAcc = getAlgo ( GaudiSequencer , 'InCaloFutureAcceptance' , context ) + + inECAL = inEcalAcc ( context , enableRecoOnDemand , trackLocation , matchTrTypes ) + inHCAL = getAlgo ( InHcalFutureAcceptanceAlg , + 'InHCALFuture' , + context , + "Rec/Calo/InAccHcal" , + enableRecoOnDemand ) + inBREM = getAlgo ( FutureInBremFutureAcceptanceAlg , + 'InBREMFuture' , + context , + "Rec/Calo/InAccBrem" , + enableRecoOnDemand ) + inAcc.Members = [ inECAL , inHCAL , inBREM ] + + if not noSpdPrs : + inSPD = getAlgo ( InSpdFutureAcceptanceAlg , + 'InSPD' , + context , + "Rec/Calo/InAccSpd" , + enableRecoOnDemand ) + inPRS = getAlgo ( InPrsFutureAcceptanceAlg , + 'InPRS' , + context , + "Rec/Calo/InAccPrs" , + enableRecoOnDemand ) + inAcc.Members += [ inSPD , inPRS ] + else : + log.info('remove Spd/Prs from acceptance') + + + + + # matching + match = getAlgo ( GaudiSequencer , + 'CaloFutureMatch' , + context ) + cluster = trackMatch ( context , enableRecoOnDemand , trackLocation, matchTrTypes, fastPID,clusterLocation) + + electron = getAlgo ( FutureElectronMatchAlg , + "ElectronMatchFuture" , + context , + 'Rec/Calo/ElectronMatch' , + enableRecoOnDemand ) + brem = getAlgo ( BremMatchAlgFuture , + "BremMatchFuture" , + context , + 'Rec/Calo/BremMatch' , + enableRecoOnDemand ) + + match.Members = [cluster , electron, brem ] + + # energy + energy = getAlgo ( GaudiSequencer , + 'CaloFutureEnergy' , + context ) + ecalE = getAlgo ( FutureTrack2EcalEAlg , + 'EcalEFuture' , + context , + 'Rec/Calo/EcalE' , + enableRecoOnDemand ) + hcalE = getAlgo ( FutureTrack2HcalEAlg , + 'HcalEFuture' , + context , + 'Rec/Calo/HcalE' , + enableRecoOnDemand ) + + + energy.Members = [ ecalE , hcalE ] + if not noSpdPrs : + spdE = getAlgo ( FutureTrack2SpdEAlg , + 'SpdEFuture' , + context , + 'Rec/Calo/SpdE' , + enableRecoOnDemand ) + prsE = getAlgo ( FutureTrack2PrsEAlg , + 'PrsEFuture' , + context , + 'Rec/Calo/PrsE' , + enableRecoOnDemand ) + + energy.Members += [ spdE , prsE ] + else : + log.info('remove Spd/Prs from energy estimators') + + + # Chi2's + chi2 = getAlgo ( GaudiSequencer , 'CaloFutureChi2', context ) + eChi2 = getAlgo ( FutureEcalChi22ID, 'FutureEcalChi22ID' , context, 'Rec/Calo/EcalChi2', enableRecoOnDemand ) + bChi2 = getAlgo ( BremChi22IDFuture, 'BremChi22IDFuture' , context, 'Rec/Calo/BremChi2', enableRecoOnDemand ) + cChi2 = getAlgo ( FutureClusChi22ID, 'FutureClusChi22ID' , context, 'Rec/Calo/ClusChi2', enableRecoOnDemand ) + chi2.Members = [ eChi2, bChi2 , cChi2 ] + + + # DLL + dlle = getAlgo ( GaudiSequencer , + 'CaloFutureDLLeFuture' , + context ) + dllmu = getAlgo ( GaudiSequencer , + 'CaloFutureDLLmuFuture' , + context ) + ecale=getAlgo ( FutureEcalPIDeAlg , + 'EcalPIDeFuture' , + context , + 'Rec/Calo/EcalPIDe' , + enableRecoOnDemand ) + breme=getAlgo ( BremPIDeAlgFuture , + 'BremPIDeFuture' , + context , + 'Rec/Calo/BremPIDe' , + enableRecoOnDemand ) + hcale=getAlgo ( FutureHcalPIDeAlg , + 'HcalPIDeFuture' , + context , + 'Rec/Calo/HcalPIDe' , + enableRecoOnDemand ) + ecalmu=getAlgo ( FutureEcalPIDmuAlg , + 'EcalPIDmuFuture' , + context , + 'Rec/Calo/EcalPIDmu' , + enableRecoOnDemand ) + hcalmu=getAlgo ( FutureHcalPIDmuAlg , + 'HcalPIDmuFuture' , + context , + 'Rec/Calo/HcalPIDmu' , + enableRecoOnDemand ) + + + dllmu.Members = [ ecalmu, hcalmu ] + dlle.Members = [ ecale , breme , hcale ] + if not noSpdPrs : + prse=getAlgo ( FuturePrsPIDeAlg , + 'PrsPIDe' , + context , + 'Rec/Calo/PrsPIDe' , + enableRecoOnDemand ) + + dlle.Members += [ prse ] + else : + log.info('remove Spd/Prs from dlle') + + + + # alternative sequence (per caloPID technique) + ecalT = getAlgo ( GaudiSequencer ,'EcalPIDFuture' , context ) + ecalT.Members = [ inECAL, cluster, electron, ecalE, eChi2, cChi2, ecale, ecalmu ] + + hcalT = getAlgo ( GaudiSequencer ,'HcalPIDFuture' , context ) + hcalT.Members = [ inHCAL, hcalE, hcale, hcalmu ] + + + if not noSpdPrs : + prsT = getAlgo ( GaudiSequencer ,'PrsPIDFuture' , context ) + prsT.Members = [ inPRS, prsE, prse ] + + spdT = getAlgo ( GaudiSequencer ,'SpdPIDFuture' , context ) + spdT.Members = [ inSPD, spdE ] + + bremT = getAlgo ( GaudiSequencer ,'BremPIDFuture' , context ) + bremT.Members = [ inBREM, brem, bChi2, breme ] + + + # === Redefine accepted track types === + # matchTrTypes propagated to the relevant modules (inEcalAcc & clusterMatch) + if caloTrTypes != [] : + electron.AcceptedType = caloTrTypes + cChi2.AcceptedType = caloTrTypes + eChi2.AcceptedType = caloTrTypes + ecalE.AcceptedType = caloTrTypes + ecale.AcceptedType = caloTrTypes + ecalmu.AcceptedType = caloTrTypes + inHCAL.AcceptedType = caloTrTypes + hcalE.AcceptedType = caloTrTypes + hcale.AcceptedType = caloTrTypes + hcalmu.AcceptedType = caloTrTypes + if not noSpdPrs : + inSPD.AcceptedType = caloTrTypes + spdE.AcceptedType = caloTrTypes + inPRS.AcceptedType = caloTrTypes + prsE.AcceptedType = caloTrTypes + prse.AcceptedType = caloTrTypes + if bremTrTypes != [] : + inBREM.AcceptedType = bremTrTypes + brem.AcceptedType = bremTrTypes + bChi2.AcceptedType = bremTrTypes + breme.AcceptedType = bremTrTypes + + # === Override CaloFutureAlgUtils default track location === + if trackLocation : + electron.Tracks = trackLocation + brem.Tracks = trackLocation + inBREM.Inputs = trackLocation + inHCAL.Inputs = trackLocation + eChi2.Tracks = trackLocation + bChi2.Tracks = trackLocation + cChi2.Tracks = trackLocation + ecalE.Inputs = trackLocation + hcalE.Inputs = trackLocation + if not noSpdPrs : + inPRS.Inputs = trackLocation + inSPD.Inputs = trackLocation + spdE.Inputs = trackLocation + prsE.Inputs = trackLocation + + charged.Members = [] + # updatXe global sequence with charged + if 'InAcceptance' in list : charged.Members += [ inAcc ] + if 'Match' in list : charged.Members += [ match ] + if 'Energy' in list : charged.Members += [ energy ] + if 'Chi2' in list : charged.Members += [ chi2 ] + if 'DLL' in list or 'DLLe' in list : charged.Members += [ dlle ] + if 'DLL' in list or 'DLLmu' in list : charged.Members += [ dllmu ] + + # alternative full sequence per technique + if 'EcalPID' in list : charged.Members += [ ecalT ] + if 'BremPID' in list : charged.Members += [ bremT ] + if 'HcalPID' in list : charged.Members += [ hcalT ] + if 'PrsPID' in list and not noSpdPrs : charged.Members += [ prsT ] + if 'SpdPID' in list and not noSpdPrs : charged.Members += [ spdT ] + if charged.Members : addAlgs( seq , charged ) + + + ## Add Neutrals (! No neutralID so far for the noSpdPrs configuration ) + if not skipNeutrals and not noSpdPrs: + _name = 'NeutralPIDs' + if name != context or context.upper() == 'OFFLINE': _name = _name+name + neutrals = getAlgo( GaudiSequencer , _name , context ) + photonID = PhotonID( context , enableRecoOnDemand ) + mergedID = MergedID( context , enableRecoOnDemand ) + photonFromMergedID = PhotonFromMergedID( context , enableRecoOnDemand ) + # update global sequence with neutrals + neutrals.Members = [] + if 'PhotonID' in list or 'NeutralPID' in list : neutrals.Members += [ photonID ] + if 'MergedID' in list or 'NeutralPID' in list : neutrals.Members += [ mergedID ] + if 'PhotonFromMergedID' in list or 'NeutralPID' in list : neutrals.Members += [ photonFromMergedID ] + if neutrals.Members : addAlgs( seq , neutrals ) + + + + setTheProperty ( seq , 'Context' , context ) + + log.debug ( 'Configure CaloFuture PIDs Reco : %s for context : %s' %( seq.name() , context) ) + + return seq + + + +def referencePIDs( dataType='' ) : + + """ + Define various reference Histograms on THS + """ + hsvc = HistogramSvc ( 'HistogramDataSvc' ) + inputs = hsvc.Input + + # photon PDF default + pfound = False + for line in inputs : + if 0 == line.find ( 'CaloFutureNeutralPIDs') : pfound = True + + if pfound : + log.info ("CaloFuturePIDsConf: LUN 'CaloFutureNeutralPIDs' has been defined already") + else: + hsvc.Input += [ "CaloFutureNeutralPIDs DATAFILE='$PARAMFILESROOT/data/PhotonPdf.root' TYP='ROOT'" ] + + + # charged PDF default + found = False + for line in inputs : + if 0 == line.find ( 'CaloFuturePIDs') : found = True + + if found : + log.info ("CaloFuturePIDsConf: LUN 'CaloFuturePIDs' has been defined already") + elif 'DC06' == dataType : + hsvc.Input += [ "CaloFuturePIDs DATAFILE='$PARAMFILESROOT/data/CaloPIDs_DC06_v2.root' TYP='ROOT'" ] + else: + hsvc.Input += [ "CaloFuturePIDs DATAFILE='$PARAMFILESROOT/data/CaloPIDs_DC09_v1.root' TYP='ROOT'" ] + + return + + +# ============================================================================= +if '__main__' == __name__ : + print __doc__ + diff --git a/CaloFuture/CaloFuturePIDs/python/CaloFuturePIDs/__init__.py b/CaloFuture/CaloFuturePIDs/python/CaloFuturePIDs/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/CaloFuture/CaloFuturePIDs/src/BremChi22IDFuture.cpp b/CaloFuture/CaloFuturePIDs/src/BremChi22IDFuture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..271322efccf3f34fa90fa0eb0744d7713dcc3bcf --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/BremChi22IDFuture.cpp @@ -0,0 +1,34 @@ +// Include files +#include "CaloFutureChi22ID.h" +#include "ToVector.h" + +// ============================================================================ +/** @class BremChi22IDFuture BremChi22IDFuture.cpp + * The preconfigured instance of class CaloFutureChi22ID + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + */ +// ============================================================================ +using TABLEI = LHCb::RelationWeighted2D<LHCb::CaloHypo, LHCb::Track, float>; +using TABLEO = LHCb::Relation1D<LHCb::Track, float>; + +struct BremChi22IDFuture final : public CaloFutureChi22ID<TABLEI,TABLEO> { + static_assert( + std::is_base_of<LHCb::CaloFuture2Track::IHypoTrTable2D, TABLEI>::value, + "TABLEI must inherit from IHypoTrTable2D"); + BremChi22IDFuture(const std::string& name, ISvcLocator* pSvc) + : CaloFutureChi22ID<TABLEI,TABLEO>(name, pSvc) { + using LHCb::CaloFutureAlgUtils::CaloFutureIdLocation; + Gaudi::Functional::updateHandleLocation(*this, "Input", CaloFutureIdLocation("BremMatch", context())); + Gaudi::Functional::updateHandleLocation(*this, "Output", CaloFutureIdLocation("BremChi2", context())); + // @todo it must be in agrement with "Threshold" for BremMatchAlgFuture + _setProperty("CutOff", "10000"); + // track types: + _setProperty("AcceptedType", Gaudi::Utils::toString<int>( + LHCb::Track::Types::Velo, LHCb::Track::Types::Long, + LHCb::Track::Types::Upstream)); + }; +}; + +// ============================================================================ + +DECLARE_COMPONENT( BremChi22IDFuture ) diff --git a/CaloFuture/CaloFuturePIDs/src/BremMatchAlgFuture.cpp b/CaloFuture/CaloFuturePIDs/src/BremMatchAlgFuture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ff3a871d20628f8d4a85eb257d1cc5ce2cd17b22 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/BremMatchAlgFuture.cpp @@ -0,0 +1,36 @@ +// Include files +#include "CaloFutureTrackMatchAlg.h" + +// ============================================================================= +/** @class BremMatchAlgFuture + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-16 + */ +// ============================================================================= +using TABLE = LHCb::RelationWeighted2D<LHCb::CaloHypo, LHCb::Track, float>; +using CALOFUTURETYPES = LHCb::CaloHypos; + +struct BremMatchAlgFuture final : CaloFutureTrackMatchAlg<TABLE,CALOFUTURETYPES> { + static_assert(std::is_base_of<LHCb::CaloFuture2Track::IHypoTrTable2D, TABLE>::value, + "TABLE must inherit from IHypoTrTable2D"); + + BremMatchAlgFuture(const std::string& name, ISvcLocator* pSvc) + : CaloFutureTrackMatchAlg<TABLE,CALOFUTURETYPES>(name, pSvc) { + Gaudi::Functional::updateHandleLocation(*this, "Calos", LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation("Photons",context())); + Gaudi::Functional::updateHandleLocation(*this, "Output", LHCb::CaloFutureAlgUtils::CaloFutureIdLocation("BremMatch",context())); + Gaudi::Functional::updateHandleLocation(*this, "Filter", LHCb::CaloFutureAlgUtils::CaloFutureIdLocation("InBrem",context())); + + _setProperty("Tool", "CaloFutureBremMatch/BremMatchFuture"); + _setProperty("Threshold", "10000"); + // track types: + _setProperty("AcceptedType", Gaudi::Utils::toString<int>( + LHCb::Track::Types::Velo, LHCb::Track::Types::Long, + LHCb::Track::Types::Upstream)); + _setProperty("TableSize", "1000"); + } + +}; + +// ============================================================================= + +DECLARE_COMPONENT( BremMatchAlgFuture ) diff --git a/CaloFuture/CaloFuturePIDs/src/BremPIDeAlgFuture.cpp b/CaloFuture/CaloFuturePIDs/src/BremPIDeAlgFuture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bae0e92c00c0925469d0a6cec20a67f17856d106 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/BremPIDeAlgFuture.cpp @@ -0,0 +1,50 @@ +// Include files +#include "CaloFutureID2DLL.h" + +// ============================================================================ +/** @class BremPIDeAlgFuture BremPIDeAlgFuture.cpp + * The preconfigured instance of class CaloFutureID2DLL + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-18 + */ +// ============================================================================ + +class BremPIDeAlgFuture final : public CaloFutureID2DLL { + public: + /// Standard protected constructor + BremPIDeAlgFuture(const std::string& name, ISvcLocator* pSvc) + : CaloFutureID2DLL(name, pSvc) { + using LHCb::CaloFutureAlgUtils::CaloFutureIdLocation; + + Gaudi::Functional::updateHandleLocation( + *this, "Input", CaloFutureIdLocation("BremChi2", context())); + Gaudi::Functional::updateHandleLocation( + *this, "Output", CaloFutureIdLocation("BremPIDe", context())); + + _setProperty("nVlong" , Gaudi::Utils::toString(200)); + _setProperty("nVvelo" , Gaudi::Utils::toString(200)); + _setProperty("nVupstr", Gaudi::Utils::toString(200)); + _setProperty("nMlong" , Gaudi::Utils::toString(50 * Gaudi::Units::GeV)); + _setProperty("nMvelo" , Gaudi::Utils::toString(50 * Gaudi::Units::GeV)); + _setProperty("nMupstr", Gaudi::Utils::toString(50 * Gaudi::Units::GeV)); + + _setProperty("HistogramU" , "DLL_Long"); + _setProperty("HistogramL" , "DLL_Long"); + _setProperty("HistogramV" , "DLL_Long"); + _setProperty("ConditionName", "Conditions/ParticleID/Calo/BremPIDe"); + + _setProperty("HistogramU_THS", "CaloFuturePIDs/CALO/BREMPIDE/h3"); + _setProperty("HistogramL_THS", "CaloFuturePIDs/CALO/BREMPIDE/h3"); + _setProperty("HistogramV_THS", "CaloFuturePIDs/CALO/BREMPIDE/h3"); + + _setProperty("AcceptedType", Gaudi::Utils::toString<int>( + LHCb::Track::Types::Velo, LHCb::Track::Types::Long, + LHCb::Track::Types::Upstream)); + }; +}; + +// ============================================================================ + +DECLARE_COMPONENT( BremPIDeAlgFuture ) + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFutureBremMatch.cpp b/CaloFuture/CaloFuturePIDs/src/CaloFutureBremMatch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..41900ffe2cb641b2ee6bd04443421e666c77f3ed --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFutureBremMatch.cpp @@ -0,0 +1,165 @@ +// Include files +#include "CaloFutureInterfaces/ICaloFutureTrackMatch.h" +#include "Event/Track.h" +#include "Event/CaloPosition.h" +#include "CaloFutureTrackMatch.h" +#include "Linear.h" + +// ============================================================================ +/** @file + * Implementation file for class CaloFutureBremMatch + * @date 2006-05-29 + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + */ +// ============================================================================ + +class CaloFutureBremMatch final : public virtual ICaloFutureTrackMatch, + public CaloFutureTrackMatch { + public: + /// initialize the tool + StatusCode initialize() override { + StatusCode sc = CaloFutureTrackMatch::initialize(); + if ( sc.isFailure() ) { return sc ; } + m_showerMax = calo()->plane(CaloPlane::ShowerMax); + return StatusCode::SUCCESS; + } + + public: + /** the main matching method + * @see ICaloFutureTrackMatch + * @param caloObj pointer to "calorimeter" object (position) + * @param trObj pointer to tracking object (track) + * @param chi2 returned value of chi2 of the matching + * @return status code for matching procedure + */ + StatusCode match(const LHCb::CaloPosition* caloObj, const LHCb::Track* trObj, + double& chi2) override; + + /** The main matching method (Stl interface) + * @see ICaloFutureTrackMatch + * @param caloObj pointer to "calorimeter" object (position) + * @param trObj pointer to tracking object (track) + * @return pair of status code/chi2 for matching procedure + */ + MatchingPair operator()(const LHCb::CaloPosition* caloObj, + const LHCb::Track* trObj) override { + double chi2; + StatusCode sc = match(caloObj, trObj, chi2); + return std::make_pair(sc, chi2); + } + + /** extract the TrState which was actually used for last matching + * @attention TrState is owned by the tool itself + * The better solution could be to return the pointer + * to TrStateP + * @return pointer to the state actually used for last matching + */ + const LHCb::State* state() const override { return &_state(); } + + CaloFutureBremMatch(const std::string& type, const std::string& name, + const IInterface* parent) + : CaloFutureTrackMatch(type, name, parent) { + declareInterface<ICaloFutureTrackMatch>(this); + _setProperty("CalorimeterFuture", DeCalorimeterLocation::Ecal); + _setProperty("Tolerance", "10"); // 10 millimeters + _setProperty("zForFastExtrapolator", "0"); // 0 meters + } + + private: + typedef CaloFutureTrackMatch::Match_<2> Match; + // + Match m_caloMatch; + Match m_trackMatch; + Gaudi::Plane3D m_showerMax; + const LHCb::CaloPosition* m_cBad = nullptr; + const LHCb::Track* m_tBad = nullptr; +}; + +// ============================================================================ + +DECLARE_COMPONENT( CaloFutureBremMatch ) + +// ============================================================================ +/// the main matching method +// ============================================================================ + +StatusCode CaloFutureBremMatch::match(const LHCb::CaloPosition* caloObj, + const LHCb::Track* trObj, double& chi2) { + chi2 = bad(); // reset chi2 + + // check the stored values! + if (m_cBad == caloObj || m_tBad == trObj) { + return StatusCode::FAILURE; + } + + if (caloObj == nullptr) { + return Error("match(): CaloPosition* points to NULL"); + } + + if (!use(trObj)) { + return Error("match(): track is not OK"); + } + + if (updateCaloFuturePos(m_position, caloObj)) { + // if ( m_position != caloObj ){ + // update the position + StatusCode sc = fillBrem(*caloObj, m_caloMatch); + if (sc.isFailure()) { + m_cBad = caloObj; + return Warning("match(): Error from fill(2D) ", sc, 0); + } + // find the proper plane in the detector + const LHCb::CaloPosition::Center& par = caloObj->center(); + const Gaudi::XYZPoint point(par(0), par(1), caloObj->z()); + if (tolerance() < m_plane.Distance(point)) { + m_plane = calo()->plane(point); + } + // keep the track of the position + m_position = caloObj; + } + // + // get the correct state + const LHCb::State* state = nullptr; + { // get the correct state at TT + state = CaloFutureTrackTool::state(*trObj, LHCb::State::Location::AtTT); + if (state == nullptr) { + state = CaloFutureTrackTool::state(*trObj, LHCb::State::Location::EndRich1); + } + if (state == nullptr) { + state = CaloFutureTrackTool::state(*trObj, LHCb::State::Location::BegRich1); + } + if (state == nullptr) { + state = CaloFutureTrackTool::state(*trObj, LHCb::State::Location::EndVelo); + } + // no appropriate state is found + if (state == nullptr) { + // get the closest state to some artificial value + state = &(trObj->closestState(2.0 * Gaudi::Units::meter)); + // allowed z ? + if (state->z() > 4.0 * Gaudi::Units::meter) { + if (msgLevel(MSG::DEBUG)) print(debug(), trObj); + m_tBad = trObj; + return Warning("No appropriate states are found, see 'debug'"); + } + } + // use the linear extrapolator + // StatusCode sc = propagate ( _state() , m_plane ); + StatusCode sc = Utils::Linear::propagate(*state, m_plane, _state()); + if (sc.isFailure()) { + m_tBad = trObj; + return Warning("match(): failure from propagate (1) ", sc); + } + } + + StatusCode sc = fill(_state(), m_trackMatch); + if (sc.isFailure()) { + return Warning("match(): error for fill(2D)"); + } + + // make a real evaluation + chi2 = CaloFutureTrackMatch::chi2(m_caloMatch, m_trackMatch); + + return StatusCode::SUCCESS; +} + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFutureChi22ID.cpp b/CaloFuture/CaloFuturePIDs/src/CaloFutureChi22ID.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f004dd8bc7f9b0105b3ee6cc5a40791bb18a3ec --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFutureChi22ID.cpp @@ -0,0 +1,51 @@ +// Include files +#include "CaloFutureChi22ID.h" + +// ============================================================================= +/** @file + * Implementation file for class CaloFutureChi22ID + * @date 2006-06-18 + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + */ +// ============================================================================= + +//DECLARE_COMPONENT( CaloFutureChi22ID ) + +// ============================================================================= +/// Standard protected constructor +// ============================================================================= +template <typename TABLEI, typename TABLEO> +CaloFutureChi22ID<TABLEI,TABLEO>::CaloFutureChi22ID(const std::string& name, ISvcLocator* pSvcLocator) + : base_type(name, pSvcLocator, {KeyValue{"Tracks",""},KeyValue{"Input",""}},KeyValue{"Output",""}) { + // context-dependent default track container + Gaudi::Functional::updateHandleLocation(*this, "Tracks", LHCb::CaloFutureAlgUtils::TrackLocations(context()).front()); +} + +// ============================================================================= +/// algorithm execution +// ============================================================================= +template <typename TABLEI, typename TABLEO> +TABLEO CaloFutureChi22ID<TABLEI,TABLEO>::operator()(const LHCb::Tracks& tracks, const TABLEI& input) const { + + TABLEO output(input.relations().size()+10); + for(auto const& track : tracks){ + if( !use(track) ) continue; + auto links = input.inverse()->relations( track ); + // fill the relation table + auto chi2 = links.empty() ? m_large.value() : links.front().weight(); + output.i_push( track,chi2 ); + } + /// MANDATORY: i_sort after i_push + output.i_sort(); + + m_nTracks+= tracks.size(); + m_nLinks += output.i_relations().size(); + + return output; +} + +// ============================================================================= + +template class CaloFutureChi22ID<LHCb::RelationWeighted2D<LHCb::CaloHypo, LHCb::Track, float>,LHCb::Relation1D<LHCb::Track,float>>; +template class CaloFutureChi22ID<LHCb::RelationWeighted2D<LHCb::CaloCluster, LHCb::Track, float>,LHCb::Relation1D<LHCb::Track,float>>; + diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFutureChi22ID.h b/CaloFuture/CaloFuturePIDs/src/CaloFutureChi22ID.h new file mode 100644 index 0000000000000000000000000000000000000000..52f206af2db4c2fc944acb2d3a920da69530d690 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFutureChi22ID.h @@ -0,0 +1,48 @@ +#ifndef CALOFUTUREPIDS_CALOFUTURECHI22ID_H +#define CALOFUTUREPIDS_CALOFUTURECHI22ID_H 1 + +// Include files +#include "CaloFutureTrackAlg.h" +#include "CaloFutureUtils/CaloFuture2Track.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "Event/CaloCluster.h" +#include "Event/CaloHypo.h" +#include "Event/Track.h" +#include "GaudiAlg/Transformer.h" +#include "GaudiKernel/Counters.h" +#include "Relations/Relation1D.h" +#include "Relations/RelationWeighted2D.h" + +// ============================================================================ +/** @class CaloFutureChi22ID CaloFutureChi22ID.h + * + * + * @author Ivan BELYAEV + * @date 2006-06-18 + */ +// ============================================================================ +template <typename TABLEI, typename TABLEO> +class CaloFutureChi22ID : public Gaudi::Functional::Transformer<TABLEO(const LHCb::Tracks&,const TABLEI&), Gaudi::Functional::Traits::BaseClass_t<CaloFutureTrackAlg> > +{ + public: + using CaloFutureTrackAlg::context; + using CaloFutureTrackAlg::use; + using CaloFutureTrackAlg::getProperty; + using CaloFutureTrackAlg::_setProperty; + using base_type = Gaudi::Functional::Transformer<TABLEO(const LHCb::Tracks&,const TABLEI&),Gaudi::Functional::Traits::BaseClass_t<CaloFutureTrackAlg> >; + using KeyValue = typename base_type::KeyValue; + + // standard constructor + CaloFutureChi22ID(const std::string& name, ISvcLocator* pSvc); + + /// algorithm execution + TABLEO operator()(const LHCb::Tracks& tracks, const TABLEI& input) const override; + + protected: + Gaudi::Property<float> m_large{ this, "CutOff", 10000, "large value"}; + + mutable Gaudi::Accumulators::StatCounter<> m_nLinks {this, "#links in table"}; + mutable Gaudi::Accumulators::StatCounter<> m_nTracks {this, "#total tracks"}; +}; +#endif // CALOFUTURECHI22ID_H +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFutureElectronMatch.cpp b/CaloFuture/CaloFuturePIDs/src/CaloFutureElectronMatch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7144ae0de0e9663e19d72a755085c266749a2e66 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFutureElectronMatch.cpp @@ -0,0 +1,162 @@ +// Include files +#include "CaloFutureInterfaces/ICaloFutureTrackMatch.h" +#include "Event/Track.h" +#include "Event/CaloPosition.h" +#include "CaloFutureTrackMatch.h" + +// ============================================================================ +/** @file + * Implementation file for class CaloFutureElectronMatch + * @date 2006-05-29 + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + */ +// ============================================================================ + +class CaloFutureElectronMatch final : public virtual ICaloFutureTrackMatch, + public CaloFutureTrackMatch { + public: + /// initialize the tool + StatusCode initialize() override { + StatusCode sc = CaloFutureTrackMatch::initialize(); + if (sc.isFailure()) { return sc; } + m_showerMax = calo()->plane(CaloPlane::ShowerMax); + return StatusCode::SUCCESS; + }; + + public: + /** the main matching method + * @see ICaloFutureTrackMatch + * @param caloObj pointer to "calorimeter" object (position) + * @param trObj pointer to tracking object (track) + * @param chi2 returned value of chi2 of the matching + * @return status code for matching procedure + */ + StatusCode match(const LHCb::CaloPosition* caloObj, const LHCb::Track* trObj, + double& chi2) override; + + /** The main matching method (Stl interface) + * @see ICaloFutureTrackMatch + * @param caloObj pointer to "calorimeter" object (position) + * @param trObj pointer to tracking object (track) + * @return pair of status code/chi2 for matching procedure + */ + MatchingPair operator()(const LHCb::CaloPosition* caloObj, + const LHCb::Track* trObj) override { + double chi2; + StatusCode sc = match(caloObj, trObj, chi2); + return std::make_pair(sc, chi2); + }; + + /** extract the TrState which was actually used for last matching + * @attention TrState is owned by the tool itself + * The better solution could be to return the pointer + * to TrStateP + * @return pointer to the state actually used for last matching + */ + const LHCb::State* state() const override { return &_state(); }; + + CaloFutureElectronMatch(const std::string& type, const std::string& name, + const IInterface* parent) + : CaloFutureTrackMatch(type, name, parent) { + declareInterface<ICaloFutureTrackMatch>(this); + _setProperty("CalorimeterFuture", DeCalorimeterLocation::Ecal); + _setProperty("Tolerance", "5"); // 5 millimeters + }; + + private: + typedef CaloFutureTrackMatch::Match_<3> Match; + // + Match m_caloMatch; + Match m_trackMatch; + Gaudi::Plane3D m_showerMax; + const LHCb::CaloPosition* m_cBad = nullptr; + const LHCb::Track* m_tBad = nullptr; +}; + +// ============================================================================ + +DECLARE_COMPONENT( CaloFutureElectronMatch ) + +// ============================================================================ +/// the main matching method +// ============================================================================ + +StatusCode CaloFutureElectronMatch::match(const LHCb::CaloPosition* caloObj, + const LHCb::Track* trObj, double& chi2) { + using namespace LHCb; + + chi2 = bad(); // reset chi2 + // + // check the stored values! + if (m_cBad == caloObj || m_tBad == trObj) { + return StatusCode::FAILURE; + } + + if (caloObj == nullptr) { + return Error("match(): CaloPosition* points to NULL"); + } + + if (!use(trObj)) { + return Error("match(): track is not OK"); + } + + if (updateCaloFuturePos(m_position, caloObj)) { + // update the position + StatusCode sc = fill(*caloObj, m_caloMatch); + if (sc.isFailure()) { + m_cBad = caloObj; + return Warning("match(): Error from fill(2D) ", sc, 0); + } + // find the proper plane in detector + const LHCb::CaloPosition::Center& par = caloObj->center(); + const Gaudi::XYZPoint point(par(0), par(1), caloObj->z()); + if (tolerance() < m_plane.Distance(point)) { + m_plane = calo()->plane(point); + } + // keep the track of the position + m_position = caloObj; + } + // + // get the correct state + const LHCb::State* st = nullptr; + { + st = CaloFutureTrackTool::state(*trObj, LHCb::State::Location::ECalShowerMax); + if (st == nullptr) { + StatusCode sc = propagate(*trObj, m_showerMax, _state()); + if (sc.isFailure()) { + m_tBad = trObj; + return Warning("match(): failure from propagate (1) ", sc); + } + _state().setLocation(LHCb::State::Location::ECalShowerMax); + const_cast<LHCb::Track*>(trObj)->addToStates(_state()); + st = CaloFutureTrackTool::state(*trObj, LHCb::State::Location::ECalShowerMax); + } + // check the validity of the state + if (tolerance() < ::fabs(m_plane.Distance(st->position()))) + // if ( 1 * Gaudi::Units::mm < ::fabs( caloObj->z() - st->position().z() ) ) + // // let's decrease z-tolerance here to 1 mm + { + _state() = *st; + StatusCode sc = propagate(_state(), m_plane); + // StatusCode sc = propagate ( _state() , caloObj->z() ); + if (sc.isFailure()) { + m_tBad = trObj; + return Warning("match(): failure from propagate (2) ", sc); + } + st = &_state(); + } + } + + Assert(st != nullptr, "LHCb::State* points to NULL!"); + StatusCode sc = fill(*st, m_trackMatch); + if (sc.isFailure()) { + return Warning("match(): error for fill(3D)"); + } + + // make a real evaluation + chi2 = CaloFutureTrackMatch::chi2(m_caloMatch, m_trackMatch); + + return StatusCode::SUCCESS; +} + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFutureEnergyForTrack.cpp b/CaloFuture/CaloFuturePIDs/src/CaloFutureEnergyForTrack.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb17cc42acf896f7472d76c2e72cdb9bebf2ab07 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFutureEnergyForTrack.cpp @@ -0,0 +1,328 @@ +// Include files +#include "CaloFutureEnergyForTrack.h" +#include <set> +#include "CaloFutureInterfaces/ICaloFutureTrackIdEval.h" +#include "CaloFutureUtils/CaloFutureNeighbours.h" +#include "Event/CaloDigit.h" +#include "Event/Track.h" +#include "GaudiKernel/IIncidentListener.h" +#include "GaudiKernel/IIncidentSvc.h" + +// ============================================================================ +// constructor +// ============================================================================ + +CaloFutureEnergyForTrack::CaloFutureEnergyForTrack(const std::string &type, + const std::string &name, + const IInterface *parent) + : CaloFuture::CaloFutureTrackTool(type, name, parent) { + declareInterface <ICaloFutureTrackIdEval> ( this ) ; + declareInterface <ICaloFutureDigits4Track> ( this ) ; + declareInterface <IIncidentListener> ( this ) ; +} + +// ============================================================================ +// initialize the tool +// ============================================================================ + +StatusCode CaloFutureEnergyForTrack::initialize() { + StatusCode sc = CaloFuture::CaloFutureTrackTool::initialize(); + if (sc.isFailure()) { + return sc; + } + if (m_address.empty()) { + return Error("Invalid 'DataAddress'"); + } + auto isvc = service<IIncidentSvc>("IncidentSvc", true); + isvc->addListener(this, IncidentType::BeginEvent); + // + std::string det = detectorName(); + const long caloID = CaloCellCode::CaloNumFromName(det.c_str()); + switch (caloID) { + case 0: + // SPD + m_location = LHCb::State::Location::Spd; + m_planes = {calo()->plane(CaloPlane::Middle)}; + break; // BREAK + case 1: + // PRS + m_location = LHCb::State::Location::Prs; + m_planes = {calo()->plane(CaloPlane::Middle)}; + break; + case 2: + // ECAL + m_location = LHCb::State::Location::ECalShowerMax; + m_planes = { + calo()->plane(CaloPlane::Front), calo()->plane(CaloPlane::ShowerMax), + calo()->plane(CaloPlane::Middle), calo()->plane(CaloPlane::Back)}; + break; + case 3: + // HCAL + m_location = LHCb::State::Location::MidHCal; + m_planes = {calo()->plane(CaloPlane::Front), + calo()->plane(CaloPlane::Middle), + calo()->plane(CaloPlane::Back)}; + break; + default: + return Error("Invald calorimeter TYPE! '" + detectorName() + "'"); + } + // + if (propsPrint() || msgLevel(MSG::DEBUG)) { + info() << "State Location is set to '" << m_location << "'" << endmsg; + } + // + if (m_planes.empty()) { + return Error("Empty list of CaloFuture-planes"); + } + // + return StatusCode::SUCCESS; +} + +// ============================================================================ +/* collect the cellID-s along the line + * @param line (INPUT) the line + * @param cells (OUTPUT) the container of cells + * @return status code + */ +// ============================================================================ + +StatusCode CaloFutureEnergyForTrack::collect(const CaloFutureEnergyForTrack::Line& line, + LHCb::CaloCellID::Set& cells) const { + cells.clear(); + + // get the interesection points of the line with the planes + Points points; + { + points.reserve(m_planes.size() + m_morePlanes); + // get the intersection points + for (const auto plane: m_planes){ + double mu = 0; + Gaudi::XYZPoint point; + Gaudi::Math::intersection(line, plane, point, mu); + points.push_back(point); + } + // add some additional points (if requested) + if (2 <= points.size() && 0 < m_morePlanes) { + // the same line but in another reparameterization: + const auto l2 = Line(points.front(), points.back() - points.front()); + const double dmu = 1.0 / (1.0 + m_morePlanes); + for (unsigned short i = 0; i < m_morePlanes; ++i) { + points.push_back(l2.position(dmu * (i + 1.0))); + } + } + } + // get all touched calorimeter cells: convert points to cells + for (const auto point: points){ + // get the cell ! + const auto callParam = calo()->Cell_(point); + /// skip invalid cells + if (callParam == nullptr || !callParam->valid()) { + continue; + } + // collect all valid cells + cells.insert(callParam->cellID()); + } + + // add neighbours + if (0 < m_addNeighbors) { + LHCb::CaloFutureFunctors::neighbours(cells, m_addNeighbors, calo()); + } + + return StatusCode::SUCCESS; +} +// ============================================================================ +/* collect the cellID-s along the line + * @param line (INPUT) the line + * @param cells (OUTPUT) the container of cells + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureEnergyForTrack::collect(const CaloFutureEnergyForTrack::Line& line, + LHCb::CaloCellID::Vector& cells) const { + cells.clear(); + Cells _cells; + StatusCode sc = collect(line, _cells); + if (sc.isFailure()) { + return sc; + } + cells.insert(cells.end(), _cells.begin(), _cells.end()); + return StatusCode::SUCCESS; +} +// ============================================================================ +/* collect the cellID-s along the path of the tracks + * @param track (INPUT) the track + * @param cells (OUTPUT) the container of cells + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureEnergyForTrack::collect(const LHCb::Track* track, + LHCb::CaloCellID::Set& cells) const { + cells.clear(); + + // get the correct state + auto state = CaloFutureTrackTool::state(*track, m_location); + if (state == nullptr) { + // propagate it! + StatusCode sc = propagate(*track, m_planes.front(), m_state); + if (sc.isFailure()) { + return Error("process(): failure from propagate, return 'bad'", sc); + } + // initialize the state + state = &m_state; + } + // get the line from the state: + const auto l1 = line(*state); + return collect(l1, cells); +} +// ============================================================================ +/* collect the cellID-s along the path of the tracks + * @param track (INPUT) the track + * @param cells (OUTPUT) the container of cells + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureEnergyForTrack::collect(const LHCb::Track* track, + LHCb::CaloCellID::Vector& cells) const { + cells.clear(); + Cells _cells; + StatusCode sc = collect(track, _cells); + if (sc.isFailure()) { + return Error("Error from collect(set)", sc); + } + cells.insert(cells.end(), _cells.begin(), _cells.end()); + return StatusCode::SUCCESS; +} +// ========================================================================== +/* collect the fired digits along the path of the tracks + * @param line (INPUT) the line + * @param hits (OUTPUT) the container of digits + * @return status code + */ +// ========================================================================== +StatusCode CaloFutureEnergyForTrack::collect(const CaloFutureEnergyForTrack::Line& line, + LHCb::CaloDigit::Set& hits) const { + hits.clear(); + Cells cells; + StatusCode sc = collect(line, cells); + if (sc.isFailure()) { + return Error("Error from collect(cells)", sc); + } + // convert cells into digits: + if (!cells.empty()) { + const Digits* data = digits(); + for (const auto cell: cells){ + // get the gidit + const auto digit = data->object(cell); + // accumulate good fired cells + if (digit != nullptr) { + hits.insert(digit); + } + } + } + return StatusCode::SUCCESS; +} +// ============================================================================ +/* collect the fired digits along the line + * @param line (INPUT) the line + * @param digits (OUTPUT) the container of digits + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureEnergyForTrack::collect(const CaloFutureEnergyForTrack::Line& line, + LHCb::CaloDigit::Vector& hits) const { + hits.clear(); + LHCb::CaloDigit::Set _hits; + StatusCode sc = collect(line, _hits); + if (sc.isFailure()) { + return Error("Error from collect(set)", sc); + } + hits.insert(hits.end(), _hits.begin(), _hits.end()); + return StatusCode::SUCCESS; +} +// ============================================================================ +/* collect the digits from the given calorimeter along the track + * @param track (INPUT) pointer to the object to be processed + * @param digits (OUTPUT) the conatiner of collected digits + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureEnergyForTrack::collect(const LHCb::Track* track, + LHCb::CaloDigit::Set& hits) const { + hits.clear(); + Cells cells; + StatusCode sc = collect(track, cells); + if (sc.isFailure()) { + return Error("Error from collect(cells)", sc); + } + // convert cells into digits: + if (!cells.empty()) { + const auto data = digits(); + for (const auto cell: cells){ + // get the gidit + const auto digit = data->object(cell); + // accumulate good fired cells + if (digit != nullptr) { + hits.insert(digit); + } + } + } + return StatusCode::SUCCESS; +} +// ============================================================================ +/* collect the digits from the given calorimeter along the track + * @param track (INPUT) pointer to the object to be processed + * @param digits (OUTPUT) the conatiner of collected digits + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureEnergyForTrack::collect(const LHCb::Track* track, + LHCb::CaloDigit::Vector& hits) const { + hits.clear(); + LHCb::CaloDigit::Set _hits; + StatusCode sc = collect(track, _hits); + if (sc.isFailure()) { + return Error("Error from collect(set)", sc); + } + hits.insert(hits.end(), _hits.begin(), _hits.end()); + return StatusCode::SUCCESS; +} +// ============================================================================ +// The main processing method +// ============================================================================ +StatusCode CaloFutureEnergyForTrack::process(const LHCb::Track* track, + double& value) const { + value = m_bad; + LHCb::CaloDigit::Set hits; + StatusCode sc = collect(track, hits); + if (sc.isFailure()) { + return Error("Error from 'collect(set)'", sc); + } + + // accumulate the energy from all touched cells + double energy = 0; + for (const auto digit: hits){ + if (digit != nullptr) { + energy += digit->e(); + } + } + // + value = energy; // RESULT + // + return StatusCode::SUCCESS; +} +// ============================================================================ +// The main processing method (functor interface) +// ============================================================================ +double CaloFutureEnergyForTrack::operator()(const LHCb::Track* track) const { + double value = m_bad; + StatusCode sc = process(track, value); + Assert(sc.isSuccess(), "Failure from process():", sc); + return value; +} +// ============================================================================ +/// factory +// ============================================================================ +DECLARE_COMPONENT( CaloFutureEnergyForTrack ) +// ============================================================================ +// The END +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFutureEnergyForTrack.h b/CaloFuture/CaloFuturePIDs/src/CaloFutureEnergyForTrack.h new file mode 100644 index 0000000000000000000000000000000000000000..74cb3f68eeba9148b303df3ccc35a4c15573ee20 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFutureEnergyForTrack.h @@ -0,0 +1,153 @@ +#ifndef CALOFUTUREENERGYFORTRACK_H +#define CALOFUTUREENERGYFORTRACK_H 1 + +// Include files +#include <set> +#include "GaudiKernel/IIncidentSvc.h" +#include "GaudiKernel/IIncidentListener.h" +#include "CaloFutureInterfaces/ICaloFutureTrackIdEval.h" +#include "CaloFutureInterfaces/ICaloFutureDigits4Track.h" +#include "Event/Track.h" +#include "Event/CaloDigit.h" +#include "CaloFutureTrackTool.h" + +// ============================================================================ +/** @class CaloFutureEnergyForTrack + * tool which accumulates the energy for the given track + * along the track line + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + */ +class CaloFutureEnergyForTrack : public virtual ICaloFutureTrackIdEval, + public virtual ICaloFutureDigits4Track, + public virtual IIncidentListener, + public CaloFuture::CaloFutureTrackTool { + public: + typedef LHCb::CaloDigit::Container Digits; + typedef ICaloFutureDigits4Track::Line Line; + + /// Inform that a new incident has occured @see IIncidentListener + void handle(const Incident&) override { m_digits = 0; } + + StatusCode initialize() override; + + /** The main processing method + * It evaluated the Track ID estimators using the calorimeter information + * @param track pointer to the object to be processed + * @param value (return) the value of the estimator + * @return status code + */ + StatusCode process(const LHCb::Track* track, double& value) const override; + + /** The main processing method (functor interface) + * It evaluated the Track ID estimators using the calorimeter information + * @param track pointer to the object to be processed + */ + double operator()(const LHCb::Track* track) const override; + + /** collect the cellID-s along the line + * @param line (INPUT) the line + * @param cells (OUTPUT) the container of cells + * @return status code + */ + StatusCode collect(const Line& line, + LHCb::CaloCellID::Vector& cells) const override; + + /** collect the cellID-s along the line + * @param line (INPUT) the line + * @param cells (OUTPUT) the container of cells + * @return status code + */ + StatusCode collect(const Line& line, + LHCb::CaloCellID::Set& cells) const override; + + /** collect the cellID-s along the path of the tracks + * @param track (INPUT) the track + * @param cells (OUTPUT) the container of cells + * @return status code + */ + StatusCode collect(const LHCb::Track* track, + LHCb::CaloCellID::Vector& cells) const override; + + /** collect the cellID-s along the path of the tracks + * @param track (INPUT) the track + * @param cells (OUTPUT) the container of cells + * @return status code + */ + StatusCode collect(const LHCb::Track* track, + LHCb::CaloCellID::Set& cells) const override; + + /** collect the fired digits along the line + * @param line (INPUT) the line + * @param digits (OUTPUT) the container of digits + * @return status code + */ + StatusCode collect(const Line& line, + LHCb::CaloDigit::Vector& digits) const override; + + /** collect the fired digits along the path of the tracks + * @param line (INPUT) the line + * @param digits (OUTPUT) the container of digits + * @return status code + */ + StatusCode collect(const Line& line, + LHCb::CaloDigit::Set& digits) const override; + + /** collect the fired digits along the path of the tracks + * @param track (INPUT) the track + * @param digits (OUTPUT) the container of digits + * @return status code + */ + StatusCode collect(const LHCb::Track* track, + LHCb::CaloDigit::Vector& digits) const override; + + /** collect the fired digits along the path of the tracks + * @param track (INPUT) the track + * @param digits (OUTPUT) the container of digits + * @return status code + */ + StatusCode collect(const LHCb::Track* track, + LHCb::CaloDigit::Set& digits) const override; + + CaloFutureEnergyForTrack(const std::string& type, const std::string& name, + const IInterface* parent); + + protected: + // get the data form TES + inline const Digits* digits() const; + + typedef std::vector<Gaudi::Plane3D> Planes; + typedef std::vector<Gaudi::XYZPoint> Points; + typedef std::vector<LHCb::State*> States; + typedef LHCb::CaloCellID::Set Cells; + + private: + mutable const Digits* m_digits = nullptr; + mutable LHCb::State m_state; + + Gaudi::Property<std::string> m_address + {this, "DataAddress", "", "TES-location of corresponding CaloDigits"}; + + Gaudi::Property<double> m_bad + {this, "BadValue", 1e+10, "The bad value to be returned"}; + + LHCb::State::Location m_location = LHCb::State::Location::Spd; + Planes m_planes; + Gaudi::Property<unsigned short> m_morePlanes {this, "MorePlanes", 0}; + Gaudi::Property<unsigned short> m_addNeighbors {this, "AddNeighbours", 0}; + +}; + +// ============================================================================ +// get the data form TES +// ============================================================================ + +inline const CaloFutureEnergyForTrack::Digits* CaloFutureEnergyForTrack::digits() const { + if (m_digits == nullptr) { + m_digits = get<Digits>(m_address); + } + return m_digits; +} + +// ============================================================================ +#endif // CALOFUTUREENERGYFORTRACK_H +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFutureID2DLL.cpp b/CaloFuture/CaloFuturePIDs/src/CaloFutureID2DLL.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6c0c9cf454bc7b0d42b213b761cc4432522baa45 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFutureID2DLL.cpp @@ -0,0 +1,200 @@ +// Include files +#include <type_traits> +#include "GaudiKernel/ITHistSvc.h" +#include "DetDesc/HistoParam.h" +#include "CaloFutureID2DLL.h" +#include "GaudiUtils/Aida2ROOT.h" + +// ============================================================================ +/** @file + * Implementation file for class CaloFutureID2DLL + * @date 2006-06-18 + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + */ +// ============================================================================ + +DECLARE_COMPONENT( CaloFutureID2DLL ) + +// ============================================================================ +/// standard proected constructor +// ============================================================================ + +CaloFutureID2DLL::CaloFutureID2DLL(const std::string &name, ISvcLocator *pSvcLocator) + : Transformer(name, pSvcLocator, KeyValue{"Input", ""}, KeyValue{"Output", ""}) { + // track types + _setProperty("AcceptedType", Gaudi::Utils::toString<int>( + LHCb::Track::Types::Long, + LHCb::Track::Types::Ttrack, + LHCb::Track::Types::Downstream + )); +} + +//============================================================================== +// Algorithm initialization +//============================================================================== + +StatusCode CaloFutureID2DLL::initialize() { + StatusCode sc = Transformer::initialize(); + if (sc.isFailure()) + return sc; + + if (!existDet<DataObject>(detSvc(), m_conditionName)) { + warning() << "Initialise: Condition '" << m_conditionName + << "' not found -- switch to reading the DLLs from THS!" + << endmsg; + m_useCondDB = false; + } + + sc = m_useCondDB ? initializeWithCondDB() : initializeWithoutCondDB(); + return sc; +} + +// ============================================================================ + +StatusCode CaloFutureID2DLL::initializeWithCondDB() +{ + info() << "init with CondDB, m_conditionName = " << m_conditionName.value() << endmsg; + try { + registerCondition(m_conditionName, m_cond, &CaloFutureID2DLL::i_updateDLL); + } catch (GaudiException &e) { + fatal() << e << endmsg; + return StatusCode::FAILURE; + } + StatusCode sc = runUpdate(); // load the conditions + return sc; +} + +// ============================================================================ + +StatusCode CaloFutureID2DLL::initializeWithoutCondDB() { + info() << "init w/o CondDB (read the 2D DLL histograms from a root file " + "through THS)" + << endmsg; + + // locate the histogram + if (!m_title_lt_ths.empty()) { + AIDA::IHistogram2D *aida = + get<AIDA::IHistogram2D>(histoSvc(), m_title_lt_ths); + m_histo_lt = Gaudi::Utils::Aida2ROOT::aida2root(aida); + } + + if (!m_title_dt_ths.empty()) { + AIDA::IHistogram2D *aida = + get<AIDA::IHistogram2D>(histoSvc(), m_title_dt_ths); + m_histo_dt = Gaudi::Utils::Aida2ROOT::aida2root(aida); + } + + if (!m_title_tt_ths.empty()) { + AIDA::IHistogram2D *aida = + get<AIDA::IHistogram2D>(histoSvc(), m_title_tt_ths); + m_histo_tt = Gaudi::Utils::Aida2ROOT::aida2root(aida); + } + + if (!m_title_vt_ths.empty()) { + AIDA::IHistogram2D *aida = + get<AIDA::IHistogram2D>(histoSvc(), m_title_vt_ths); + m_histo_vt = Gaudi::Utils::Aida2ROOT::aida2root(aida); + } + + if (!m_title_ut_ths.empty()) { + AIDA::IHistogram2D *aida = + get<AIDA::IHistogram2D>(histoSvc(), m_title_ut_ths); + m_histo_ut = Gaudi::Utils::Aida2ROOT::aida2root(aida); + } + + if (msgLevel(MSG::DEBUG)) + debug() << "\nLong: '" << m_title_lt_ths << "' -> " + << (void *)m_histo_lt << "\nDownstream: '" << m_title_dt_ths + << "' -> " << (void *)m_histo_dt << "\nTTuricensis: '" + << m_title_tt_ths << "' -> " << (void *)m_histo_tt + << "\nUpstream: '" << m_title_ut_ths << "' -> " + << (void *)m_histo_ut << "\nVelo: '" << m_title_vt_ths + << "' -> " << (void *)m_histo_vt << endmsg; + + return StatusCode::SUCCESS; +} + +// ============================================================================ +/// Algorithm execution +// ============================================================================ + +Table CaloFutureID2DLL::operator()(const Table &input) const { + + // create and register the output ocntainer + const auto links = input.relations(); + auto table = Table(links.size()); + + // loop over all links + for (const auto link : links) { + const auto track = link.from(); + const double value = link.to(); + if (!use(track)) { + continue; + } + + // convert value to DLL + const double DLL = dLL(track->p(), value, track->type()); + + // fill the relation table + table.i_push(track, (float)DLL); // NB!: i_push + }; + /// MANDATORY: i_sort after i_push + table.i_sort(); + + if (counterStat->isQuiet()) + counter(inputLocation() + "=>" + outputLocation()) += + table.i_relations().size(); + + return table; +} + +// ============================================================================ + +StatusCode CaloFutureID2DLL::i_updateDLL() { + if (msgLevel(MSG::DEBUG)) + debug() << "i_updateDLL() called" << endmsg; + if (!m_cond) + return StatusCode::FAILURE; + + try { + if (!m_title_lt.empty()) { + m_histo_lt = reinterpret_cast<TH2D *>( + &m_cond->param<DetDesc::Params::Histo2D>(m_title_lt)); + } + + if (!m_title_dt.empty()) { + m_histo_dt = reinterpret_cast<TH2D *>( + &m_cond->param<DetDesc::Params::Histo2D>(m_title_dt)); + } + + if (!m_title_tt.empty()) { + m_histo_tt = reinterpret_cast<TH2D *>( + &m_cond->param<DetDesc::Params::Histo2D>(m_title_tt)); + } + + if (!m_title_ut.empty()) { + m_histo_ut = reinterpret_cast<TH2D *>( + &m_cond->param<DetDesc::Params::Histo2D>(m_title_ut)); + } + + if (!m_title_vt.empty()) { + m_histo_vt = reinterpret_cast<TH2D *>( + &m_cond->param<DetDesc::Params::Histo2D>(m_title_vt)); + } + } catch (GaudiException &exc) { + fatal() << "DLL update failed! msg ='" << exc << "'" << endmsg; + return StatusCode::FAILURE; + } + + if (msgLevel(MSG::DEBUG)) + debug() << "\nLong: '" << m_title_lt << "' -> " << (void *)m_histo_lt + << "\nDownstream: '" << m_title_dt << "' -> " << (void *)m_histo_dt + << "\nTTuricensis: '" << m_title_tt << "' -> " << (void *)m_histo_tt + << "\nUpstream: '" << m_title_ut << "' -> " << (void *)m_histo_ut + << "\nVelo: '" << m_title_vt << "' -> " << (void *)m_histo_vt + << endmsg; + + return StatusCode::SUCCESS; +} + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFutureID2DLL.h b/CaloFuture/CaloFuturePIDs/src/CaloFutureID2DLL.h new file mode 100644 index 0000000000000000000000000000000000000000..d3856d4b088dac7be5ad58b017e0dc3f9d2b8bcf --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFutureID2DLL.h @@ -0,0 +1,147 @@ +#ifndef CALOFUTUREPIDS_CALOFUTUREID2DLL_H +#define CALOFUTUREPIDS_CALOFUTUREID2DLL_H 1 + +// Include files +#include <cmath> +#include "GaudiKernel/VectorMap.h" +#include "GaudiAlg/Transformer.h" +#include "AIDA/IHistogram2D.h" +#include "Relations/IRelation.h" +#include "Relations/Relation1D.h" +#include "Event/Track.h" +#include "CaloFutureUtils/CaloFuture2Track.h" +#include "CaloFutureTrackAlg.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "ToString.h" +#include "ToVector.h" +#include "DetDesc/Condition.h" +#include "TH2D.h" + + +class ITHistSvc; + +// ============================================================================ +/** @class CaloFutureID2DLL CaloFutureID2DLL.h + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-18 + */ +// ============================================================================ + +using Table = LHCb::Relation1D<LHCb::Track, float>; + +class CaloFutureID2DLL : public Gaudi::Functional::Transformer< + Table(const Table &), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureTrackAlg>> { +public: + StatusCode initialize() override; + Table operator()(const Table& input) const override; + + /// callback function invoked by the UpdateManagerSvc + StatusCode i_updateDLL(); + StatusCode dumpDLLsToFile(); + + CaloFutureID2DLL(const std::string &name, ISvcLocator *pSvc); + +protected: + inline double dLL(const double p, const double v, + const LHCb::Track::Types t) const; + +private: + StatusCode initializeWithCondDB(); + StatusCode initializeWithoutCondDB(); + +protected: + // histogram title + Gaudi::Property<std::string> m_title_lt {this, "HistogramL", "", "histogram title long" }; + Gaudi::Property<std::string> m_title_dt {this, "HistogramD", "", "histogram title down" }; + Gaudi::Property<std::string> m_title_tt {this, "HistogramT", "", "histogram title TTrack"}; + Gaudi::Property<std::string> m_title_ut {this, "HistogramU", "", "histogram title upstr" }; + Gaudi::Property<std::string> m_title_vt {this, "HistogramV", "", "histogram title velo" }; + + Gaudi::Property<std::string> m_title_lt_ths {this, "HistogramL_THS", "", "histogram title long if DLLs are read from a root file via THS"}; + Gaudi::Property<std::string> m_title_dt_ths {this, "HistogramD_THS", "", "histogram title down if DLLs are read from a root file via THS"}; + Gaudi::Property<std::string> m_title_tt_ths {this, "HistogramT_THS", "", "histogram title TTrack if DLLs are read from a root file via THS"}; + Gaudi::Property<std::string> m_title_ut_ths {this, "HistogramU_THS", "", "histogram title upstr if DLLs are read from a root file via THS"}; + Gaudi::Property<std::string> m_title_vt_ths {this, "HistogramV_THS", "", "histogram title velo if DLLs are read from a root file via THS"}; + + Gaudi::Property<float> m_pScale_lt {this, "nMlong" , -1, "scale for mom long"}; + Gaudi::Property<float> m_pScale_dt {this, "nMdown" , -1, "scale for mom down"}; + Gaudi::Property<float> m_pScale_tt {this, "nMTtrack", -1, "scale for mom TT"}; + Gaudi::Property<float> m_pScale_ut {this, "nMupstr" , -1, "scale for val upstr"}; + Gaudi::Property<float> m_pScale_vt {this, "nMvelo" , -1, "scale for val velo"}; + + Gaudi::Property<float> m_vScale_lt {this, "nVlong" , -1, "scale for val long"}; + Gaudi::Property<float> m_vScale_dt {this, "nVdown" , -1, "scale for val down"}; + Gaudi::Property<float> m_vScale_tt {this, "nVTtrack", -1, "scale for val TT"}; + Gaudi::Property<float> m_vScale_ut {this, "nVupstr" , -1, "scale for val upstr"}; + Gaudi::Property<float> m_vScale_vt {this, "nVvelo" , -1, "scale for val velo"}; + +private: + + const TH2D *m_histo_lt = nullptr; + const TH2D *m_histo_dt = nullptr; + const TH2D *m_histo_tt = nullptr; + const TH2D *m_histo_ut = nullptr; + const TH2D *m_histo_vt = nullptr; + + Gaudi::Property<bool> m_useCondDB + {this, "UseCondDB", true, "if true - use CondDB, otherwise get the DLLs via THS from a root file"}; + + Gaudi::Property<std::string> m_conditionName {this, "ConditionName"}; + Condition * m_cond = nullptr; +}; + +// ============================================================================ + +inline double CaloFutureID2DLL::dLL(const double p, const double v, + const LHCb::Track::Types t) const { + const TH2D *histo = nullptr; + double pScale = -1.; + double vScale = -1.; + + switch (t) { + case LHCb::Track::Types::Long: + histo = m_histo_lt; + pScale = m_pScale_lt; + vScale = m_vScale_lt; + break; + case LHCb::Track::Types::Downstream: + histo = m_histo_dt; + pScale = m_pScale_dt; + vScale = m_vScale_dt; + break; + case LHCb::Track::Types::Upstream: + histo = m_histo_ut; + pScale = m_pScale_ut; + vScale = m_vScale_ut; + break; + case LHCb::Track::Types::Velo: + histo = m_histo_vt; + pScale = m_pScale_vt; + vScale = m_vScale_vt; + break; + case LHCb::Track::Types::Ttrack: + histo = m_histo_tt; + pScale = m_pScale_tt; + vScale = m_vScale_tt; + break; + default: + Error ("Injvald track type, return 0").ignore(); + return 0; + } + + if ( 0 == histo ) + { + Error ("Histogram is not specified return 0").ignore(); + return 0; + } + + const double _x = ::tanh(p / pScale); + const double _y = ::tanh(v / vScale); + const int ii = const_cast<TH2D *>(histo)->FindBin(_x, _y); + return histo->GetBinContent(ii); +} + +// ============================================================================ +#endif // CALOFUTUREID2DLL_H +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFuturePhotonIdAlg.cpp b/CaloFuture/CaloFuturePIDs/src/CaloFuturePhotonIdAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..15374f48eac51c2a523750bdc0588b4444da122e --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFuturePhotonIdAlg.cpp @@ -0,0 +1,407 @@ +// Include files +#include "CaloFuturePhotonIdAlg.h" +#include "DetDesc/HistoParam.h" +#include <GaudiUtils/Aida2ROOT.h> +#include <math.h> + +//------------------------------------------------------------------------------ +// Implementation file for class : CaloFuturePhotonIdAlg +// +// 2010-02-27 : Olivier Deschamps +//------------------------------------------------------------------------------ + +DECLARE_COMPONENT( CaloFuturePhotonIdAlg ) + +//============================================================================== +// Standard constructor, initializes variables +//============================================================================== + +CaloFuturePhotonIdAlg::CaloFuturePhotonIdAlg(const std::string &name, + ISvcLocator *pSvcLocator) + : MergingTransformer(name, pSvcLocator, {"Inputs", {}}, {"Output", {}}) { + // TODO : split PID estimator (Prs-Spd-Ecal(Chi2, seed/cluster) + add + // estimator ( E4/E9, Hcal/Ecal, shower-shape, ...) + // and let NeutralProtoParticle to combine ... +} + +//============================================================================== +// Initialization +//============================================================================== +StatusCode CaloFuturePhotonIdAlg::initialize() { + StatusCode sc = MergingTransformer::initialize(); + if (sc.isFailure()) + return sc; + if (msgLevel(MSG::DEBUG)) + debug() << "==> Initialize" << endmsg; + + // Retrieve tools + m_counterStat.retrieve(); + sc = m_estimator.retrieve(); + if (sc.isFailure()) + return sc; + + // Report + if (m_dlnL) { + info() << "PhotonId : Delta Log Likelihood calculation." << endmsg; + } else { + info() << "PhotonId : Likelihood estimator." << endmsg; + } + // Initialize histogram access + if (m_useCondDB && !existDet<DataObject>(detSvc(), m_conditionName)) { + warning() << "Initialise: Condition '" << m_conditionName + << "' not found -- switch to reading the DLLs from THS!" + << endmsg; + m_useCondDB = false; + } + + sc = m_useCondDB ? initializeWithCondDB() : initializeWithoutCondDB(); + + // context-dependent inputs/output (if not defined via options) + using LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation; + using LHCb::CaloFutureAlgUtils::CaloFutureIdLocation; + + // Update inputs to this default if null + if (getProperty("Inputs").toString() == "[ ]"){ + std::string loc; + if (m_type == "MergedID") { + loc = "MergedPi0s"; + } else if (m_type == "PhotonID") { + loc = "Photons"; + } else if (m_type == "PhotonFromMergedID") { + loc = "SplitPhotons"; + } + std::vector<std::string> inputs = {CaloFutureHypoLocation(loc, context())}; + Gaudi::Functional::updateHandleLocations(*this, "Inputs", inputs); + } + // Update output to this default if null + if (getProperty("Output").toString() == ""){ + std::string output = CaloFutureIdLocation(m_type, context()); + Gaudi::Functional::updateHandleLocation(*this, "Output", output); + } + + + // Warning : the algorithm settings overwrite the caloHypo2CaloFuture default + // settings + std::string seed = m_seed ? "true" : "false"; + std::string line = m_extrapol ? "true" : "false"; + std::string neig = m_neig ? "true" : "false"; + m_estimator->hypo2CaloFuture()->_setProperty("Seed", seed).ignore(); + m_estimator->hypo2CaloFuture()->_setProperty("PhotonLine", line).ignore(); + m_estimator->hypo2CaloFuture()->_setProperty("AddNeighbors", neig).ignore(); + m_estimator->_setProperty("SkipNeutralID", "true").ignore(); // avoid loop + + return sc; +} + +//============================================================================== + +Table CaloFuturePhotonIdAlg::operator()(const HyposList &hyposlist) const { + +// StatusCode CaloFuturePhotonIdAlg::execute() { + if (msgLevel(MSG::DEBUG)) + debug() << "==> Execute" << endmsg; + + // create the table + auto table = Table(200); + + // fill the table + for (const auto hypos : hyposlist) { + // Skip if null + if (!hypos) { + if (m_counterStat->isQuiet()) + counter("Empty location ") += 1; + continue; + } + // Retrieve location on TES + const auto loc = hypos->registry()->identifier(); + if (m_counterStat->isVerbose()) + counter("#Hypos in " + loc) += hypos->size(); + + // Loop over hypos + for (const auto hypo : *hypos){ + if (hypo == nullptr) { + if (m_counterStat->isQuiet()) + counter("hypo points to NULL in " + loc) += 1; + continue; + } + const double l = m_isRunnable ? likelihood(hypo) : -999.; + if (m_counterStat->isVerbose()) + counter("likelihood") += l; + table.i_push(hypo, (float)(l)); + } + } + table.i_sort(); + + // statistics + if (m_counterStat->isQuiet()){ + const auto inputs = getProperty("Inputs").toString(); + const auto output = getProperty("Output").toString(); + counter(inputs + " ==> " + output) += table.i_relations().size(); + } + + return table; +} + +//============================================================================== + +double CaloFuturePhotonIdAlg::likelihood(const LHCb::CaloHypo *hypo) const { + // Get the relevant information - basic checks + if (0 == hypo) { + Warning("CaloHypo points to NULL", StatusCode::SUCCESS).ignore(); + if (m_counterStat->isQuiet()) + counter("Null hypo") += 1; + return -999.; + } + + double energy, et, eSeed, ePrs; + int nSpd; + unsigned int area; + + double chi2 = -999.; + + // parameter evaluation + if (evalParam(hypo, energy, et, eSeed, nSpd, ePrs, area).isFailure()) + return -999.; + + // get chi2 + chi2 = -999.; + if (m_tracking) + chi2 = m_estimator->data(hypo, CaloFutureDataType::ClusterMatch, +999.); + // evaluate + return evalLikelihood(energy, et, eSeed, nSpd, ePrs, chi2, area); +} + +//============================================================================== + +StatusCode CaloFuturePhotonIdAlg::evalParam(const LHCb::CaloHypo *hypo, + double &energy, double &et, double &eSeed, + int &nSpd, double &ePrs, + unsigned int &area) const { + using namespace CaloFutureDataType; + energy = m_estimator->data(hypo, HypoE); + et = m_estimator->data(hypo, HypoEt); + eSeed = m_estimator->data(hypo, E1Hypo); + nSpd = (int)m_estimator->data(hypo, ToSpdM); + ePrs = m_estimator->data(hypo, ToPrsE); + area = LHCb::CaloCellID( + (LHCb::CaloCellID::ContentType)m_estimator->data(hypo, CellID)) + .area(); + if (!m_estimator->status()) + return StatusCode::FAILURE; + return StatusCode::SUCCESS; +} + +//============================================================================== + +double CaloFuturePhotonIdAlg::evalLikelihood(double energy, double et, double eSeed, + int nSpd, double ePrs, double chi2, + unsigned int area) const { + // Initialization + double estimator; + double signal, backgr; + const double epsilon = 1.e-20; + // SPD Hit + + signal = epsilon; + backgr = epsilon; + + if (nSpd == 0) { + signal = CaloFuturePhotonIdAlg::dLL(energy, ePrs, chi2, eSeed, + CaloFuturePhotonIdAlg::SIGNAL, area); + if (m_isRunnable) { + backgr = CaloFuturePhotonIdAlg::dLL(energy, ePrs, chi2, eSeed, + CaloFuturePhotonIdAlg::BACKGROUND, area); + } + } else { + signal = CaloFuturePhotonIdAlg::dLL(energy, ePrs, chi2, eSeed, + CaloFuturePhotonIdAlg::SIGNAL_SPD, area); + if (m_isRunnable) { + backgr = CaloFuturePhotonIdAlg::dLL(energy, ePrs, chi2, eSeed, + CaloFuturePhotonIdAlg::BACKGROUND_SPD, area); + } + } + + if (m_dlnL) { + if (m_isRunnable) { + if (signal < epsilon) + signal = epsilon; + if (backgr < epsilon) + backgr = epsilon; + estimator = log(signal) - log(backgr); + } else + estimator = -999.; + } else { + if (m_isRunnable) { + estimator = (signal + backgr > 0.) ? signal / (signal + backgr) : -1.; + } else { + estimator = -999.; + } + } + + if (msgLevel(MSG::DEBUG)) { + debug() << "Photon Candidate :" << endmsg; + debug() << " -E =" << energy << endmsg; + debug() << " -Et =" << et << endmsg; + debug() << " -#Spd hits =" << nSpd << endmsg; + debug() << " -EPrs =" << ePrs << endmsg; + debug() << " -Chi2 =" << chi2 << endmsg; + debug() << " -ESeed =" << eSeed << endmsg; + if (m_dlnL) + debug() << " => DlnL = " << estimator << endmsg; + else + debug() << " => estimator= " << estimator << endmsg; + } + + return estimator; +} + +//============================================================================== + +StatusCode CaloFuturePhotonIdAlg::initializeWithCondDB() { + info() << "init with CondDB, m_conditionName = " << m_conditionName.value() << endmsg; + try { + registerCondition(m_conditionName, m_cond, &CaloFuturePhotonIdAlg::i_updateDLL); + } catch (GaudiException &e) { + fatal() << e << endmsg; + m_isRunnable = false; + return StatusCode::FAILURE; + } + StatusCode sc = runUpdate(); // load the conditions + return sc; +} + +//============================================================================== + +StatusCode CaloFuturePhotonIdAlg::initializeWithoutCondDB() { + info() << "init w/o CondDB, pdf histos path is " << m_histo_path << endmsg; + + m_Sig_EPrs_10 = locateHistoOnDisk(m_title_Sig_EPrs_10); + m_Sig_EPrs_11 = locateHistoOnDisk(m_title_Sig_EPrs_11); + m_Sig_EPrs_12 = locateHistoOnDisk(m_title_Sig_EPrs_12); + m_Sig_EPrs_15 = locateHistoOnDisk(m_title_Sig_EPrs_15); + m_Sig_EPrs_16 = locateHistoOnDisk(m_title_Sig_EPrs_16); + m_Sig_EPrs_17 = locateHistoOnDisk(m_title_Sig_EPrs_17); + + m_Sig_Chi2_20 = locateHistoOnDisk(m_title_Sig_Chi2_20); + m_Sig_Chi2_21 = locateHistoOnDisk(m_title_Sig_Chi2_21); + m_Sig_Chi2_22 = locateHistoOnDisk(m_title_Sig_Chi2_22); + m_Sig_Chi2_25 = locateHistoOnDisk(m_title_Sig_Chi2_25); + m_Sig_Chi2_26 = locateHistoOnDisk(m_title_Sig_Chi2_26); + m_Sig_Chi2_27 = locateHistoOnDisk(m_title_Sig_Chi2_27); + + m_Sig_Seed_30 = locateHistoOnDisk(m_title_Sig_Seed_30); + m_Sig_Seed_31 = locateHistoOnDisk(m_title_Sig_Seed_31); + m_Sig_Seed_32 = locateHistoOnDisk(m_title_Sig_Seed_32); + m_Sig_Seed_35 = locateHistoOnDisk(m_title_Sig_Seed_35); + m_Sig_Seed_36 = locateHistoOnDisk(m_title_Sig_Seed_36); + m_Sig_Seed_37 = locateHistoOnDisk(m_title_Sig_Seed_37); + + m_Bkg_EPrs_110 = locateHistoOnDisk(m_title_Bkg_EPrs_110); + m_Bkg_EPrs_111 = locateHistoOnDisk(m_title_Bkg_EPrs_111); + m_Bkg_EPrs_112 = locateHistoOnDisk(m_title_Bkg_EPrs_112); + m_Bkg_EPrs_115 = locateHistoOnDisk(m_title_Bkg_EPrs_115); + m_Bkg_EPrs_116 = locateHistoOnDisk(m_title_Bkg_EPrs_116); + m_Bkg_EPrs_117 = locateHistoOnDisk(m_title_Bkg_EPrs_117); + + m_Bkg_Chi2_120 = locateHistoOnDisk(m_title_Bkg_Chi2_120); + m_Bkg_Chi2_121 = locateHistoOnDisk(m_title_Bkg_Chi2_121); + m_Bkg_Chi2_122 = locateHistoOnDisk(m_title_Bkg_Chi2_122); + m_Bkg_Chi2_125 = locateHistoOnDisk(m_title_Bkg_Chi2_125); + m_Bkg_Chi2_126 = locateHistoOnDisk(m_title_Bkg_Chi2_126); + m_Bkg_Chi2_127 = locateHistoOnDisk(m_title_Bkg_Chi2_127); + + m_Bkg_Seed_130 = locateHistoOnDisk(m_title_Bkg_Seed_130); + m_Bkg_Seed_131 = locateHistoOnDisk(m_title_Bkg_Seed_131); + m_Bkg_Seed_132 = locateHistoOnDisk(m_title_Bkg_Seed_132); + m_Bkg_Seed_135 = locateHistoOnDisk(m_title_Bkg_Seed_135); + m_Bkg_Seed_136 = locateHistoOnDisk(m_title_Bkg_Seed_136); + m_Bkg_Seed_137 = locateHistoOnDisk(m_title_Bkg_Seed_137); + + return StatusCode::SUCCESS; +} + +//============================================================================== + +StatusCode CaloFuturePhotonIdAlg::i_updateDLL() { + if (msgLevel(MSG::DEBUG)) + debug() << "i_updateDLL() called" << endmsg; + if (!m_cond) + return StatusCode::FAILURE; + + try { + m_Sig_EPrs_10 = locateHistoOnDB(m_title_Sig_EPrs_10); + m_Sig_EPrs_11 = locateHistoOnDB(m_title_Sig_EPrs_11); + m_Sig_EPrs_12 = locateHistoOnDB(m_title_Sig_EPrs_12); + m_Sig_EPrs_15 = locateHistoOnDB(m_title_Sig_EPrs_15); + m_Sig_EPrs_16 = locateHistoOnDB(m_title_Sig_EPrs_16); + m_Sig_EPrs_17 = locateHistoOnDB(m_title_Sig_EPrs_17); + + m_Sig_Chi2_20 = locateHistoOnDB(m_title_Sig_Chi2_20); + m_Sig_Chi2_21 = locateHistoOnDB(m_title_Sig_Chi2_21); + m_Sig_Chi2_22 = locateHistoOnDB(m_title_Sig_Chi2_22); + m_Sig_Chi2_25 = locateHistoOnDB(m_title_Sig_Chi2_25); + m_Sig_Chi2_26 = locateHistoOnDB(m_title_Sig_Chi2_26); + m_Sig_Chi2_27 = locateHistoOnDB(m_title_Sig_Chi2_27); + + m_Sig_Seed_30 = locateHistoOnDB(m_title_Sig_Seed_30); + m_Sig_Seed_31 = locateHistoOnDB(m_title_Sig_Seed_31); + m_Sig_Seed_32 = locateHistoOnDB(m_title_Sig_Seed_32); + m_Sig_Seed_35 = locateHistoOnDB(m_title_Sig_Seed_35); + m_Sig_Seed_36 = locateHistoOnDB(m_title_Sig_Seed_36); + m_Sig_Seed_37 = locateHistoOnDB(m_title_Sig_Seed_37); + + m_Bkg_EPrs_110 = locateHistoOnDB(m_title_Bkg_EPrs_110); + m_Bkg_EPrs_111 = locateHistoOnDB(m_title_Bkg_EPrs_111); + m_Bkg_EPrs_112 = locateHistoOnDB(m_title_Bkg_EPrs_112); + m_Bkg_EPrs_115 = locateHistoOnDB(m_title_Bkg_EPrs_115); + m_Bkg_EPrs_116 = locateHistoOnDB(m_title_Bkg_EPrs_116); + m_Bkg_EPrs_117 = locateHistoOnDB(m_title_Bkg_EPrs_117); + + m_Bkg_Chi2_120 = locateHistoOnDB(m_title_Bkg_Chi2_120); + m_Bkg_Chi2_121 = locateHistoOnDB(m_title_Bkg_Chi2_121); + m_Bkg_Chi2_122 = locateHistoOnDB(m_title_Bkg_Chi2_122); + m_Bkg_Chi2_125 = locateHistoOnDB(m_title_Bkg_Chi2_125); + m_Bkg_Chi2_126 = locateHistoOnDB(m_title_Bkg_Chi2_126); + m_Bkg_Chi2_127 = locateHistoOnDB(m_title_Bkg_Chi2_127); + + m_Bkg_Seed_130 = locateHistoOnDB(m_title_Bkg_Seed_130); + m_Bkg_Seed_131 = locateHistoOnDB(m_title_Bkg_Seed_131); + m_Bkg_Seed_132 = locateHistoOnDB(m_title_Bkg_Seed_132); + m_Bkg_Seed_135 = locateHistoOnDB(m_title_Bkg_Seed_135); + m_Bkg_Seed_136 = locateHistoOnDB(m_title_Bkg_Seed_136); + m_Bkg_Seed_137 = locateHistoOnDB(m_title_Bkg_Seed_137); + } catch (GaudiException &exc) { + fatal() << "DLL update failed! msg ='" << exc << "'" << endmsg; + return StatusCode::FAILURE; + } + return StatusCode::SUCCESS; +} + +//============================================================================== + +TH2D *CaloFuturePhotonIdAlg::locateHistoOnDisk(std::string histoname) const { + TH2D *histo = nullptr; + if (!histoname.empty()) { + AIDA::IHistogram2D *aida = + get<AIDA::IHistogram2D>(histoSvc(), m_histo_path + histoname); + if (aida == nullptr) { + warning() << "Could not find AIDA::IHistogram2D* " + << m_histo_path + histoname << "." << endmsg; + m_isRunnable = false; + return nullptr; + } + histo = Gaudi::Utils::Aida2ROOT::aida2root(aida); + } + return histo; +} + +//============================================================================== + +TH2D *CaloFuturePhotonIdAlg::locateHistoOnDB(std::string histoname) const { + TH2D *histo = nullptr; + if (!histoname.empty()) { + histo = reinterpret_cast<TH2D *>( + &m_cond->param<DetDesc::Params::Histo2D>(histoname)); + } + return histo; +} diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFuturePhotonIdAlg.h b/CaloFuture/CaloFuturePIDs/src/CaloFuturePhotonIdAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..7a36b8ab4ff89d0b1cc398449b47b5290073a4f6 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFuturePhotonIdAlg.h @@ -0,0 +1,327 @@ +#ifndef CALOFUTUREPHOTONIDALG_H +#define CALOFUTUREPHOTONIDALG_H 1 + +// Include files +#include "AIDA/IHistogram2D.h" +#include "CaloFutureInterfaces/ICaloFutureHypoEstimator.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" +#include "CaloFutureUtils/CaloFuture2Track.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "CaloFutureUtils/ClusterFunctors.h" +#include "DetDesc/Condition.h" +#include "GaudiAlg/MergingTransformer.h" +#include "Relations/IRelationWeighted.h" +#include "Relations/Relation1D.h" +#include "TH2D.h" +#include "boost/static_assert.hpp" +#include <GaudiUtils/Aida2ROOT.h> + +// ============================================================================= +/** @class CaloFuturePhotonIdAlg CaloFuturePhotonIdAlg.h + * @author Olivier Deschamps + * @date 2010-02-27 + */ + +using Hypos = LHCb::CaloHypos; +using HyposList = Gaudi::Functional::vector_of_const_<Hypos*>; +using Table = LHCb::Relation1D<LHCb::CaloHypo, float>; + +class CaloFuturePhotonIdAlg final + : public Gaudi::Functional::MergingTransformer<Table(const HyposList &)> { +public: + static_assert(std::is_base_of<LHCb::CaloFuture2Track::IHypoEvalTable, Table>::value, + "Table must inherit from IHypoEvalTable"); + + enum TYPE { SIGNAL, BACKGROUND, SIGNAL_SPD, BACKGROUND_SPD }; + + /// Standard constructor + CaloFuturePhotonIdAlg(const std::string &name, ISvcLocator *pSvcLocator); + + /// C++11 non-copyable idiom + CaloFuturePhotonIdAlg() = delete; + CaloFuturePhotonIdAlg(const CaloFuturePhotonIdAlg &) = delete; + CaloFuturePhotonIdAlg &operator=(const CaloFuturePhotonIdAlg &) = delete; + + StatusCode initialize() override; + Table operator()(const HyposList &hyposlist) const override; + + /// callback function invoked by the UpdateManagerSvc + StatusCode i_updateDLL(); + +protected: + StatusCode initializeWithCondDB(); + StatusCode initializeWithoutCondDB(); + +private: + double likelihood(const LHCb::CaloHypo *hypo) const; + + inline double dLL(const double, const double, const double, const double, + const CaloFuturePhotonIdAlg::TYPE, const int) const; + + StatusCode evalParam(const LHCb::CaloHypo *, double &, double &, double &, + int &, double &, unsigned int &) const; + + double evalLikelihood(double, double, double, int, double, double, + unsigned int) const; + + TH2D *locateHistoOnDisk(std::string) const; + TH2D *locateHistoOnDB(std::string) const; + +private: + + ToolHandle<IFutureCounterLevel> m_counterStat {"FutureCounterLevel"}; + + mutable ToolHandle<ICaloFutureHypoEstimator> m_estimator + {"CaloFutureHypoEstimator/CaloFutureHypoEstimator", this}; + + bool m_extrapol = true; + bool m_seed = false; + bool m_neig = false; + mutable bool m_isRunnable = true; + + Condition * m_cond = nullptr; + + Gaudi::Property<std::string> m_type {this, "Type", "PhotonID"}; + + Gaudi::Property<bool> m_tracking {this, "Tracking", true}; + Gaudi::Property<bool> m_pdfEPrs {this, "PdfEPrs" , true}; + Gaudi::Property<bool> m_pdfChi2 {this, "PdfChi2" , true}; + Gaudi::Property<bool> m_pdfSeed {this, "PdfSeed" , true}; + Gaudi::Property<bool> m_dlnL {this, "DlnL" , true}; + + + // Condition dbase + Gaudi::Property<bool> m_useCondDB + {this, "UseCondDB", true, + "if true - use CondDB, otherwise get the DLLs via THS from a root file"}; + + Gaudi::Property<std::string> m_conditionName + {this, "ConditionName", "Conditions/ParticleID/Calo/PhotonID"}; + + std::string m_histo_path = "CaloFutureNeutralPIDs/PhotonID/"; + + // Photon Pdf + + std::string m_title_Sig_EPrs_10 = "Signal_Prs_noSpdHit_10"; + std::string m_title_Sig_EPrs_11 = "Signal_Prs_noSpdHit_11"; + std::string m_title_Sig_EPrs_12 = "Signal_Prs_noSpdHit_12"; + std::string m_title_Sig_EPrs_15 = "Signal_Prs_SpdHit_15"; + std::string m_title_Sig_EPrs_16 = "Signal_Prs_SpdHit_16"; + std::string m_title_Sig_EPrs_17 = "Signal_Prs_SpdHit_17"; + + std::string m_title_Sig_Chi2_20 = "Signal_Chi2Tk_noSpdHit_20"; + std::string m_title_Sig_Chi2_21 = "Signal_Chi2Tk_noSpdHit_21"; + std::string m_title_Sig_Chi2_22 = "Signal_Chi2Tk_noSpdHit_22"; + std::string m_title_Sig_Chi2_25 = "Signal_Chi2Tk_SpdHit_25"; + std::string m_title_Sig_Chi2_26 = "Signal_Chi2Tk_SpdHit_26"; + std::string m_title_Sig_Chi2_27 = "Signal_Chi2Tk_SpdHit_27"; + + std::string m_title_Sig_Seed_30 = "Signal_ESeed_noSpdHit_30"; + std::string m_title_Sig_Seed_31 = "Signal_ESeed_noSpdHit_31"; + std::string m_title_Sig_Seed_32 = "Signal_ESeed_noSpdHit_32"; + std::string m_title_Sig_Seed_35 = "Signal_ESeed_SpdHit_35"; + std::string m_title_Sig_Seed_36 = "Signal_ESeed_SpdHit_36"; + std::string m_title_Sig_Seed_37 = "Signal_ESeed_SpdHit_37"; + + std::string m_title_Bkg_EPrs_110 = "Background_Prs_noSpdHit_110"; + std::string m_title_Bkg_EPrs_111 = "Background_Prs_noSpdHit_111"; + std::string m_title_Bkg_EPrs_112 = "Background_Prs_noSpdHit_112"; + std::string m_title_Bkg_EPrs_115 = "Background_Prs_SpdHit_115"; + std::string m_title_Bkg_EPrs_116 = "Background_Prs_SpdHit_116"; + std::string m_title_Bkg_EPrs_117 = "Background_Prs_SpdHit_117"; + + std::string m_title_Bkg_Chi2_120 = "Background_Chi2Tk_noSpdHit_120"; + std::string m_title_Bkg_Chi2_121 = "Background_Chi2Tk_noSpdHit_121"; + std::string m_title_Bkg_Chi2_122 = "Background_Chi2Tk_noSpdHit_122"; + std::string m_title_Bkg_Chi2_125 = "Background_Chi2Tk_SpdHit_125"; + std::string m_title_Bkg_Chi2_126 = "Background_Chi2Tk_SpdHit_126"; + std::string m_title_Bkg_Chi2_127 = "Background_Chi2Tk_SpdHit_127"; + + std::string m_title_Bkg_Seed_130 = "Background_ESeed_noSpdHit_130"; + std::string m_title_Bkg_Seed_131 = "Background_ESeed_noSpdHit_131"; + std::string m_title_Bkg_Seed_132 = "Background_ESeed_noSpdHit_132"; + std::string m_title_Bkg_Seed_135 = "Background_ESeed_SpdHit_135"; + std::string m_title_Bkg_Seed_136 = "Background_ESeed_SpdHit_136"; + std::string m_title_Bkg_Seed_137 = "Background_ESeed_SpdHit_137"; + + const TH2D *m_Sig_EPrs_10 = nullptr; + const TH2D *m_Sig_EPrs_11 = nullptr; + const TH2D *m_Sig_EPrs_12 = nullptr; + const TH2D *m_Sig_EPrs_15 = nullptr; + const TH2D *m_Sig_EPrs_16 = nullptr; + const TH2D *m_Sig_EPrs_17 = nullptr; + + const TH2D *m_Sig_Chi2_20 = nullptr; + const TH2D *m_Sig_Chi2_21 = nullptr; + const TH2D *m_Sig_Chi2_22 = nullptr; + const TH2D *m_Sig_Chi2_25 = nullptr; + const TH2D *m_Sig_Chi2_26 = nullptr; + const TH2D *m_Sig_Chi2_27 = nullptr; + + const TH2D *m_Sig_Seed_30 = nullptr; + const TH2D *m_Sig_Seed_31 = nullptr; + const TH2D *m_Sig_Seed_32 = nullptr; + const TH2D *m_Sig_Seed_35 = nullptr; + const TH2D *m_Sig_Seed_36 = nullptr; + const TH2D *m_Sig_Seed_37 = nullptr; + + const TH2D *m_Bkg_EPrs_110 = nullptr; + const TH2D *m_Bkg_EPrs_111 = nullptr; + const TH2D *m_Bkg_EPrs_112 = nullptr; + const TH2D *m_Bkg_EPrs_115 = nullptr; + const TH2D *m_Bkg_EPrs_116 = nullptr; + const TH2D *m_Bkg_EPrs_117 = nullptr; + + const TH2D *m_Bkg_Chi2_120 = nullptr; + const TH2D *m_Bkg_Chi2_121 = nullptr; + const TH2D *m_Bkg_Chi2_122 = nullptr; + const TH2D *m_Bkg_Chi2_125 = nullptr; + const TH2D *m_Bkg_Chi2_126 = nullptr; + const TH2D *m_Bkg_Chi2_127 = nullptr; + + const TH2D *m_Bkg_Seed_130 = nullptr; + const TH2D *m_Bkg_Seed_131 = nullptr; + const TH2D *m_Bkg_Seed_132 = nullptr; + const TH2D *m_Bkg_Seed_135 = nullptr; + const TH2D *m_Bkg_Seed_136 = nullptr; + const TH2D *m_Bkg_Seed_137 = nullptr; +}; + +// ============================================================================ + +inline double CaloFuturePhotonIdAlg::dLL(const double energy, const double eprs, + const double chi2, const double seed, + const CaloFuturePhotonIdAlg::TYPE type, + const int area) const { + const TH2D *histo_eprs = nullptr; + const TH2D *histo_chi2 = nullptr; + const TH2D *histo_seed = nullptr; + + const double epsilon = 1.e-20; + + switch (area) { + case 0: + switch (type) { + case SIGNAL: + histo_eprs = m_Sig_EPrs_10; + histo_chi2 = m_Sig_Chi2_20; + histo_seed = m_Sig_Seed_30; + break; + case SIGNAL_SPD: + histo_eprs = m_Sig_EPrs_15; + histo_chi2 = m_Sig_Chi2_25; + histo_seed = m_Sig_Seed_35; + break; + case BACKGROUND: + histo_eprs = m_Bkg_EPrs_110; + histo_chi2 = m_Bkg_Chi2_120; + histo_seed = m_Bkg_Seed_130; + break; + case BACKGROUND_SPD: + histo_eprs = m_Bkg_EPrs_115; + histo_chi2 = m_Bkg_Chi2_125; + histo_seed = m_Bkg_Seed_135; + break; + default: + Error("Invalid cluster type").ignore(); + return epsilon; + } + break; + case 1: + switch (type) { + case SIGNAL: + histo_eprs = m_Sig_EPrs_11; + histo_chi2 = m_Sig_Chi2_21; + histo_seed = m_Sig_Seed_31; + break; + case SIGNAL_SPD: + histo_eprs = m_Sig_EPrs_16; + histo_chi2 = m_Sig_Chi2_26; + histo_seed = m_Sig_Seed_36; + break; + case BACKGROUND: + histo_eprs = m_Bkg_EPrs_111; + histo_chi2 = m_Bkg_Chi2_121; + histo_seed = m_Bkg_Seed_131; + break; + case BACKGROUND_SPD: + histo_eprs = m_Bkg_EPrs_116; + histo_chi2 = m_Bkg_Chi2_126; + histo_seed = m_Bkg_Seed_136; + break; + default: + Error("Invalid cluster type").ignore(); + return epsilon; + } + break; + case 2: + switch (type) { + case SIGNAL: + histo_eprs = m_Sig_EPrs_12; + histo_chi2 = m_Sig_Chi2_22; + histo_seed = m_Sig_Seed_32; + break; + case SIGNAL_SPD: + histo_eprs = m_Sig_EPrs_17; + histo_chi2 = m_Sig_Chi2_27; + histo_seed = m_Sig_Seed_37; + break; + case BACKGROUND: + histo_eprs = m_Bkg_EPrs_112; + histo_chi2 = m_Bkg_Chi2_122; + histo_seed = m_Bkg_Seed_132; + break; + case BACKGROUND_SPD: + histo_eprs = m_Bkg_EPrs_117; + histo_chi2 = m_Bkg_Chi2_127; + histo_seed = m_Bkg_Seed_137; + break; + default: + Error("Invalid cluster type").ignore(); + return epsilon; + } + break; + default: + Error("Invalid area").ignore(); + return epsilon; + } + + if (histo_eprs == nullptr) { + warning() << "Histogram EPrs is not found." << endmsg; + warning() << "Stop evaluating the Dll." << endmsg; + m_isRunnable = false; + return -9999.; + } + if (histo_chi2 == nullptr) { + warning() << "Histogram Chi2 is not found." << endmsg; + warning() << "Stop evaluating the Dll." << endmsg; + m_isRunnable = false; + return -9999.; + } + if (histo_seed == nullptr) { + warning() << "Histogram Seed is not found." << endmsg; + warning() << "Stop evaluating the Dll." << endmsg; + m_isRunnable = false; + return -9999.; + } + + if (energy < epsilon) + return epsilon; + double e = log(1.4 * energy) - 6.2; + if (e > 5.5) + e = 5.5; + + const int ieprs = const_cast<TH2D *>(histo_eprs)->FindBin(eprs, e); + const int ichi2 = const_cast<TH2D *>(histo_chi2)->FindBin(chi2, e); + const int iseed = const_cast<TH2D *>(histo_seed)->FindBin(seed, e); + + double tmp = + histo_eprs->GetBinContent(ieprs) * histo_seed->GetBinContent(iseed); + + if (m_tracking) + tmp *= histo_chi2->GetBinContent(ichi2); + + return tmp; +} + +#endif // CALOFUTUREPHOTONIDALG_H diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFuturePhotonMatch.cpp b/CaloFuture/CaloFuturePIDs/src/CaloFuturePhotonMatch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4f303a236a492567f0e7a9c7bef04d1a613425ed --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFuturePhotonMatch.cpp @@ -0,0 +1,166 @@ +// Include files +#include "CaloFutureInterfaces/ICaloFutureTrackMatch.h" +#include "Event/Track.h" +#include "Event/CaloPosition.h" +#include "CaloFutureTrackMatch.h" + +// ============================================================================ +/** @file + * Implementation file for class CaloFuturePhotonMatch + * @date 2006-05-29 + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + */ +// ============================================================================ + +class CaloFuturePhotonMatch final : public virtual ICaloFutureTrackMatch, + public CaloFutureTrackMatch { + public: + /// initialize the tool + StatusCode initialize() override { + StatusCode sc = CaloFutureTrackMatch::initialize(); + if (sc.isFailure()) { return sc; } + if (calo()->index() == CaloCellCode::EcalCalo) { + m_showerMaxLocation = LHCb::State::Location::ECalShowerMax; + m_showerMax = calo()->plane(CaloPlane::ShowerMax); + } else if (calo()->index() == CaloCellCode::HcalCalo) { + m_showerMaxLocation = LHCb::State::Location::MidHCal; + m_showerMax = calo()->plane(CaloPlane::Middle); + } else { + return Error("initialize: calorimeter niether Ecal nor Hcal"); + } + return StatusCode::SUCCESS; + }; + + public: + /** the main matching method + * @see ICaloFutureTrackMatch + * @param caloObj pointer to "calorimeter" object (position) + * @param trObj pointer to tracking object (track) + * @param chi2 returned value of chi2 of the matching + * @return status code for matching procedure + */ + StatusCode match(const LHCb::CaloPosition* caloObj, const LHCb::Track* trObj, + double& chi2) override; + /** The main matching method (Stl interface) + * @see ICaloFutureTrackMatch + * @param caloObj pointer to "calorimeter" object (position) + * @param trObj pointer to tracking object (track) + * @return pair of status code/chi2 for matching procedure + */ + MatchingPair operator()(const LHCb::CaloPosition* caloObj, + const LHCb::Track* trObj) override { + double chi2; + StatusCode sc = match(caloObj, trObj, chi2); + return std::make_pair(sc, chi2); + }; + /** extract the TrState which was actually used for last matching + * @attention TrState is owned by the tool itself + * The better solution could be to return the pointer + * to TrStateP + * @return pointer to the state actually used for last matching + */ + const LHCb::State* state() const override { return &_state(); }; + + CaloFuturePhotonMatch(const std::string& type, // ? + const std::string& name, const IInterface* parent) + : CaloFutureTrackMatch(type, name, parent) { + declareInterface<ICaloFutureTrackMatch>(this); + _setProperty("CalorimeterFuture", DeCalorimeterLocation::Ecal); + _setProperty("Tolerance", "15"); // 15 millimeters + }; + + private: + typedef CaloFutureTrackMatch::Match_<2> Match; + Match m_caloMatch; + Match m_trackMatch; + Gaudi::Plane3D m_showerMax; + const LHCb::CaloPosition* m_cBad = nullptr; + const LHCb::Track* m_tBad = nullptr; + LHCb::State::Location m_showerMaxLocation; +}; + +// ============================================================================ + +DECLARE_COMPONENT( CaloFuturePhotonMatch ) + +// ============================================================================ +/// the main matching method +// ============================================================================ + +StatusCode CaloFuturePhotonMatch::match(const LHCb::CaloPosition* caloObj, + const LHCb::Track* trObj, double& chi2) { + using namespace LHCb; + + chi2 = bad(); // reset chi2 + // + if (m_cBad == caloObj || m_tBad == trObj) { + return StatusCode::FAILURE; + } + // + if (caloObj == nullptr) { + return Error("match(): CaloPosition* points to NULL"); + } + + if (!use(trObj)) { + return Error("match(): track is not OK"); + } + + if (updateCaloFuturePos(m_position, caloObj)) { + // if ( m_position != caloObj ){ + // update the position + StatusCode sc = fill(*caloObj, m_caloMatch); + if (sc.isFailure()) { + m_cBad = caloObj; + m_position = nullptr; + return Warning("match(): Error from fill(2D) -- ", StatusCode::FAILURE, + 0); + } + // find the proper plane in detector + const LHCb::CaloPosition::Center& par = caloObj->center(); + const Gaudi::XYZPoint point(par(0), par(1), caloObj->z()); + if (tolerance() < m_plane.Distance(point)) { + m_plane = calo()->plane(point); + } + // keep the track of the position + m_position = caloObj; + } + + // get the correct state + const LHCb::State* st = nullptr; + { + st = CaloFutureTrackTool::state(*trObj, m_showerMaxLocation); + if (st == nullptr) { + StatusCode sc = propagate(*trObj, m_showerMax, _state()); + if (sc.isFailure()) { + m_tBad = trObj; + return Warning("match(): failure from propagate (1) ", sc); + } + _state().setLocation(m_showerMaxLocation); + // ugly, but efficient + const_cast<LHCb::Track*>(trObj)->addToStates(_state()); + st = CaloFutureTrackTool::state(*trObj, m_showerMaxLocation); + } + // check the state, propagate if needed + if (tolerance() < ::fabs(m_plane.Distance(st->position()))) { + _state() = *st; + StatusCode sc = propagate(_state(), m_plane); + if (sc.isFailure()) { + m_tBad = trObj; + return Warning("match(): failure from propagate (2) ", sc); + } + st = &_state(); + } + } + + Assert(st != nullptr, "LHCb::State* points to NULL!"); + StatusCode sc = fill(*st, m_trackMatch); + if (sc.isFailure()) { + return Warning("match(): error for fill(2D)"); + } + + // make a real evaluation + chi2 = CaloFutureTrackMatch::chi2(m_caloMatch, m_trackMatch); + return StatusCode::SUCCESS; +} + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFutureTrack2IDAlg.cpp b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrack2IDAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..64b1019344740838d4a3662e33a4343a7898cbe1 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrack2IDAlg.cpp @@ -0,0 +1,66 @@ +// Include files +#include "CaloFutureTrack2IDAlg.h" +#include <type_traits> + +// ============================================================================ + +DECLARE_COMPONENT( CaloFutureTrack2IDAlg ) + +// ============================================================================ +/// Standard protected constructor +// ============================================================================ + +CaloFutureTrack2IDAlg::CaloFutureTrack2IDAlg(const std::string &name, ISvcLocator *pSvc) + : Transformer(name, pSvc, {KeyValue{"Inputs",""},KeyValue{"Filter",""}}, KeyValue{"Output",""}) { + _setProperty("StatPrint", "false"); + // track types: + _setProperty("AcceptedType", Gaudi::Utils::toString<int>( + LHCb::Track::Types::Long, + LHCb::Track::Types::Downstream, + LHCb::Track::Types::Ttrack)); + + // context-dependent default track container + Gaudi::Functional::updateHandleLocation(*this, "Inputs", LHCb::CaloFutureAlgUtils::TrackLocations(context()).front()); +} + +// ============================================================================ +/// standard algorithm execution +// ============================================================================ +Table CaloFutureTrack2IDAlg::operator()(const LHCb::Tracks& tracks, const Filter& filter) const { + static_assert(std::is_base_of<LHCb::CaloFuture2Track::ITrEvalTable, Table>::value, "Table must inherit from ITrEvalTable"); + + Table table(100); + + // loop over all tracks + for (const auto& track : tracks) { + // use the track ? + if (!use(track)) { + continue; + } // CONTINUE + // use filter ? + const auto r = filter.relations(track); + // no positive information? skip! + if (r.empty() || !r.front().to()) { + continue; + } // CONTINUE + double value = 0; + StatusCode sc = m_tool->process(track, value); + if (sc.isFailure()) { + Warning(" Failure from the tool, skip the track!", sc).ignore(); + continue; + } + // make a relations (fast, efficient, call for i_sort is mandatory!) + table.i_push(track, value); // NB! i_push + } + // MANDATORY after i_push! // NB! i_sort + table.i_sort(); + + m_nTracks += tracks.size(); + auto links = table.i_relations(); + m_nLinks += links.size(); + //for( const auto& link : links) m_nEnergy += link.to() / Gaudi::Units::GeV; + auto c = m_nEnergy.buffer(); + for(const auto& link : links) c += link.to() / Gaudi::Units::GeV; + + return table; +} diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFutureTrack2IDAlg.h b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrack2IDAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..32be663d0ae73dfe55072e6118a24b05021e5344 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrack2IDAlg.h @@ -0,0 +1,41 @@ +#ifndef CALOFUTUREPIDS_CALOFUTURETRACK2IDALG_H +#define CALOFUTUREPIDS_CALOFUTURETRACK2IDALG_H 1 + +// Include files +#include "CaloFutureTrackAlg.h" +#include "CaloFutureInterfaces/ICaloFutureTrackIdEval.h" +#include "CaloFutureUtils/CaloFuture2Track.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "Event/Track.h" +#include "GaudiAlg/Transformer.h" +#include "GaudiKernel/Counters.h" +#include "Relations/Relation1D.h" +#include "ToVector.h" + +// ============================================================================ +/** @class CaloFutureTrack2IDAlg CaloFutureTrack2IDAlg.h + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-15 + */ + +using Table = LHCb::Relation1D<LHCb::Track,float>; +using Filter = LHCb::Relation1D<LHCb::Track,bool>; + +class CaloFutureTrack2IDAlg : public Gaudi::Functional::Transformer<Table(const LHCb::Tracks&,const Filter&),Gaudi::Functional::Traits::BaseClass_t<CaloFutureTrackAlg> > { + static_assert(std::is_base_of<LHCb::CaloFuture2Track::ITrAccTable,Filter>::value,"Filter must inherit from ITrAccTable"); + public: + CaloFutureTrack2IDAlg(const std::string& name, ISvcLocator* pSvc); + Table operator()(const LHCb::Tracks&,const Filter&) const override; + + private: + // tool to be used for evaluation + ToolHandle<ICaloFutureTrackIdEval> m_tool{this, "Tool", "<NOT DEFINED>"}; + + mutable Gaudi::Accumulators::StatCounter<> m_nTracks{this, "#total tracks"}; + mutable Gaudi::Accumulators::StatCounter<> m_nLinks {this, "#links in table"}; + mutable Gaudi::Accumulators::StatCounter<double> m_nEnergy{this, "#total energy"}; +}; + +// ============================================================================ +#endif // CALOFUTURETRACK2IDALG_H +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackAlg.cpp b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4dc3914d008e17524346128540cd5ceb472f5fe9 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackAlg.cpp @@ -0,0 +1,57 @@ +// Include files +#include "CaloFutureTrackAlg.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "Event/Track.h" + +// ============================================================================ +/** @file + * + * Implementation file for class CaloCluster2TrackAlg + * @see CaloCluster2TrackAlg + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 02/11/2001 + */ +// ============================================================================ + +CaloFutureTrackAlg::CaloFutureTrackAlg(const std::string& name, ISvcLocator* svcloc) + : GaudiAlgorithm(name, svcloc) { + // + _setProperty("CheckTracks", "true"); + std::vector<int> stat = {LHCb::Track::FitStatus::Fitted}; + if (LHCb::CaloFutureAlgUtils::hltContext(context())) + stat.push_back(LHCb::Track::FitStatus::FitStatusUnknown); + setProperty("AcceptedFitStatus", stat).ignore(); +} + +// ============================================================================= +// standard algorithm initialization +// ============================================================================= + +StatusCode CaloFutureTrackAlg::initialize() { + StatusCode sc = GaudiAlgorithm::initialize(); + if (sc.isFailure()) { + return sc; + } + // Retrieve tools + sc = counterStat.retrieve(); + if (sc.isFailure()) { + return sc; + } + // + if (propsPrint() || msgLevel(MSG::DEBUG) || m_use.check()) { + info() << m_use << endmsg; + }; + // + return StatusCode::SUCCESS; +} + +// ============================================================================= + +void CaloFutureTrackAlg::_setProperty(const std::string& p, const std::string& v) { + StatusCode sc = setProperty(p, v); + if (!sc.isSuccess()) { + warning() << " setting Property " << p << " to " << v << " FAILED" + << endmsg; + } +} diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackAlg.h b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..4c87fd5e1eb11b8a6531e99a48ed0415259eb7b6 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackAlg.h @@ -0,0 +1,86 @@ +#ifndef CALOFUTUREUTILS_CALOFUTURETrackAlg_H +#define CALOFUTUREUTILS_CALOFUTURETrackAlg_H 1 + +// Include files +#include <string> +#include "GaudiAlg/GaudiAlgorithm.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" +#include "Event/TrackUse.h" + +// ============================================================================ +/** @class CaloFutureTrackAlg CaloFutureTrackAlg.h + * + * Helper base algorithm form implementation 'track'-related algorithms + * + * It helps to select the appropriate tracks for further processing + * Track is 'selected' if it fullfills + * + * - general features + * - category + * - "algorithm" + * + * @see TrackUse + * + * @see CaloFutureAlgorithm + * @see Algorithm + * @see IAlgorithm + * + * @author Vanya BELYAEV belyaev@lapp.in2p3.fr + * @date 2004-10-26 + */ +// ============================================================================ + +class TrackUse; +class Track; + +class CaloFutureTrackAlg : public GaudiAlgorithm { + public: + /// standard algorithm initialization + StatusCode initialize() override; + + void _setProperty(const std::string& p, const std::string& v); + + /// C++11 non-copyable idiom + CaloFutureTrackAlg() = delete; + CaloFutureTrackAlg(const CaloFutureTrackAlg&) = delete; + CaloFutureTrackAlg& operator=(const CaloFutureTrackAlg&) = delete; + + protected: + /// Standard constructor + CaloFutureTrackAlg(const std::string& name, ISvcLocator* svcloc); + + virtual ~CaloFutureTrackAlg(){}; + + /// check if the track to be used @see TrackUse + inline bool use(const LHCb::Track* track) const { return m_use(track); } + /// print the short infomration about track flags + inline MsgStream& print(MsgStream& stream, const LHCb::Track* track) const; + /// print the short infomration about track flags + inline MsgStream& print(const LHCb::Track* track, + const MSG::Level level = MSG::INFO) const; + + ToolHandle<IFutureCounterLevel> counterStat{"FutureCounterLevel"}; + TrackUse m_use { *this }; +}; + +// ============================================================================ +/// print the short infomration about track flags +// ============================================================================ + +inline MsgStream& CaloFutureTrackAlg::print(MsgStream& stream, + const LHCb::Track* track) const { + return stream.isActive() ? m_use.print(stream, track) : stream; +} + +// ============================================================================ +/// print the short infomration about track flags +// ============================================================================ + +inline MsgStream& CaloFutureTrackAlg::print(const LHCb::Track* track, + const MSG::Level level) const { + return print(msgStream(level), track); +} + +// ============================================================================ +#endif // CALOFUTURETrackAlg_H +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackMatch.cpp b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackMatch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fada31a33796c692abdee2ebd7bfa39ffa64704c --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackMatch.cpp @@ -0,0 +1,97 @@ +// Include files +#include "CaloFutureTrackMatch.h" +#include "GaudiKernel/IIncidentListener.h" +#include "GaudiKernel/IIncidentSvc.h" + +// ============================================================================ +/** @file + * Implementation file for class CaloFutureTrackMatch + * + * Properties of the class: + * BadValue - bad value of the chi2, + * ConditionName - string with the path to the file containing e- and e+ X-correction condition parameters, + * AlphaPOut - track-cluster matching X-correction parameters for Outer zone of the ECAL in case (q*polarity) > 0 + * AlphaNOut - track-cluster matching X-correction parameters for Outer zone of the ECAL in case (q*polarity) < 0 + * AlphaPMid - track-cluster matching X-correction parameters for Middle zone of the ECAL in case (q*polarity) > 0 + * AlphaNMid - track-cluster matching X-correction parameters for Middle zone of the ECAL in case (q*polarity) < 0 + * AlphaPInn - track-cluster matching X-correction parameters for Inner zone of the ECAL in case (q*polarity) > 0 + * AlphaNInn - track-cluster matching X-correction parameters for Inner zone of the ECAL in case (q*polarity) < 0 + * + * @author Oleg STENYAKIN oleg.stenyakin@cern.ch + * @date 2014-03-03 + * + */ + +// ============================================================================ +/// standard constructor +// ============================================================================ + +CaloFutureTrackMatch::CaloFutureTrackMatch(const std::string& type, const std::string& name, + const IInterface* parent) + : CaloFuture::CaloFutureTrackTool(type, name, parent) { + declareInterface<IIncidentListener>(this); +} + +// ============================================================================ + +StatusCode CaloFutureTrackMatch::i_updateAlpha() { + // allow a user to disable the CondDB and reset the x-corrections with + // setProperty on the fly (if ever needed) + if ( m_conditionName.empty() ){ + if( msgLevel(MSG::DEBUG) ) + debug() << "attempt to update X-correction parameters by UpdMgrSvc while CondDB access disabled" << endmsg; + return StatusCode::SUCCESS; + } + + // safety protection against SIGSEGV + if ( !m_cond ){ fatal() << "CaloFutureTrackMatch::i_updateAlpha m_cond == 0" << endmsg; return StatusCode::FAILURE; } + try { + m_alphaPOut.value() = m_cond->paramAsDoubleVect( "alphaPOut" ); + m_alphaNOut.value() = m_cond->paramAsDoubleVect( "alphaNOut" ); + m_alphaPMid.value() = m_cond->paramAsDoubleVect( "alphaPMid" ); + m_alphaNMid.value() = m_cond->paramAsDoubleVect( "alphaNMid" ); + m_alphaPInn.value() = m_cond->paramAsDoubleVect( "alphaPInn" ); + m_alphaNInn.value() = m_cond->paramAsDoubleVect( "alphaNInn" ); + } + catch ( GaudiException &exc ){ + fatal() << "X-correction update failed! msg ='" << exc << "'" << endmsg; + return StatusCode::FAILURE; + } + if ( msgLevel(MSG::DEBUG) ) + debug() << "CondDB update of CaloFutureTrackMatch X-correction parameters with '" << m_conditionName << "':" + <<"\nalphaPOut: "<< Gaudi::Utils::toString ( m_alphaPOut.value() ) + <<" alphaNOut: " << Gaudi::Utils::toString ( m_alphaNOut.value() ) + <<"\nalphaPMid: "<< Gaudi::Utils::toString ( m_alphaPMid.value() ) + <<" alphaNMid: " << Gaudi::Utils::toString ( m_alphaNMid.value() ) + <<"\nalphaPInn: "<< Gaudi::Utils::toString ( m_alphaPInn.value() ) + <<" alphaNInn: " << Gaudi::Utils::toString ( m_alphaNInn.value() ) << endmsg; + + return StatusCode::SUCCESS; +} + +// ============================================================================= + +StatusCode CaloFutureTrackMatch::initialize(){ + StatusCode sc = CaloFuture::CaloFutureTrackTool::initialize(); + if ( sc.isFailure() ) { return sc ; } + IIncidentSvc* isvc = svc<IIncidentSvc>( "IncidentSvc" , true ) ; + isvc->addListener ( this , IncidentType::BeginEvent ) ; + + if (! existDet<DataObject>(detSvc(), m_conditionName) ){ + if( msgLevel(MSG::DEBUG) ) debug() << "Condition '" << m_conditionName << "' not found -- switch off the use of the CondDB for CaloFutureTrackMatch!" << endmsg; + m_conditionName = ""; + } + + if ( ! m_conditionName.empty() ){ + registerCondition(m_conditionName, m_cond, &CaloFutureTrackMatch::i_updateAlpha); + sc = runUpdate(); // ask UpdateManagerSvc to load the condition w/o waiting for the next BeginEvent incident + } + else + if( msgLevel(MSG::DEBUG) ) debug() << "ConditionName empty -- reading of the CaloFutureTrackMatch X-correction parameters from the CondDB has been disabled!" << endmsg; + + m_magFieldSvc = svc<ILHCbMagnetSvc>( "MagneticFieldSvc", true ) ; + + return StatusCode::SUCCESS; +} + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackMatch.h b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackMatch.h new file mode 100644 index 0000000000000000000000000000000000000000..f7a4a574d59150c2f7ec89ef8e0d5ae67ecbe2ed --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackMatch.h @@ -0,0 +1,406 @@ +#ifndef CALOFUTUREUTILS_CALOFUTURETRACKMATCH_H +#define CALOFUTUREUTILS_CALOFUTURETRACKMATCH_H 1 + +// Include files +#include "GaudiKernel/IIncidentSvc.h" +#include "GaudiKernel/IIncidentListener.h" +#include "GaudiKernel/GenericVectorTypes.h" +#include "GaudiKernel/SymmetricMatrixTypes.h" +#include "Event/CaloPosition.h" +#include "Event/State.h" +#include "CaloFutureTrackTool.h" +#include "DetDesc/Condition.h" +#include "Kernel/ILHCbMagnetSvc.h" + +// ============================================================================ +/** @class CaloFutureTrackMatch CaloFutureTrackMatch.h + * Description of the use of the track-cluster matching X-correction + * parameters for electrons and positrons. + * + * The X-correction part of the code has been designed with the kind help from + * Vanya BELYAEV and Dmitry GOLUBKOV. + * + * Common form of the X-correction between the X-position of the state + * of track and barycentre of the CaloHypo object is: + * dX = a0*p + a1 + a2/p + a3/p^2 + ... + * where p - momentum of the track in GeV/$c$, + * parameter vectors for each zone of the ECAL + * m_alphaN<Area>[3] = {a0, a1, a2, a3, ...} + * for e- MagUp and e+ MagDown: (q*polarity) < 0 + * and + * m_alphaP<Area>[3] = {a0, a1, a2, a3, ...} + * for e- MagDown and e+ MagUp: (q*polarity) > 0 + * + * By default the X-correction parameters are read from the CondDB + * path '/dd/Conditions/ParticleID/Calo/ElectronXCorrection'. + * + * In the case when the CondDB is switched off or reading + * of the X-correction parameters from the CondDB is disabled + * the X-correction is not implemented and all X-correction parameters + * are equal to zero. + * + * Usage of the X-correction parameters in Bender scripts: + * def configure ( ) : + * """ + * Job configuration + * """ + * ... + * from Configurables import CaloFutureElectronMatch + * my_tool = CaloFutureElectronMatch() + * ## disable use of the CondDB to apply correction coefficients + * ## from the Options + * my_tool.ConditionName = "" + * ## Set the X-correction parameters for the Outer zone + * ## of the ECAL in case (q*polarity) < 0 + * my_tool.AlphaNOut = [ 0.0, -18.92, 83.46, -292.4 ] + * + * For more info see talk by O. Stenyakin + * at 2014/02/20 Moscow student meeting + * https://indico.cern.ch/event/302695/ + * or + * at 2014/01/24 CaloFuture Objects meeting + * https://indico.cern.ch/event/296617/ + * + * @author Oleg STENYAKIN oleg.stenyakin@cern.ch + * @date 2014-03-03 + */ +// ============================================================================ + +class CaloFutureTrackMatch : public CaloFuture::CaloFutureTrackTool, + public virtual IIncidentListener { + public: + /// initialization + StatusCode initialize() override; + StatusCode i_updateAlpha(); + void handle(const Incident&) override { + m_position = nullptr; + m_plane = Gaudi::Plane3D(); + } + + protected: + /// Standard constructor + CaloFutureTrackMatch(const std::string& type, const std::string& name, + const IInterface* parent); + + virtual ~CaloFutureTrackMatch(){}; + + protected: + /// helper internal structure to simplify matrix calculations + template <unsigned D> + class Match_ { + public: + using Vector = ROOT::Math::SVector<double, D>; + using Matrix = ROOT::Math::SMatrix<double, D, D, ROOT::Math::MatRepSym<double, D> >; + + public: + /// constructor + Match_(const Vector& params, const Matrix& matrix) + : m_params(params), m_matrix(matrix), m_ok(true), m_inverted(false){}; + Match_() : m_params(), m_matrix(), m_ok(true), m_inverted(false){}; + + public: + inline const Vector& params() const { return m_params; } + inline const Matrix& matrix() const { return m_matrix; } + inline bool ok() const { return m_ok; } + inline bool inverted() const { return m_inverted; } + + public: + double& operator()(const unsigned int ind) { return m_params(ind); } + double& operator()(const unsigned int ind1, const unsigned int ind2) { + return m_matrix(ind1, ind2); + } + + public: + Match_& set(const Matrix& m) { + m_matrix = m; + return *this; + } + Match_& set(const Vector& v) { + m_params = v; + return *this; + } + Match_& setOK(const bool e) { + m_ok = e; + return *this; + } + Match_& setInverted(const bool i) { + m_inverted = i; + return *this; + } + + public: + // invert the matrix + bool invert() { + if (m_inverted) { + return m_ok; + } // RETURN + m_ok = m_matrix.Invert(); + if (m_ok) { + m_inverted = true; + } + return ok(); + }; + + private: + Match_(const Match_&); + Match_& operator=(const Match_&); + + private: + // the vector of parameters x,y(,e) + Vector m_params; + // the (inverse) covariance matrix of parameters + Matrix m_matrix; + // flag for errors + bool m_ok = true; + // flag to indicate that matrix is already inverted + bool m_inverted = false; + }; + + protected: + inline bool updateCaloFuturePos(const LHCb::CaloPosition* p1, + const LHCb::CaloPosition* p2) { + return (p1 != p2); + } + + template <unsigned int D> + inline double chi2(const Match_<D>& m1, const Match_<D>& m2) const { + typedef typename Match_<D>::Vector Vector; + typedef typename Match_<D>::Matrix Matrix; + + if (!m1.inverted() || !m1.ok() || !m2.inverted() || !m2.ok()) { + Warning("chi2(): invalid data are detected - return bad chi2").ignore(); + return 99999999.; + } + + // local storage to avoid the dynamic allocation + static Matrix s_cov; + // evaluate the overall covariance matrix + s_cov = m1.matrix() + m2.matrix(); + if (!s_cov.Invert()) { + Warning("chi2(): can not invert the matrix - return bad chi2").ignore(); + return 99999999.; + } + + // get the weighted and mean parameters + // Note: Cannot use `auto` here + Vector pw = m1.matrix()*m1.params() + m2.matrix()*m2.params() ; + Vector pm = s_cov * pw ; + + // evaluate chi2 + const double temp = ROOT::Math::Similarity(pm - m1.params(), m1.matrix()) + + ROOT::Math::Similarity(pm - m2.params(), m2.matrix()); + return temp; + } + + /// get 2D-infomration form CaloPosition + inline StatusCode fill(const LHCb::CaloPosition& c, Match_<2>& match) const { + const auto par = c.center(); + const auto cov = c.spread(); + match(0) = par(0); + match(1) = par(1); + match(0, 0) = cov(0, 0); + match(0, 1) = cov(0, 1); + match(1, 1) = cov(1, 1); + match.setInverted(false); + match.setOK(true); + if (!match.invert()) { + if (msgLevel(MSG::DEBUG)) { + debug() << "CaloPosition:" << c << endmsg; + } + return Warning("match(): Could not invert '2D-calo' matrix, see debug", + StatusCode::FAILURE, 0); + } + return StatusCode::SUCCESS; + }; + + // get 2D-information from State + inline StatusCode fill(const LHCb::State& s, Match_<2>& match) const { + const auto par = s.stateVector(); + const auto cov = s.covariance(); + match(0) = par(0); + match(1) = par(1); + match(0, 0) = cov(0, 0); + match(0, 1) = cov(0, 1); + match(1, 1) = cov(1, 1); + match.setInverted(false); + match.setOK(true); + if (!match.invert()) { + if (msgLevel(MSG::DEBUG)) { + debug() << "State:" << s << endmsg; + } + return Warning("match(): Could not invert 'track' matrix", + StatusCode::FAILURE); + } + return StatusCode::SUCCESS; + }; + + /// get 3D-infomration form CaloPosition + inline StatusCode fill(const LHCb::CaloPosition& c, Match_<3>& match) const { + const auto par = c.parameters(); + const auto cov = c.covariance(); + match(0) = par(LHCb::CaloPosition::Index::X); + match(1) = par(LHCb::CaloPosition::Index::Y); + match(2) = par(LHCb::CaloPosition::Index::E); + match(0, 0) = cov(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::X); + match(0, 1) = cov(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::Y); + match(0, 2) = cov(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::E); + match(1, 1) = cov(LHCb::CaloPosition::Index::Y, LHCb::CaloPosition::Index::Y); + match(1, 2) = cov(LHCb::CaloPosition::Index::Y, LHCb::CaloPosition::Index::E); + match(2, 2) = cov(LHCb::CaloPosition::Index::E, LHCb::CaloPosition::Index::E); + match.setInverted(false); + match.setOK(true); + if (!match.invert()) { + if (msgLevel(MSG::DEBUG)) { + debug() << "CaloPosition:" << c << endmsg; + } + return Warning("match(): Could not invert '3D-calo' matrix", + StatusCode::FAILURE); + } + return StatusCode::SUCCESS; + }; + + /// get 2D-infomration from CaloPosition for Bremstrahlung + inline StatusCode fillBrem(const LHCb::CaloPosition& c, + Match_<2>& match) const { + const auto par = c.parameters(); + const auto cov = c.covariance(); + match(0) = par(LHCb::CaloPosition::Index::X); + match(1) = par(LHCb::CaloPosition::Index::Y); + match(0, 0) = cov(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::X); + match(0, 1) = cov(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::Y); + match(1, 1) = cov(LHCb::CaloPosition::Index::Y, LHCb::CaloPosition::Index::Y); + match.setInverted(false); + match.setOK(true); + if (!match.invert()) { + if (msgLevel(MSG::DEBUG)) { + debug() << "CaloPosition:" << c << endmsg; + } + return Warning("match(): Could not invert '2D-calobrem' matrix", + StatusCode::FAILURE); + } + return StatusCode::SUCCESS; + }; + + // get 3D-information from State + inline StatusCode fill(const LHCb::State& s, Match_<3>& match) const { + const auto par = s.stateVector(); + const double q = 0 < par(4) ? 1. : -1.; // charge + const double mom = + ::fabs(1.0 / par(4) / Gaudi::Units::GeV); // momentum in GeV + + // find calo area corresponding to the input LHCb::State &s; + const auto cell = + calo()->Cell_(s.position()); // cell parameters (null if point is + // outside the CalorimeterFuture) + unsigned int area = 4; // initialize with some invalid area number + if (cell) // protection against tracks pointing outside the CalorimeterFuture + area = cell->cellID().area(); // 0:Outer, 1:Middle, 2:Inner + else // roughly assign the area around the beam hole to the Inner, + // everything outside CaloFuture -- to the Outer + area = (fabs(s.position().x()) < 2. * Gaudi::Units::m && + fabs(s.position().y()) < 2. * Gaudi::Units::m) + ? 2 + : 0; // |x,y| < > 2m + + const float polarity = m_magFieldSvc->isDown() ? -1 : +1; + const bool qpolarity = (q * polarity > + 0); // true : (q*polarity) > 0, false : (q*polarity) < 0 + + const std::vector<double>* alpha = nullptr; + switch (area) // symbolic names only declaread as "the private part" of + // namespace CaloFutureCellCode in CaloFutureCellCode.cpp + { + case 0 : // Outer ECAL + alpha = qpolarity ? &m_alphaPOut.value() : &m_alphaNOut.value(); + break; + case 1 : // Middle ECAL + alpha = qpolarity ? &m_alphaPMid.value() : &m_alphaNMid.value(); + break; + case 2 : // Inner ECAL + alpha = qpolarity ? &m_alphaPInn.value() : &m_alphaNInn.value(); + break; + } + Assert(alpha, + "electron track pointing to an impossible CaloFuture area outside 0..2 " + "range"); + + match(0) = par(0); + // now add the correction series dX = a0*p + a1 + a2/p + a3/p^2 + ... + if (!alpha->empty()) { + double mmm = mom; // p, 1, 1/p, 1/p^2, ... + double inv = fabs(par(4) * Gaudi::Units::GeV); // abs(1/p) in GeV + + for (const auto it: *alpha){ + match(0) += it * mmm; + mmm *= inv; // [1/p]^k, k=-1, 0, ... size(alpha)-2 + } + } + + match(1) = par(1); + match(2) = ::fabs(1.0 / par(4)); /// @todo check it! + const double f = -1.0 * q / par(4) / par(4); // d(p)/d(Q/p) + const auto cov = s.covariance(); + match(0, 0) = cov(0, 0); // (x,x) + match(0, 1) = cov(0, 1); // (x,y) + match(1, 1) = cov(1, 1); // (y,y) + match(0, 2) = f * cov(0, 4); // (x,p) + match(1, 2) = f * cov(1, 4); // (y,p) + match(2, 2) = f * cov(4, 4) * f; // (p,p) + match.setInverted(false); + match.setOK(true); + if (!match.invert()) { + if (msgLevel(MSG::DEBUG)) { + debug() << "State:" << s << endmsg; + } + return Warning("match(): Could not invert 'track' matrix", + StatusCode::FAILURE); + } + return StatusCode::SUCCESS; + }; + + protected: + inline double bad () const { return m_bad ; } + inline LHCb::State& _state () { return m_state ; } + inline const LHCb::State& _state () const { return m_state ; } + + Condition* m_cond; + Gaudi::Property<std::string> m_conditionName + {this, "ConditionName", + "/dd/Conditions/ParticleID/Calo/ElectronXCorrection", + "set this property to an empty string to disable the use of CondDB"}; + + ILHCbMagnetSvc* m_magFieldSvc; + + const LHCb::CaloPosition* m_position = nullptr; + + Gaudi::Plane3D m_plane; + +private: + LHCb::State m_state; + + Gaudi::Property<double> m_bad + {this, "BadValue", 1.e+10, "bad value for chi2"}; + + Gaudi::Property<std::vector<double>> m_alphaPOut + {this, "AlphaPOut", {}, "electron X-correction params for (q*polarity) > 0 Outer" }; + + Gaudi::Property<std::vector<double>> m_alphaNOut + {this, "AlphaNOut", {}, "electron X-correction params for (q*polarity) < 0 Outer" }; + + Gaudi::Property<std::vector<double>> m_alphaPMid + {this, "AlphaPMid", {}, "electron X-correction params for (q*polarity) > 0 Middle"}; + + Gaudi::Property<std::vector<double>> m_alphaNMid + {this, "AlphaNMid", {}, "electron X-correction params for (q*polarity) < 0 Middle"}; + + Gaudi::Property<std::vector<double>> m_alphaPInn + {this, "AlphaPInn", {}, "electron X-correction params for (q*polarity) > 0 Inner" }; + + Gaudi::Property<std::vector<double>> m_alphaNInn + {this, "AlphaNInn", {}, "electron X-correction params for (q*polarity) < 0 Inner" }; + +}; + +// ============================================================================ +#endif // CALOFUTUREUTILS_CALOFUTURETRACKMATCH_H +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackMatchAlg.cpp b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackMatchAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..63c645fe761bd411bbea9598c33b0c74fcf29b5a --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackMatchAlg.cpp @@ -0,0 +1,74 @@ +// Include files +#include "CaloFutureTrackMatchAlg.h" + +// ============================================================================ +/** @file + * Implementation file for class CaloFutureTrackMatchAlg + * @date 2006-06-16 + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + */ +// ============================================================================ +/// Standard protected constructor +// ============================================================================ + +template <typename TABLE, typename CALOFUTURETYPES> +CaloFutureTrackMatchAlg<TABLE,CALOFUTURETYPES>::CaloFutureTrackMatchAlg(const std::string& name, ISvcLocator* pSvc) + : base_type(name, pSvc, {KeyValue{"Tracks",""},KeyValue{"Calos",""},KeyValue{"Filter",""}}, KeyValue{"Output",""}) +{ + // context-dependent default track container + Gaudi::Functional::updateHandleLocation(*this, "Tracks", LHCb::CaloFutureAlgUtils::TrackLocations(context()).front()); +} + +// ============================================================================ +/// standard algorithm execution +// ============================================================================ +template <typename TABLE, typename CALOFUTURETYPES> +TABLE CaloFutureTrackMatchAlg<TABLE,CALOFUTURETYPES>::operator()(const LHCb::Tracks& tracks, const CALOFUTURETYPES& calos, const Filter& filter) const { + + LHCb::Track::ConstVector good_tracks; + good_tracks.reserve(100); + std::copy_if( tracks.begin(), tracks.end(), std::back_inserter(good_tracks), + [&](const auto& track){ + if(!this->use(track)) return false; + const auto& r = filter.relations(track); + return !r.empty() && r.front().to(); + } + ); + const size_t nTracks = good_tracks.size(); + if(0==nTracks) if(msgLevel(MSG::DEBUG)) debug() << "No good tracks have been selected" << endmsg; + + TABLE table(m_tablesize); + size_t nOverflow = 0; + + // loop over the calo objects + for(const auto& calo : calos){ + const auto caloPos = position(calo); + for(const auto& track : good_tracks){ + double chi2 = 0; + StatusCode sc = m_tool->match( caloPos, track, chi2); + if (sc.isFailure() ){ + if (msgLevel(MSG::DEBUG)) debug() << "Failure from Tool::match, skip" << endmsg; + m_nMatchFailure += 1; + continue; + } + if( m_threshold < chi2 ){++nOverflow; continue;} + table.i_push(calo,track,chi2); + } + }//calos + // MANDATORY: i_sort after i_push + table.i_sort(); // NB: i_sort + + const auto links = table.i_relations(); + m_nLinks += links.size(); + m_nTracks += nTracks; + m_nCalos += calos.size(); + m_nOverflow += nOverflow; + auto b = m_chi2.buffer(); + for(const auto& l : links) b += l.weight(); + + return table; +} + +template class CaloFutureTrackMatchAlg<LHCb::RelationWeighted2D<LHCb::CaloCluster, LHCb::Track, float>,LHCb::CaloClusters>; +template class CaloFutureTrackMatchAlg<LHCb::RelationWeighted2D<LHCb::CaloHypo, LHCb::Track, float>,LHCb::CaloHypos>; + diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackMatchAlg.h b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackMatchAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..7eb513caa5a003cf33abfd8b4b2c47c0725d88b7 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackMatchAlg.h @@ -0,0 +1,77 @@ +#ifndef CALOFUTURETRACKMATCHALG_H +#define CALOFUTURETRACKMATCHALG_H 1 + +// Include files +#include "CaloFutureTrackAlg.h" +#include "CaloFutureUtils/CaloFuture2Track.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "Event/CaloCluster.h" +#include "Event/CaloHypo.h" +#include "Event/Track.h" +#include "CaloFutureInterfaces/ICaloFutureTrackMatch.h" +#include "Relations/Relation1D.h" +#include "Relations/RelationWeighted2D.h" +#include "GaudiAlg/Transformer.h" +#include "GaudiKernel/Counters.h" +#include "ToVector.h" + +// ============================================================================ +/** @class CaloFutureTrackMatchAlg CaloFutureTrackMatchAlg.h + * + * + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-16 + */ + +using Filter = LHCb::Relation1D<LHCb::Track,bool>; + +template <typename TABLE, typename CALOFUTURETYPES> +class CaloFutureTrackMatchAlg + : public Gaudi::Functional::Transformer< + TABLE(const LHCb::Tracks&, const CALOFUTURETYPES&, const Filter&), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureTrackAlg> > +{ + static_assert(std::is_base_of<LHCb::CaloFuture2Track::ITrAccTable,Filter>::value,"Filter must inherit from ITrAccTable"); + public: + using CaloFutureTrackAlg::context; + using CaloFutureTrackAlg::msgLevel; + using CaloFutureTrackAlg::debug; + using CaloFutureTrackAlg::use; + using CaloFutureTrackAlg::getProperty; + using CaloFutureTrackAlg::_setProperty; + using base_type = Gaudi::Functional::Transformer<TABLE(const LHCb::Tracks&,const CALOFUTURETYPES&,const Filter&), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureTrackAlg> >; + using KeyValue = typename base_type::KeyValue; + + // standard constructor + CaloFutureTrackMatchAlg(const std::string& name, ISvcLocator* pSvc); + + // standard execution + TABLE operator()(const LHCb::Tracks& tracks, const CALOFUTURETYPES& calos, const Filter& filter) const override; + + + protected: + + Gaudi::Property<float> m_threshold {this, "Threshold", 10000., "threshold"}; + Gaudi::Property<int> m_tablesize {this, "TableSize", 100, "table size"}; + + // the tool for matching + // **TODO**: update tool CaloFutureTrackMatch + mutable ToolHandle<ICaloFutureTrackMatch> m_tool {this, "Tool", "<NOT DEFINED>"}; + + // a bit of statistics + mutable Gaudi::Accumulators::StatCounter<> m_nMatchFailure {this, "#match failure"}; + mutable Gaudi::Accumulators::StatCounter<> m_nLinks {this, "#links in table"}; + mutable Gaudi::Accumulators::StatCounter<> m_nTracks {this, "#good tracks"}; + mutable Gaudi::Accumulators::StatCounter<> m_nCalos {this, "#total calos"}; + mutable Gaudi::Accumulators::StatCounter<> m_nOverflow {this, "#above threshold"}; + mutable Gaudi::Accumulators::StatCounter<float> m_chi2 {this, "#chi2"}; + + private: + const LHCb::CaloPosition* position(const LHCb::CaloCluster* c) const { return &c->position();} + const LHCb::CaloPosition* position(const LHCb::CaloHypo* c) const { return c->position();} +}; + +// ============================================================================ +#endif // CALOFUTURETRACKMATCHALG_H +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackTool.cpp b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2a4e4bb692bca5cca71f8bcbf12c5d0ddba04914 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackTool.cpp @@ -0,0 +1,55 @@ +// Include files +#include "CaloFutureTrackTool.h" + +// ============================================================================ +/** @file + * Implementation file for class CaloFuture::CaloFutureTrackTool + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-28 + */ +// ============================================================================ +/// standard constructor +// ============================================================================ +CaloFuture::CaloFutureTrackTool::CaloFutureTrackTool( const std::string& type , // ? + const std::string& name , + const IInterface* parent ) + : GaudiTool ( type , name , parent ) +{ + _setProperty("CheckTracks", "false"); + declareProperty("Extrapolator", m_extrapolator); +} + +//============================================================================== +/// initialize the tool +//============================================================================== + +StatusCode CaloFuture::CaloFutureTrackTool::initialize() { + StatusCode sc = GaudiTool::initialize(); + if ( sc.isFailure() ) { return sc ; } + // + if ( propsPrint() || msgLevel ( MSG::DEBUG ) || m_use.check() ) + { info () << m_use << endmsg ; } ; + // + if ( !m_detectorName.empty() ) + { m_calo = getDet<DeCalorimeter> ( detectorName() ); } + else { Warning("empty detector name!"); } + + // Retrieve tools + sc = m_extrapolator.retrieve(); + if (sc.isFailure()) {return sc;} + sc = m_fastExtrapolator.retrieve(); + if (sc.isFailure()) {return sc;} + + return StatusCode::SUCCESS ; +} + +//============================================================================== + +void CaloFuture::CaloFutureTrackTool::_setProperty(const std::string &p, + const std::string &v) { + StatusCode sc = setProperty(p, v); + if (!sc) { + warning() << " setting Property " << p << " to " << v << " FAILED" + << endmsg; + } +} diff --git a/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackTool.h b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackTool.h new file mode 100644 index 0000000000000000000000000000000000000000..44ec7b065f5b5fec60d1909f2ea1cd7d0d068ed9 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/CaloFutureTrackTool.h @@ -0,0 +1,315 @@ +#ifndef CALOFUTUREUTILS_CALOFUTURE_CALOFUTURETRACKTOOL_H +#define CALOFUTUREUTILS_CALOFUTURE_CALOFUTURETRACKTOOL_H 1 + +// Include files +#include <vector> +#include <string> +#include <algorithm> +#include "GaudiAlg/GaudiTool.h" +#include "LHCbMath/GeomFun.h" +#include "LHCbMath/Line.h" +#include "Event/Track.h" +#include "Event/TrackFunctor.h" +#include "Event/State.h" +#include "Event/TrackUse.h" +#include "CaloFutureInterfaces/ICaloFutureTrackMatch.h" +#include "CaloFutureInterfaces/ICaloFutureDigits4Track.h" +#include "TrackInterfaces/ITrackExtrapolator.h" +#include "CaloDet/DeCalorimeter.h" + +//============================================================================== + +namespace CaloFuture +{ + /** @class CaloFuture::CaloFutureTrackTool CaloFutureTrackTool.h + * + * + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-05-28 + */ + class CaloFutureTrackTool : public GaudiTool + { + public: + using TrackTypes = std::vector<LHCb::Track::Types>; + using Line = ICaloFutureDigits4Track::Line; + + /// initialize the tool + StatusCode initialize() override; + + // Internal version. Raise warning if failure + void _setProperty(const std::string& p ,const std::string& v); + + /// the default constructor is disabled ; + CaloFutureTrackTool() = delete; + + protected: + /// standard constructor + CaloFutureTrackTool + ( const std::string& type , + const std::string& name , + const IInterface* parent ) ; + + /// protected destructor + virtual ~CaloFutureTrackTool() {} + + inline ITrackExtrapolator* extrapolator () const ; + inline ITrackExtrapolator* fastExtrapolator () const ; + + /// Propagate track to a given 3D-place + inline StatusCode propagate + ( const LHCb::Track& track , + const Gaudi::Plane3D& plane , + LHCb::State& state , + const LHCb::Tr::PID pid = LHCb::Tr::PID::Pion() ) const ; + + /// Propagate state to a given 3D-place + inline StatusCode propagate + ( LHCb::State& state , + const Gaudi::Plane3D& plane , + const LHCb::Tr::PID pid = LHCb::Tr::PID::Pion() ) const ; + + /// Propagate state to a given Z + inline StatusCode propagate + ( LHCb::State& state , + const double z , + const LHCb::Tr::PID pid = LHCb::Tr::PID::Pion() ) const ; + + /// construct the straight line from the state + inline Line line ( const LHCb::State& state ) const + { return Line ( state.position() , state.slopes () ) ; } ; + + /** get a pointer to the satte for the given track at given location + * it shodul be faster then double usage of + * LHCb::Track::hasStateAt ( location ) and LHCb::stateAt ( location ) + * In addition it scans the list of states fro the end - + * it is good for calorimeter + */ + inline const LHCb::State* state + ( const LHCb::Track& track , + const LHCb::State::Location loc ) const ; + + /** get a pointer to the satte for the given track at given location + * it shodul be faster then double usage of + * LHCb::Track::hasStateAt ( location ) and LHCb::stateAt ( location ) + * In addition it scans the list of states fro the end - + * it is good for calorimeter + */ + inline LHCb::State* state + ( LHCb::Track& track , + const LHCb::State::Location loc ) const ; + + /// check if the track to be used @see TrackUse + inline bool use ( const LHCb::Track* track ) const { return m_use( track) ; } + + /// print the short infomration about track flags + inline MsgStream& print + ( MsgStream& stream , + const LHCb::Track* track ) const ; + + /// print the short infomration about track flags + inline MsgStream& print + ( const LHCb::Track* track , + const MSG::Level level = MSG::INFO ) const ; + + double tolerance() const { return m_tolerance ; } + const std::string& detectorName() const { return m_detectorName ; } + const DeCalorimeter* calo() const { return m_calo ; } + + private: + + // extrapolator + mutable ToolHandle<ITrackExtrapolator> m_extrapolator + {"TrackRungeKuttaExtrapolator/Regular", this}; + + // fast extrapolator + mutable ToolHandle<ITrackExtrapolator> m_fastExtrapolator + {"TrackLinearExtrapolator/Linear"}; + + Gaudi::Property<float> m_fastZ + {this, "zForFastExtrapolator", + 10.0 * Gaudi::Units::meter, + "z-position of 'linear' extrapolation"}; + + Gaudi::Property<float> m_tolerance + {this, "Tolerance", + 2.0 * Gaudi::Units::mm, + "plane extrapolation tolerance"}; + + Gaudi::Property<float> m_cosTolerance + {this, "CosTolerance", + ::cos( 0.1 * Gaudi::Units::mrad ), + "plane extrapolation angular tolerance"}; + + Gaudi::Property<unsigned int> m_maxIter + {this, "MaxPlaneIterations", 5, + "maximal number of iterations"}; + + Gaudi::Property<std::string> m_detectorName + {this, "CalorimeterFuture"}; + + // detector element + const DeCalorimeter* m_calo = nullptr; + + // track selector + TrackUse m_use { *this }; + + // local storages + mutable Gaudi::XYZPoint m_pos; + mutable Gaudi::XYZVector m_mom; + }; +} + +// ============================================================================ +// get the extrapolator +// ============================================================================ + +inline ITrackExtrapolator *CaloFuture::CaloFutureTrackTool::extrapolator() const { + return m_extrapolator.get(); +} + +// ============================================================================ +// get the fast extrapolator +// ============================================================================ + +inline ITrackExtrapolator *CaloFuture::CaloFutureTrackTool::fastExtrapolator() const { + return m_fastExtrapolator.get(); +} + +// ============================================================================ +// Propagate track to a given 3D-place +// ============================================================================ + +inline StatusCode +CaloFuture::CaloFutureTrackTool::propagate +( const LHCb::Track& track , + const Gaudi::Plane3D& plane , + LHCb::State& state , + const LHCb::Tr::PID pid ) const +{ + state = track.closestState ( plane ) ; + if ( ::fabs( plane.Distance ( state.position() ) ) < tolerance() ) + { return StatusCode::SUCCESS ; } + return propagate ( state , plane , pid ) ; +} + +// ============================================================================ +// Propagate state to a given 3D-place +// ============================================================================ + +inline StatusCode +CaloFuture::CaloFutureTrackTool::propagate +( LHCb::State& state , + const Gaudi::Plane3D& plane , + const LHCb::Tr::PID pid ) const +{ + // check the plane: if it is "almost Z=const"-plane + const Gaudi::XYZVector& normal = plane.Normal() ; + if ( m_cosTolerance < ::fabs ( normal.Z() ) ) + { + // use the standard method + const double Z = -1*plane.HesseDistance()/normal.Z() ; + return propagate ( state , Z , pid ) ; + } + Gaudi::XYZPoint point ; + for ( unsigned int iter = 0 ; iter < m_maxIter ; ++iter ) + { + const double distance = ::fabs ( plane.Distance( state.position() ) ); + if ( distance <m_tolerance ) { return StatusCode::SUCCESS ; } // RETURN + double mu = 0.0 ; + if ( !Gaudi::Math::intersection ( line ( state ) , plane , point , mu ) ) + { return Warning ( "propagate: line does not cross the place" ) ; }// RETURN + StatusCode sc = propagate ( state , point.Z() , pid ) ; + if ( sc.isFailure() ) + { return Warning ( "propagate: failure from propagate" , sc ) ; } // RETURN + } + return Warning ( "propagate: no convergency has been reached" ) ; +} + +// ============================================================================ +// Propagate state to a given Z +// ============================================================================ + +inline StatusCode +CaloFuture::CaloFutureTrackTool::propagate +( LHCb::State& state , + const double z , + const LHCb::Tr::PID pid ) const +{ + if ( std::max ( state.z() , z ) < m_fastZ ) + { // use the regular extrapolator + return extrapolator () -> propagate ( state , z , pid ) ; + } + else if ( std::min ( state.z() , z ) > m_fastZ ) + { // use the fast (linear) extrapolator + return fastExtrapolator () -> propagate ( state , z , pid ) ; + } + // use the pair of extrapolators + StatusCode sc1 ; + StatusCode sc2 ; + if ( state.z () < z ) + { + sc1 = extrapolator () -> propagate ( state , m_fastZ , pid ) ; + sc2 = fastExtrapolator () -> propagate ( state , z , pid ) ; + } + else + { + sc2 = fastExtrapolator () -> propagate ( state , m_fastZ , pid ) ; + sc1 = extrapolator () -> propagate ( state , z , pid ) ; + } + + StatusCode sc = StatusCode::SUCCESS; + std::string errMsg; + if ( sc2.isFailure() ) + { + errMsg = "Error from FastExtrapolator"; + sc = sc2; + } + if ( sc1.isFailure() ) + { + errMsg = "Error from extrapolator"; + sc = sc1; + } + // + return sc.isFailure() ? Warning( errMsg, sc ) : sc; +} + +// ============================================================================ +// print the short infomration about track flags +// ============================================================================ + +inline MsgStream& +CaloFuture::CaloFutureTrackTool::print +( MsgStream& stream , + const LHCb::Track* track ) const +{ return stream.isActive() ? m_use.print ( stream , track ) : stream ; } + +// ============================================================================ +// print the short infomration about track flags +// ============================================================================ + +inline MsgStream& +CaloFuture::CaloFutureTrackTool::print +( const LHCb::Track* track , + const MSG::Level level ) const +{ return print ( msgStream ( level ) , track ) ; } + +// ============================================================================ +// get a pointer to the state for the given track at given location +// ============================================================================ + +inline const LHCb::State* +CaloFuture::CaloFutureTrackTool::state +( const LHCb::Track& track , const LHCb::State::Location loc ) const +{ + const auto& states = track.states() ; + // loop in reverse order: for calo should be a bit more efficient + auto found = std::find_if( states.rbegin(), states.rend(), + [&](const LHCb::State* s) + { return s->checkLocation(loc); } ); + // + return found != states.rend() ? *found : nullptr ; // RETURN +} + +// ============================================================================ +#endif // CALOFUTUREUTILS_CALOFUTURE_CALOFUTURETRACKTOOL_H +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/FutureClusChi22ID.cpp b/CaloFuture/CaloFuturePIDs/src/FutureClusChi22ID.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1bdea136791bd47bb8a9bd88494a829918d1c3bf --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/FutureClusChi22ID.cpp @@ -0,0 +1,29 @@ +// Include files +#include "CaloFutureChi22ID.h" +#include "ToVector.h" + +// ============================================================================ +using TABLEI = LHCb::RelationWeighted2D<LHCb::CaloCluster, LHCb::Track, float>; +using TABLEO = LHCb::Relation1D<LHCb::Track, float>; + +struct FutureClusChi22ID final: public CaloFutureChi22ID<TABLEI,TABLEO> { + static_assert( + std::is_base_of<LHCb::CaloFuture2Track::IClusTrTable2D, TABLEI>::value, + "TABLEI must inherit from IClusTrTable2D"); + + FutureClusChi22ID(const std::string& name, ISvcLocator* pSvc) + : CaloFutureChi22ID<TABLEI,TABLEO>(name, pSvc) { + using LHCb::CaloFutureAlgUtils::CaloFutureIdLocation; + Gaudi::Functional::updateHandleLocation(*this, "Input", CaloFutureIdLocation("ClusterMatch", context())); + Gaudi::Functional::updateHandleLocation(*this, "Output", CaloFutureIdLocation("ClusChi2", context())); + // @todo it must be in agrement with "Threshold" for PhotonMatchAlg + _setProperty("CutOff", "1000"); // + // track types: + _setProperty("AcceptedType", Gaudi::Utils::toString<int>( + LHCb::Track::Types::Long, LHCb::Track::Types::Ttrack, + LHCb::Track::Types::Downstream)); + }; +}; +// ============================================================================ + +DECLARE_COMPONENT( FutureClusChi22ID ) diff --git a/CaloFuture/CaloFuturePIDs/src/FutureEcalChi22ID.cpp b/CaloFuture/CaloFuturePIDs/src/FutureEcalChi22ID.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fa7a3a0f3b944287b42db0b6e458b204824bd03b --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/FutureEcalChi22ID.cpp @@ -0,0 +1,33 @@ +// Include files +#include "CaloFutureChi22ID.h" +#include "ToVector.h" + +// ============================================================================ +/** @class FutureEcalChi22ID FutureEcalChi22ID.cpp + * The preconfigured instance of class CaloFutureChi22ID + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + */ +// ============================================================================ +using TABLEI = LHCb::RelationWeighted2D<LHCb::CaloHypo, LHCb::Track, float>; +using TABLEO = LHCb::Relation1D<LHCb::Track, float>; + +struct FutureEcalChi22ID final : public CaloFutureChi22ID<TABLEI,TABLEO> { + static_assert( + std::is_base_of<LHCb::CaloFuture2Track::IHypoTrTable2D, TABLEI>::value, + "TABLEI must inherit from IHypoTrTable2D"); + FutureEcalChi22ID(const std::string& name, ISvcLocator* pSvc) + : CaloFutureChi22ID<TABLEI,TABLEO>(name, pSvc) { + using LHCb::CaloFutureAlgUtils::CaloFutureIdLocation; + Gaudi::Functional::updateHandleLocation(*this, "Input", CaloFutureIdLocation("ElectronMatch", context())); + Gaudi::Functional::updateHandleLocation(*this, "Output", CaloFutureIdLocation("EcalChi2", context())); + // @todo it must be in agrement with "Threshold" for ElectonMatchAlg + _setProperty("CutOff", "10000"); + // track types: + _setProperty("AcceptedType", Gaudi::Utils::toString<int>( + LHCb::Track::Types::Long, LHCb::Track::Types::Ttrack, + LHCb::Track::Types::Downstream)); + }; +}; + +// ============================================================================ +DECLARE_COMPONENT( FutureEcalChi22ID ) diff --git a/CaloFuture/CaloFuturePIDs/src/FutureEcalEnergyForTrack.cpp b/CaloFuture/CaloFuturePIDs/src/FutureEcalEnergyForTrack.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6acd0ea723fd18133bad0ee40bcad6caafc0a1e7 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/FutureEcalEnergyForTrack.cpp @@ -0,0 +1,27 @@ +// Include files +#include "CaloFutureEnergyForTrack.h" + +// ============================================================================ +/** @class FutureEcalEnergyForTrack + * The concrete preconfigured insatnce for CaloFutureEnergyForTrack tool + * along the track line + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + */ +// ============================================================================ + +class FutureEcalEnergyForTrack final : public CaloFutureEnergyForTrack { + public: + FutureEcalEnergyForTrack(const std::string& type, const std::string& name, + const IInterface* parent) + : CaloFutureEnergyForTrack(type, name, parent) { + setProperty("DataAddress", LHCb::CaloDigitLocation::Ecal).ignore(); + setProperty("MorePlanes", 3).ignore(); /// 3 additional planes + setProperty("AddNeigbours", 0).ignore(); + setProperty("Tolerance", 5 * Gaudi::Units::mm).ignore(); + setProperty("CalorimeterFuture", DeCalorimeterLocation::Ecal).ignore(); + } +}; + +// ============================================================================ + +DECLARE_COMPONENT( FutureEcalEnergyForTrack ) diff --git a/CaloFuture/CaloFuturePIDs/src/FutureEcalPIDeAlg.cpp b/CaloFuture/CaloFuturePIDs/src/FutureEcalPIDeAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b94b4e896e823c91b87995cddacf3b4dfdbe58d0 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/FutureEcalPIDeAlg.cpp @@ -0,0 +1,49 @@ +// Include files +#include "CaloFutureID2DLL.h" + +// ============================================================================ +/** @class FutureEcalPIDeAlg FutureEcalPIDeAlg.cpp + * The preconfigured instance of class CaloFutureID2DLL + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-18 + */ +// ============================================================================ + +class FutureEcalPIDeAlg final : public CaloFutureID2DLL { + public: + FutureEcalPIDeAlg(const std::string& name, ISvcLocator* pSvc) + : CaloFutureID2DLL(name, pSvc) { + using LHCb::CaloFutureAlgUtils::CaloFutureIdLocation; + + Gaudi::Functional::updateHandleLocation( + *this, "Input", CaloFutureIdLocation("EcalChi2", context())); + Gaudi::Functional::updateHandleLocation( + *this, "Output", CaloFutureIdLocation("EcalPIDe", context())); + + _setProperty("nVlong" , Gaudi::Utils::toString(2500)); + _setProperty("nVdown" , Gaudi::Utils::toString(2500)); + _setProperty("nVTtrack", Gaudi::Utils::toString(2500)); + _setProperty("nMlong" , Gaudi::Utils::toString(100 * Gaudi::Units::GeV)); + _setProperty("nMdown" , Gaudi::Utils::toString(100 * Gaudi::Units::GeV)); + _setProperty("nMTtrack", Gaudi::Utils::toString(100 * Gaudi::Units::GeV)); + + _setProperty("HistogramL" , "DLL_Long"); + _setProperty("HistogramD" , "DLL_Downstream"); + _setProperty("HistogramT" , "DLL_Ttrack"); + _setProperty("ConditionName", "Conditions/ParticleID/Calo/EcalPIDe"); + + _setProperty("HistogramL_THS", "CaloFuturePIDs/CALO/ECALPIDE/h3"); + _setProperty("HistogramD_THS", "CaloFuturePIDs/CALO/ECALPIDE/h5"); + _setProperty("HistogramT_THS", "CaloFuturePIDs/CALO/ECALPIDE/h6"); + + _setProperty("AcceptedType", Gaudi::Utils::toString<int>( + LHCb::Track::Types::Long, LHCb::Track::Types::Ttrack, + LHCb::Track::Types::Downstream)); + }; +}; + +// ============================================================================ + +DECLARE_COMPONENT( FutureEcalPIDeAlg ) + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/FutureEcalPIDmuAlg.cpp b/CaloFuture/CaloFuturePIDs/src/FutureEcalPIDmuAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e4dc653f990a2f67e890ea4983e5b3d773428726 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/FutureEcalPIDmuAlg.cpp @@ -0,0 +1,49 @@ +// Include files +#include "CaloFutureID2DLL.h" + +// ============================================================================ +/** @class FutureEcalPIDmuAlg FutureEcalPIDmuAlg.cpp + * The preconfigured instance of class CaloFutureID2DLL + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-18 + */ +// ============================================================================ + +class FutureEcalPIDmuAlg final : public CaloFutureID2DLL { + public: + FutureEcalPIDmuAlg(const std::string& name, ISvcLocator* pSvc) + : CaloFutureID2DLL(name, pSvc) { + using LHCb::CaloFutureAlgUtils::CaloFutureIdLocation; + + Gaudi::Functional::updateHandleLocation( + *this, "Input", CaloFutureIdLocation("EcalE", context())); + Gaudi::Functional::updateHandleLocation( + *this, "Output", CaloFutureIdLocation("EcalPIDmu", context())); + + _setProperty("nVlong" , Gaudi::Utils::toString(5 * Gaudi::Units::GeV)); + _setProperty("nVdown" , Gaudi::Utils::toString(5 * Gaudi::Units::GeV)); + _setProperty("nVTtrack", Gaudi::Utils::toString(5 * Gaudi::Units::GeV)); + _setProperty("nMlong" , Gaudi::Utils::toString(25 * Gaudi::Units::GeV)); + _setProperty("nMdown" , Gaudi::Utils::toString(25 * Gaudi::Units::GeV)); + _setProperty("nMTtrack", Gaudi::Utils::toString(25 * Gaudi::Units::GeV)); + + _setProperty("HistogramL" , "DLL_Long"); + _setProperty("HistogramD" , "DLL_Downstream"); + _setProperty("HistogramT" , "DLL_Ttrack"); + _setProperty("ConditionName", "Conditions/ParticleID/Calo/EcalPIDmu"); + + _setProperty("HistogramL_THS", "CaloFuturePIDs/CALO/ECALPIDM/h3"); + _setProperty("HistogramD_THS", "CaloFuturePIDs/CALO/ECALPIDM/h5"); + _setProperty("HistogramT_THS", "CaloFuturePIDs/CALO/ECALPIDM/h6"); + + _setProperty("AcceptedType", Gaudi::Utils::toString<int>( + LHCb::Track::Types::Long, LHCb::Track::Types::Ttrack, + LHCb::Track::Types::Downstream)); + }; +}; + +// ============================================================================ + +DECLARE_COMPONENT( FutureEcalPIDmuAlg ) + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/FutureElectronMatchAlg.cpp b/CaloFuture/CaloFuturePIDs/src/FutureElectronMatchAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2144b1608ea067f42f9c197b071dfb6ad60fd5b1 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/FutureElectronMatchAlg.cpp @@ -0,0 +1,37 @@ +// Include files +#include "CaloFutureTrackMatchAlg.h" + +// ============================================================================ +/** @class FutureElectronMatchAlg + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-16 + */ +// ============================================================================ +using TABLE = LHCb::RelationWeighted2D<LHCb::CaloHypo, LHCb::Track, float>; +using CALOFUTURETYPES = LHCb::CaloHypos; + +struct FutureElectronMatchAlg final : CaloFutureTrackMatchAlg<TABLE,CALOFUTURETYPES> { + static_assert(std::is_base_of<LHCb::CaloFuture2Track::IHypoTrTable2D, TABLE>::value, + "Table must inherit from IHypoTrTable2D"); + + FutureElectronMatchAlg(const std::string& name, ISvcLocator* pSvc) + : CaloFutureTrackMatchAlg<TABLE,CALOFUTURETYPES>(name, pSvc) { + Gaudi::Functional::updateHandleLocation(*this, "Calos", LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation("Electrons",context())); + Gaudi::Functional::updateHandleLocation(*this, "Output", LHCb::CaloFutureAlgUtils::CaloFutureIdLocation("ElectronMatch",context())); + Gaudi::Functional::updateHandleLocation(*this, "Filter", LHCb::CaloFutureAlgUtils::CaloFutureIdLocation("InEcal",context())); + + _setProperty("Tool", "CaloFutureElectronMatch/ElectronMatchFuture"); + _setProperty("Threshold", "10000"); + // track types: + _setProperty("AcceptedType", Gaudi::Utils::toString<int>( + LHCb::Track::Types::Long, LHCb::Track::Types::Downstream, + LHCb::Track::Types::Ttrack)); + _setProperty("TableSize", "1000"); + } + +}; + +// ============================================================================ + +DECLARE_COMPONENT( FutureElectronMatchAlg ) + diff --git a/CaloFuture/CaloFuturePIDs/src/FutureHcalEnergyForTrack.cpp b/CaloFuture/CaloFuturePIDs/src/FutureHcalEnergyForTrack.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1e94a9666e152c86100bce619c8395488c04e0b1 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/FutureHcalEnergyForTrack.cpp @@ -0,0 +1,27 @@ +// Include files +#include "CaloFutureEnergyForTrack.h" + +// ============================================================================ +/** @class FutureHcalEnergyForTrack + * The concrete preconfigured insatnce for CaloFutureEnergyForTrack tool + * along the track line + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + */ +// ============================================================================ + +class FutureHcalEnergyForTrack final : public CaloFutureEnergyForTrack { + public: + FutureHcalEnergyForTrack(const std::string& type, const std::string& name, + const IInterface* parent) + : CaloFutureEnergyForTrack(type, name, parent) { + setProperty("DataAddress", LHCb::CaloDigitLocation::Hcal).ignore(); + setProperty("CalorimeterFuture", DeCalorimeterLocation::Hcal).ignore(); + setProperty("MorePlanes", 5).ignore(); + setProperty("AddNeigbours", 0).ignore(); + setProperty("Tolerance", 15.0 * Gaudi::Units::mm).ignore(); + } +}; + +// ============================================================================ + +DECLARE_COMPONENT( FutureHcalEnergyForTrack ) diff --git a/CaloFuture/CaloFuturePIDs/src/FutureHcalPIDeAlg.cpp b/CaloFuture/CaloFuturePIDs/src/FutureHcalPIDeAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4484ef2371674d4df0dbc15cd457c20458649391 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/FutureHcalPIDeAlg.cpp @@ -0,0 +1,49 @@ +// Include files +#include "CaloFutureID2DLL.h" + +// ============================================================================ +/** @class FutureHcalPIDeAlg FutureHcalPIDeAlg.cpp + * The preconfigured instance of class CaloFutureID2DLL + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-18 + */ +// ============================================================================ + +class FutureHcalPIDeAlg final : public CaloFutureID2DLL { + public: + FutureHcalPIDeAlg(const std::string& name, ISvcLocator* pSvc) + : CaloFutureID2DLL(name, pSvc) { + using LHCb::CaloFutureAlgUtils::CaloFutureIdLocation; + + Gaudi::Functional::updateHandleLocation( + *this, "Input", CaloFutureIdLocation("HcalE", context())); + Gaudi::Functional::updateHandleLocation( + *this, "Output", CaloFutureIdLocation("HcalPIDe", context())); + + _setProperty("nVlong" , Gaudi::Utils::toString(5 * Gaudi::Units::GeV)); + _setProperty("nVdown" , Gaudi::Utils::toString(5 * Gaudi::Units::GeV)); + _setProperty("nVTtrack", Gaudi::Utils::toString(5 * Gaudi::Units::GeV)); + _setProperty("nMlong" , Gaudi::Utils::toString(100 * Gaudi::Units::GeV)); + _setProperty("nMdown" , Gaudi::Utils::toString(100 * Gaudi::Units::GeV)); + _setProperty("nMTtrack", Gaudi::Utils::toString(100 * Gaudi::Units::GeV)); + + _setProperty("HistogramL" , "DLL_Long"); + _setProperty("HistogramD" , "DLL_Downstream"); + _setProperty("HistogramT" , "DLL_Ttrack"); + _setProperty("ConditionName", "Conditions/ParticleID/Calo/HcalPIDe"); + + _setProperty("HistogramL_THS", "CaloFuturePIDs/CALO/HCALPIDE/h3"); + _setProperty("HistogramD_THS", "CaloFuturePIDs/CALO/HCALPIDE/h5"); + _setProperty("HistogramT_THS", "CaloFuturePIDs/CALO/HCALPIDE/h6"); + + _setProperty("AcceptedType", Gaudi::Utils::toString<int>( + LHCb::Track::Types::Long, LHCb::Track::Types::Ttrack, + LHCb::Track::Types::Downstream)); + }; +}; + +// ============================================================================ + +DECLARE_COMPONENT( FutureHcalPIDeAlg ) + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/FutureHcalPIDmuAlg.cpp b/CaloFuture/CaloFuturePIDs/src/FutureHcalPIDmuAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ec5160837fc348abe289c67e181ebe1a605cb7be --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/FutureHcalPIDmuAlg.cpp @@ -0,0 +1,49 @@ +// Include files +#include "CaloFutureID2DLL.h" + +// ============================================================================ +/** @class FutureHcalPIDmuAlg FutureHcalPIDmuAlg.cpp + * The preconfigured instance of class CaloFutureID2DLL + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-18 + */ +// ============================================================================ + +class FutureHcalPIDmuAlg final : public CaloFutureID2DLL { + public: + FutureHcalPIDmuAlg(const std::string& name, ISvcLocator* pSvc) + : CaloFutureID2DLL(name, pSvc) { + using LHCb::CaloFutureAlgUtils::CaloFutureIdLocation; + + Gaudi::Functional::updateHandleLocation( + *this, "Input", CaloFutureIdLocation("HcalE", context())); + Gaudi::Functional::updateHandleLocation( + *this, "Output", CaloFutureIdLocation("HcalPIDmu", context())); + + _setProperty("nVlong" , Gaudi::Utils::toString(10 * Gaudi::Units::GeV)); + _setProperty("nVdown" , Gaudi::Utils::toString(10 * Gaudi::Units::GeV)); + _setProperty("nVTtrack", Gaudi::Utils::toString(10 * Gaudi::Units::GeV)); + _setProperty("nMlong" , Gaudi::Utils::toString(25 * Gaudi::Units::GeV)); + _setProperty("nMdown" , Gaudi::Utils::toString(25 * Gaudi::Units::GeV)); + _setProperty("nMTtrack", Gaudi::Utils::toString(25 * Gaudi::Units::GeV)); + + _setProperty("HistogramL" , "DLL_Long"); + _setProperty("HistogramD" , "DLL_Downstream"); + _setProperty("HistogramT" , "DLL_Ttrack"); + _setProperty("ConditionName", "Conditions/ParticleID/Calo/HcalPIDmu"); + + _setProperty("HistogramL_THS", "CaloFuturePIDs/CALO/HCALPIDM/h3"); + _setProperty("HistogramD_THS", "CaloFuturePIDs/CALO/HCALPIDM/h5"); + _setProperty("HistogramT_THS", "CaloFuturePIDs/CALO/HCALPIDM/h6"); + + _setProperty("AcceptedType", Gaudi::Utils::toString<int>( + LHCb::Track::Types::Long, LHCb::Track::Types::Ttrack, + LHCb::Track::Types::Downstream)); + }; +}; + +// ============================================================================ + +DECLARE_COMPONENT( FutureHcalPIDmuAlg ) + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/FuturePhotonMatchAlg.cpp b/CaloFuture/CaloFuturePIDs/src/FuturePhotonMatchAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..615d8faa9eea5e12453f3063a1bec42101337632 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/FuturePhotonMatchAlg.cpp @@ -0,0 +1,37 @@ +// Include files +#include "CaloFutureTrackMatchAlg.h" + + +// ============================================================================ +/** @class FuturePhotonMatchAlg + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-16 + */ +// ============================================================================ +using TABLE = LHCb::RelationWeighted2D<LHCb::CaloCluster, LHCb::Track, float>; +using CALOFUTURETYPES = LHCb::CaloClusters; + +struct FuturePhotonMatchAlg final: CaloFutureTrackMatchAlg<TABLE,CALOFUTURETYPES> { + static_assert(std::is_base_of<LHCb::CaloFuture2Track::IClusTrTable2D, TABLE>::value, + "TABLE must inherit from IClusTrTable2D"); + FuturePhotonMatchAlg(const std::string& name, ISvcLocator* pSvc) + : CaloFutureTrackMatchAlg<TABLE,CALOFUTURETYPES>(name, pSvc) { + Gaudi::Functional::updateHandleLocation(*this, "Calos", LHCb::CaloFutureAlgUtils::CaloFutureClusterLocation("Ecal",context())); + Gaudi::Functional::updateHandleLocation(*this, "Output", LHCb::CaloFutureAlgUtils::CaloFutureIdLocation("ClusterMatch",context())); + Gaudi::Functional::updateHandleLocation(*this, "Filter", LHCb::CaloFutureAlgUtils::CaloFutureIdLocation("InEcal",context())); + + _setProperty("Tool", "CaloFuturePhotonMatch/FuturePhotonMatch"); + _setProperty("Threshold", "1000"); + // track types: + _setProperty("AcceptedType", Gaudi::Utils::toString<int>( + LHCb::Track::Types::Long, LHCb::Track::Types::Downstream, + LHCb::Track::Types::Ttrack)); + _setProperty("TableSize", "5000"); + } + +}; + +// ============================================================================ + +DECLARE_COMPONENT( FuturePhotonMatchAlg ) + diff --git a/CaloFuture/CaloFuturePIDs/src/FuturePrsEnergyForTrack.cpp b/CaloFuture/CaloFuturePIDs/src/FuturePrsEnergyForTrack.cpp new file mode 100644 index 0000000000000000000000000000000000000000..146865e24ad7138e04ebb4d7bd3f904a47a38e73 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/FuturePrsEnergyForTrack.cpp @@ -0,0 +1,25 @@ +// Include files +#include "CaloFutureEnergyForTrack.h" + +// ============================================================================ +/** @class FuturePrsEnergyForTrack + * The concrete preconfigured insatnce for CaloFutureEnergyForTrack tool + * along the track line + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + */ +// ============================================================================ + +class FuturePrsEnergyForTrack final : public CaloFutureEnergyForTrack { + public: + FuturePrsEnergyForTrack(const std::string& type, const std::string& name, + const IInterface* parent) + : CaloFutureEnergyForTrack(type, name, parent) { + _setProperty("DataAddress", LHCb::CaloDigitLocation::Prs); + _setProperty("Tolerance", "2"); /// 2 * Gaudi::Units::mm + _setProperty("CalorimeterFuture", DeCalorimeterLocation::Prs); + }; +}; + +// ============================================================================ + +DECLARE_COMPONENT( FuturePrsEnergyForTrack ) diff --git a/CaloFuture/CaloFuturePIDs/src/FuturePrsPIDeAlg.cpp b/CaloFuture/CaloFuturePIDs/src/FuturePrsPIDeAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a9d5b2d1ed93e53df2409eec3acaa3204b74243a --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/FuturePrsPIDeAlg.cpp @@ -0,0 +1,49 @@ +// Include files +#include "CaloFutureID2DLL.h" + +// ============================================================================ +/** @class FuturePrsPIDeAlg FuturePrsPIDeAlg.cpp + * The preconfigured instance of class CaloFutureID2DLL + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-18 + */ +// ============================================================================ + +class FuturePrsPIDeAlg final : public CaloFutureID2DLL { + public: + FuturePrsPIDeAlg(const std::string& name, ISvcLocator* pSvc) + : CaloFutureID2DLL(name, pSvc) { + using LHCb::CaloFutureAlgUtils::CaloFutureIdLocation; + + Gaudi::Functional::updateHandleLocation( + *this, "Input", CaloFutureIdLocation("PrsE", context())); + Gaudi::Functional::updateHandleLocation( + *this, "Output", CaloFutureIdLocation("PrsPIDe", context())); + + _setProperty("nVlong" , Gaudi::Utils::toString(100 * Gaudi::Units::MeV)); + _setProperty("nVdown" , Gaudi::Utils::toString(100 * Gaudi::Units::MeV)); + _setProperty("nVTtrack", Gaudi::Utils::toString(100 * Gaudi::Units::MeV)); + _setProperty("nMlong" , Gaudi::Utils::toString(100 * Gaudi::Units::GeV)); + _setProperty("nMdown" , Gaudi::Utils::toString(100 * Gaudi::Units::GeV)); + _setProperty("nMTtrack", Gaudi::Utils::toString(100 * Gaudi::Units::GeV)); + + _setProperty("HistogramL" , "DLL_Long"); + _setProperty("HistogramD" , "DLL_Downstream"); + _setProperty("HistogramT" , "DLL_Ttrack"); + _setProperty("ConditionName", "Conditions/ParticleID/Calo/PrsPIDe"); + + _setProperty("HistogramL_THS", "CaloFuturePIDs/CALO/PRSPIDE/h3"); + _setProperty("HistogramD_THS", "CaloFuturePIDs/CALO/PRSPIDE/h5"); + _setProperty("HistogramT_THS", "CaloFuturePIDs/CALO/PRSPIDE/h6"); + + _setProperty("AcceptedType", Gaudi::Utils::toString<int>( + LHCb::Track::Types::Long, LHCb::Track::Types::Ttrack, + LHCb::Track::Types::Downstream)); + }; +}; + +// ============================================================================ + +DECLARE_COMPONENT( FuturePrsPIDeAlg ) + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/FutureSpdEnergyForTrack.cpp b/CaloFuture/CaloFuturePIDs/src/FutureSpdEnergyForTrack.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d60beaf3e712278f1c46d5f071d399a640d4b488 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/FutureSpdEnergyForTrack.cpp @@ -0,0 +1,25 @@ +// Include files +#include "CaloFutureEnergyForTrack.h" + +// ============================================================================ +/** @class FutureSpdEnergyForTrack + * The concrete preconfigured insatnce for CaloFutureEnergyForTrack tool + * along the track line + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + */ +// ============================================================================ + +class FutureSpdEnergyForTrack final : public CaloFutureEnergyForTrack { + public: + FutureSpdEnergyForTrack(const std::string& type, const std::string& name, + const IInterface* parent) + : CaloFutureEnergyForTrack(type, name, parent) { + _setProperty("DataAddress", LHCb::CaloDigitLocation::Spd); + _setProperty("Tolerance", "2"); /// 2 * Gaudi::Units::mm + _setProperty("CalorimeterFuture", DeCalorimeterLocation::Spd); + }; +}; + +// ============================================================================ + +DECLARE_COMPONENT( FutureSpdEnergyForTrack ) diff --git a/CaloFuture/CaloFuturePIDs/src/FutureTrack2EcalEAlg.cpp b/CaloFuture/CaloFuturePIDs/src/FutureTrack2EcalEAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dba435804ddaf6f7fb1c3dbcc62ed22594fff187 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/FutureTrack2EcalEAlg.cpp @@ -0,0 +1,24 @@ +// Include files +#include "CaloFutureTrack2IDAlg.h" + +// ============================================================================ +/** @class FutureTrack2EcalEAlg FutureTrack2EcalEAlg.cpp + * preconfigured instance of class CaloFutureTrack2IDAlg + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-15 + */ +struct FutureTrack2EcalEAlg final : public CaloFutureTrack2IDAlg { + FutureTrack2EcalEAlg(const std::string& name, ISvcLocator* pSvc) + : CaloFutureTrack2IDAlg(name, pSvc) { + using LHCb::CaloFutureAlgUtils::CaloFutureIdLocation; + _setProperty("Output", CaloFutureIdLocation("EcalE", context())); + _setProperty("Filter", CaloFutureIdLocation("InEcal", context())); + _setProperty("Tool", "FutureEcalEnergyForTrack/EcalEFuture"); + } +}; + +// ============================================================================ + +DECLARE_COMPONENT( FutureTrack2EcalEAlg ) + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/FutureTrack2HcalEAlg.cpp b/CaloFuture/CaloFuturePIDs/src/FutureTrack2HcalEAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f55b2a7b66b0dc0742a9017a348b8adf5ad7dc80 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/FutureTrack2HcalEAlg.cpp @@ -0,0 +1,24 @@ +// Include files +#include "CaloFutureTrack2IDAlg.h" + +// ============================================================================ +/** @class FutureTrack2HcalEAlg FutureTrack2HcalEAlg.cpp + * preconfigured instance of class CaloFutureTrack2IDAlg + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-15 + */ +struct FutureTrack2HcalEAlg final : public CaloFutureTrack2IDAlg { + FutureTrack2HcalEAlg(const std::string& name, ISvcLocator* pSvc) + : CaloFutureTrack2IDAlg(name, pSvc) { + using LHCb::CaloFutureAlgUtils::CaloFutureIdLocation; + _setProperty("Output", CaloFutureIdLocation("HcalE", context())); + _setProperty("Filter", CaloFutureIdLocation("InHcal", context())); + _setProperty("Tool", "FutureHcalEnergyForTrack/HcalEFuture"); + } +}; + +// ============================================================================ + +DECLARE_COMPONENT( FutureTrack2HcalEAlg ) + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/FutureTrack2PrsEAlg.cpp b/CaloFuture/CaloFuturePIDs/src/FutureTrack2PrsEAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d42c1e6d4c8c8a64ee1b98eebec5301655c1c1e --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/FutureTrack2PrsEAlg.cpp @@ -0,0 +1,24 @@ +// Include files +#include "CaloFutureTrack2IDAlg.h" + +// ============================================================================ +/** @class FutureTrack2PrsEAlg FutureTrack2PrsEAlg.cpp + * preconfigured instance of class CaloFutureTrack2IDAlg + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-15 + */ +struct FutureTrack2PrsEAlg final : public CaloFutureTrack2IDAlg { + FutureTrack2PrsEAlg(const std::string& name, ISvcLocator* pSvc) + : CaloFutureTrack2IDAlg(name, pSvc) { + using LHCb::CaloFutureAlgUtils::CaloFutureIdLocation; + _setProperty("Output", CaloFutureIdLocation("PrsE", context())); + _setProperty("Filter", CaloFutureIdLocation("InPrs", context())); + _setProperty("Tool", "FuturePrsEnergyForTrack/PrsE"); + } +}; + +// ============================================================================ + +DECLARE_COMPONENT( FutureTrack2PrsEAlg ) + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/FutureTrack2SpdEAlg.cpp b/CaloFuture/CaloFuturePIDs/src/FutureTrack2SpdEAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..58f646402d45c3058604ececa734342c52fd5fa0 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/FutureTrack2SpdEAlg.cpp @@ -0,0 +1,24 @@ +// Include files +#include "CaloFutureTrack2IDAlg.h" + +// ============================================================================ +/** @class FutureTrack2SpdEAlg FutureTrack2SpdEAlg.cpp + * preconfigured instance of class CaloFutureTrack2IDAlg + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-15 + */ +struct FutureTrack2SpdEAlg final : public CaloFutureTrack2IDAlg { + FutureTrack2SpdEAlg(const std::string& name, ISvcLocator* pSvc) + : CaloFutureTrack2IDAlg(name, pSvc) { + using LHCb::CaloFutureAlgUtils::CaloFutureIdLocation; + _setProperty("Output", CaloFutureIdLocation("SpdE", context())); + _setProperty("Filter", CaloFutureIdLocation("InSpd", context())); + _setProperty("Tool", "FutureSpdEnergyForTrack/SpdE"); + } +}; + +// ============================================================================ + +DECLARE_COMPONENT( FutureTrack2SpdEAlg ) + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/InBremFutureAcceptance.cpp b/CaloFuture/CaloFuturePIDs/src/InBremFutureAcceptance.cpp new file mode 100644 index 0000000000000000000000000000000000000000..db0d74f04fa363a77c2d26bd1d04941a4fada338 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/InBremFutureAcceptance.cpp @@ -0,0 +1,79 @@ +// Include files +#include "InCaloFutureAcceptance.h" +#include "LHCbMath/GeomFun.h" +#include "LHCbMath/Line.h" +#include "Linear.h" + +// ============================================================================ +/** @class InBremFutureAcceptance + * The preconfigured instance of InCaloFutureAcceptance Tool + * @author Victor EGORYCHEV Victor.Egorychev@cern.ch + * @author Vanya BELYAEV ibelyaev@phsycis.syr.edu + * @date 2006-05-28 + */ +// ============================================================================ + +struct InBremFutureAcceptance final : InCaloFutureAcceptance { + /// standard constructor + InBremFutureAcceptance(const std::string& type, const std::string& name, + const IInterface* parent) + : InCaloFutureAcceptance(type, name, parent) { + _setProperty("CalorimeterFuture", DeCalorimeterLocation::Ecal); + } + + /// C++11 non-copyable idiom + InBremFutureAcceptance() = delete; + InBremFutureAcceptance(const InBremFutureAcceptance&) = delete; + InBremFutureAcceptance& operator=(const InBremFutureAcceptance&) = delete; + + // ========================================================================== + /** check the track is in acceptance of given calorimeter + * @see IInAcceptance + * @param track track to be checked + * @return true if the track is in acceptance + */ + bool inAcceptance(const LHCb::Track* track) const override; +}; + +// ============================================================================ + +DECLARE_COMPONENT( InBremFutureAcceptance ) + +// ============================================================================ +// check the expected bremstrahlung photon is in acceptance of Ecal +// ============================================================================ + +bool InBremFutureAcceptance::inAcceptance(const LHCb::Track* track) const { + // check the goodness of the tarck + if (!use(track)) { + return false; + } // RETURN + // + // find the appropriate state + const LHCb::State* state = nullptr; + for (const auto& loc : {LHCb::State::Location::AtTT, LHCb::State::Location::EndRich1, + LHCb::State::Location::BegRich1, LHCb::State::Location::EndVelo}) { + state = CaloFutureTrackTool::state(*track, loc); + if (state) break; + } + if (!state) { + // get the closest state to some artificial value + state = &(track->closestState(2.0 * Gaudi::Units::meter)); + // allowed z ? + if (state->z() > 4.0 * Gaudi::Units::meter) { + Error("No appropriate states are found, see 'debug'").ignore(); + if (msgLevel(MSG::DEBUG)) print(debug(), track); + return false; + } + } + // get the line form the state + const Line l = line(*state); + // get the point of intersection of the line with the plane + Gaudi::XYZPoint point; + double mu = 0; + Gaudi::Math::intersection(l, plane(), point, mu); + // + return ok(point); +} + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/InBremFutureAcceptanceAlg.cpp b/CaloFuture/CaloFuturePIDs/src/InBremFutureAcceptanceAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..de10fbe1837d201042a54f2f2f81662801b817c4 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/InBremFutureAcceptanceAlg.cpp @@ -0,0 +1,33 @@ +// Include files +#include "InCaloFutureAcceptanceAlg.h" + +// ============================================================================ +/** @class FutureInBremFutureAcceptanceAlg FutureInBremFutureAcceptanceAlg.cpp + * the preconfigured instance of InCaloFutureAcceptanceAlg + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-17 + */ +// ============================================================================ + +struct FutureInBremFutureAcceptanceAlg final : InCaloFutureAcceptanceAlg { + /// Standard constructor + FutureInBremFutureAcceptanceAlg(const std::string& name, ISvcLocator* pSvc) + : InCaloFutureAcceptanceAlg(name, pSvc) { + using LHCb::CaloFutureAlgUtils::CaloFutureIdLocation; + + Gaudi::Functional::updateHandleLocation( + *this, "Output", CaloFutureIdLocation("InBrem", context())); + + _setProperty("Tool", "InBremFutureAcceptance/InBremFuture"); + // track types: + _setProperty("AcceptedType", Gaudi::Utils::toString<int>( + LHCb::Track::Types::Velo, LHCb::Track::Types::Long, + LHCb::Track::Types::Upstream)); + } +}; + +// ============================================================================ + +DECLARE_COMPONENT( FutureInBremFutureAcceptanceAlg ) + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/InCaloFutureAcceptance.cpp b/CaloFuture/CaloFuturePIDs/src/InCaloFutureAcceptance.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9f175dec429375db56a2962ac50348611af58924 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/InCaloFutureAcceptance.cpp @@ -0,0 +1,110 @@ +// Include files +#include "Event/Track.h" +#include "GaudiKernel/Point3DTypes.h" +#include "GaudiKernel/Vector3DTypes.h" +#include "GaudiKernel/Plane3DTypes.h" +#include "Kernel/CaloCellCode.h" +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureTrackAlg.h" +#include "InCaloFutureAcceptance.h" + +// ============================================================================ +/** @file + * Implementation file for class InCaloFutureAcceptance + * @see InAccpetance + * + * @author Victor EGORYCHEV Victor.Egorychev@cern.ch + * @author Vanya BELYAEV ibelyaev@phsycis.syr.edu + * @date 2006-05-28 + */ +// ============================================================================ + +DECLARE_COMPONENT( InCaloFutureAcceptance ) + +// ============================================================================ +// Standard constructor, initializes variables +// ============================================================================ + +InCaloFutureAcceptance::InCaloFutureAcceptance(const std::string& type, + const std::string& name, + const IInterface* parent) + : CaloFuture::CaloFutureTrackTool(type, name, parent) { + declareInterface<IInAcceptance>(this); +} + +// ============================================================================ +// initialization @see IAlgTool +// ============================================================================ + +StatusCode InCaloFutureAcceptance::initialize() { + StatusCode sc = CaloFuture::CaloFutureTrackTool::initialize(); + if (sc.isFailure()) { + return sc; + } + // check the detector + if (calo() == nullptr) { + return Error("Invalid Detector"); + } + // select the plane + const int check_calorimeter_id = + CaloCellCode::CaloNumFromName(detectorName()); + switch (check_calorimeter_id) { + case 0: + // SPD + m_loc = LHCb::State::Location::Spd; + m_plane = calo()->plane(CaloPlane::Middle); + break; // BREAK + case 1: + // PRS + m_loc = LHCb::State::Location::Prs; + m_plane = calo()->plane(CaloPlane::Middle); + break; // BREAK + case 2: + // ECAL + m_loc = LHCb::State::Location::ECalShowerMax; + m_plane = calo()->plane(CaloPlane::ShowerMax); + break; // BREAK + case 3: + // HCAL + m_loc = LHCb::State::Location::MidHCal; + m_plane = calo()->plane(CaloPlane::Middle); + break; // BREAK + default: + return Error("Invalid calorimeter TYPE! '" + detectorName() + "'"); + } + // + if (propsPrint() || msgLevel(MSG::DEBUG)) { + info() << "State to be used for aceptance check is '" << m_loc << "'" + << endmsg; + } + return StatusCode::SUCCESS; +} + +// ============================================================================ +// check the track is in acceptance of the given calorimeter +// ============================================================================ + +bool InCaloFutureAcceptance::inAcceptance(const LHCb::Track* track) const { + // check the goodness of the tarck + if (!use(track)) { + return false; + } // RETURN + + // find the appropriate state + auto state = CaloFuture::CaloFutureTrackTool::state(*track, m_loc); + if (state == nullptr) { + // if there is no proper state - add it into the track! + StatusCode sc = propagate(*track, plane(), m_state); + if (sc.isFailure()) { + Error("failure from propagate()", sc).ignore(); + return false; // RETURN + } + m_state.setLocation(m_loc); + const_cast<LHCb::Track*>(track)->addToStates(m_state); + state = &m_state; + } + // check the point + return ok(state->position()); +} + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/InCaloFutureAcceptance.h b/CaloFuture/CaloFuturePIDs/src/InCaloFutureAcceptance.h new file mode 100644 index 0000000000000000000000000000000000000000..d857709866bf8edb1af14b0668fee44af6f784db --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/InCaloFutureAcceptance.h @@ -0,0 +1,86 @@ +#ifndef CALOFUTUREPIDS_INCALOFUTUREACCEPTANCE_H +#define CALOFUTUREPIDS_INCALOFUTUREACCEPTANCE_H 1 + +// Include files +#include "GaudiAlg/GaudiTool.h" +#include "CaloFutureTrackTool.h" +#include "TrackInterfaces/IInAcceptance.h" +#include "TrackInterfaces/ITrackExtrapolator.h" + +// ============================================================================ + +/** @class InCaloFutureAcceptance InCaloFutureAcceptance.h + * + * The general tool to determine if the reconstructed charged track + * "is in CalorimeterFuture acceptance" + * + * @author Victor EGORYCHEV Victor.Egorychev@cern.ch + * @author Vanya BELYAEV ibelyaev@phsycis.syr.edu + * @date 2006-05-28 + */ +class InCaloFutureAcceptance : public virtual IInAcceptance, + public CaloFuture::CaloFutureTrackTool { + public: + /// initialization @see IAlgTool + StatusCode initialize() override; + + /** check the track is in acceptance of given calorimeter + * @see IInAcceptance + * @param track track to be checked + * @return true if the track is in acceptance + */ + bool inAcceptance(const LHCb::Track* track) const override; + + protected: + /// check if the point "is in acceptance" + inline bool ok(const Gaudi::XYZPoint& point) const; + /// get the plane + const Gaudi::Plane3D& plane() const { return m_plane; } + + public: + InCaloFutureAcceptance(const std::string& type, const std::string& name, + const IInterface* parent); + +private: + /// use fiducial volume or real volume ? + Gaudi::Property<bool> m_fiducial {this, "UseFiducial", true}; + LHCb::State::Location m_loc ; + /// + Gaudi::Plane3D m_plane; + /// Local storage + mutable LHCb::State m_state; +}; + +// ============================================================================ +/// check if the point "is in acceptance" +// ============================================================================ + +inline bool InCaloFutureAcceptance::ok(const Gaudi::XYZPoint& point) const { + const CellParam* cell = calo()->Cell_(point); + if (cell==nullptr || !cell->valid()) { + return false; + } + // check for fiducial volume ? + if (!m_fiducial) { + return true; + } + // check for neighbors + const CaloNeighbors& neighbors = cell->neighbors(); + // regular cell: >= 8 valid neighbours + if (8 <= neighbors.size()) { + return true; + } + // incomplete neibors: border of 2 zones ? + const unsigned int area = cell->cellID().area(); + for (auto inei = neighbors.begin() + 1; neighbors.end() != inei; ++inei) { + if (area != inei->area()) { + return true; + } + } + // finally + return false; +} + +// =========================================================================== +#endif // CALOFUTUREPIDS_INCALOFUTUREACCEPTANCE_H +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/InCaloFutureAcceptanceAlg.cpp b/CaloFuture/CaloFuturePIDs/src/InCaloFutureAcceptanceAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8bed031722f7001026778e1ce46847c52094b5d1 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/InCaloFutureAcceptanceAlg.cpp @@ -0,0 +1,65 @@ +// include files +#include <type_traits> +#include "Relations/Relation1D.h" +#include "InCaloFutureAcceptanceAlg.h" + +// ============================================================================ +/** @file + * Implementation file for class InCaloFutureAcceptanceAlg + * @Date 2006-06-17 + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + */ +// ============================================================================ + +DECLARE_COMPONENT( InCaloFutureAcceptanceAlg ) + +// ============================================================================ +/// Standard protected constructor +// ============================================================================ + +InCaloFutureAcceptanceAlg::InCaloFutureAcceptanceAlg(const std::string& name, + ISvcLocator* pSvc) + : Transformer(name, pSvc, KeyValue{"Inputs", ""}, KeyValue{"Output", ""}) { + // context-dependent default track container + // (Context only available after baseclass is contructed) + Gaudi::Functional::updateHandleLocation(*this, "Inputs", LHCb::CaloFutureAlgUtils::TrackLocations(context()).front()); +} + +// ============================================================================ +// algorithm execution +// ============================================================================ + +Table InCaloFutureAcceptanceAlg::operator()(const LHCb::Tracks& tracks) const { + // a trivial check + Assert(m_tool, "InAcceptance-tool is invalid!"); + + if (0 == tracks.size()) { + if (msgLevel(MSG::DEBUG)) + debug() << "No tracks retrieved from container" << endmsg; + } + + Table table(100); + + size_t nAccept = 0; + // loop over all tracks in the container + for (const auto& track : tracks) { + if (!use(track)) { + continue; + } // CONTINUE + const bool result = m_tool->inAcceptance(track); + // fill the relation table + table.i_push(track, result); // ATTENTION: i-push is used + if (result) { + ++nAccept; + } + } + // MANDATORY: i_sort after i_push + table.i_sort(); + + // a bit of statistics + m_nTracks += tracks.size(); + m_nAccept += nAccept; + m_nLinks += table.i_relations().size(); + + return table; +} diff --git a/CaloFuture/CaloFuturePIDs/src/InCaloFutureAcceptanceAlg.h b/CaloFuture/CaloFuturePIDs/src/InCaloFutureAcceptanceAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..f3833956d5ba195d62fe87094cb7e7397891ab68 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/InCaloFutureAcceptanceAlg.h @@ -0,0 +1,52 @@ +#ifndef CALOFUTUREPIDS_INCALOFUTUREACCEPTANCEALG_H +#define CALOFUTUREPIDS_INCALOFUTUREACCEPTANCEALG_H 1 + +// Include files +#include "CaloFutureTrackAlg.h" +#include "CaloFutureUtils/CaloFuture2Track.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "Event/Track.h" +#include "GaudiAlg/Transformer.h" +#include "GaudiKernel/Counters.h" +#include "TrackInterfaces/IInAcceptance.h" +#include "Relations/Relation1D.h" +#include "ToVector.h" + +// ============================================================================ +/** @class InCaloFutureAcceptanceAlg InCaloFutureAcceptanceAlg.h + * + * the trivial algorithm to fill "InCaloFutureAcceptance" table + * + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-17 + */ +// ============================================================================ + +using Table = LHCb::Relation1D<LHCb::Track,bool>; + +class InCaloFutureAcceptanceAlg + : public Gaudi::Functional::Transformer< + Table(const LHCb::Tracks&), + Gaudi::Functional::Traits::BaseClass_t<CaloFutureTrackAlg> > +{ + // check the proper convertability + static_assert(std::is_base_of<LHCb::CaloFuture2Track::ITrAccTable, Table>::value, + "Table must inherit from ITrAccTable"); + + public: + /// Standard constructor + InCaloFutureAcceptanceAlg(const std::string& name, ISvcLocator* pSvc); + /// algorithm execution + Table operator()(const LHCb::Tracks&) const override; + + ToolHandle<IInAcceptance> m_tool {this, "Tool", "<NOT DEFINED>"}; + + // counter + mutable Gaudi::Accumulators::StatCounter<> m_nTracks{this, "#total tracks"}; + mutable Gaudi::Accumulators::StatCounter<> m_nAccept{this, "#tracks in acceptance"}; + mutable Gaudi::Accumulators::StatCounter<> m_nLinks {this, "#links in table"}; +}; + +// ============================================================================ +#endif // CALOFUTUREPIDS_INCALOFUTUREACCEPTANCEALG_H +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/InEcalFutureAcceptance.cpp b/CaloFuture/CaloFuturePIDs/src/InEcalFutureAcceptance.cpp new file mode 100644 index 0000000000000000000000000000000000000000..47e9687c88154dd1b3f238749f25636cc9d35399 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/InEcalFutureAcceptance.cpp @@ -0,0 +1,33 @@ +// Include files +#include "InCaloFutureAcceptance.h" + +// ============================================================================ +/** @class InEcalFutureAcceptance + * The precofigured instance of InCaloFutureAcceptance Tool + * @author Victor EGORYCHEV Victor.Egorychev@cern.ch + * @author Vanya BELYAEV ibelyaev@phsycis.syr.edu + * @date 2006-05-28 + */ +// ============================================================================ + +struct InEcalFutureAcceptance final : InCaloFutureAcceptance { + /// standard constructor + InEcalFutureAcceptance(const std::string& type, const std::string& name, + const IInterface* parent) + : InCaloFutureAcceptance(type, name, parent) { + _setProperty("CalorimeterFuture", DeCalorimeterLocation::Ecal); + _setProperty("UseFiducial", "true"); + _setProperty("Tolerance", "5"); /// 5 * Gaudi::Units::mm + }; + + /// C++11 non-copyable idiom + InEcalFutureAcceptance() = delete; + InEcalFutureAcceptance(const InEcalFutureAcceptance&) = delete; + InEcalFutureAcceptance& operator=(const InEcalFutureAcceptance&) = delete; +}; + +// ============================================================================ + +DECLARE_COMPONENT( InEcalFutureAcceptance ) + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/InEcalFutureAcceptanceAlg.cpp b/CaloFuture/CaloFuturePIDs/src/InEcalFutureAcceptanceAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e9de2804a30853a52800b67ee60007bc8d8c0861 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/InEcalFutureAcceptanceAlg.cpp @@ -0,0 +1,32 @@ +// Include files +#include "InCaloFutureAcceptanceAlg.h" + +// ============================================================================ +/** @class InEcalFutureAcceptance Alg InEcalFutureAcceptance Alg.cpp + * the preconfigured instance of InCaloFutureAcceptanceAlg + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-17 + */ +// ============================================================================ + +struct InEcalFutureAcceptanceAlg final : InCaloFutureAcceptanceAlg { + /// Standard constructor + InEcalFutureAcceptanceAlg(const std::string& name, ISvcLocator* pSvc) + : InCaloFutureAcceptanceAlg(name, pSvc) { + using LHCb::CaloFutureAlgUtils::CaloFutureIdLocation; + Gaudi::Functional::updateHandleLocation( + *this, "Output", CaloFutureIdLocation("InEcal", context())); + + _setProperty("Tool", "InEcalFutureAcceptance/InEcalFuture"); + // track types: + _setProperty("AcceptedType", Gaudi::Utils::toString<int>( + LHCb::Track::Types::Long, LHCb::Track::Types::Downstream, + LHCb::Track::Types::Ttrack)); + } +}; + +// ============================================================================ + +DECLARE_COMPONENT( InEcalFutureAcceptanceAlg ) + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/InHcalFutureAcceptance.cpp b/CaloFuture/CaloFuturePIDs/src/InHcalFutureAcceptance.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d6e4c9b7f90922785c7e0fd53575493a25f61875 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/InHcalFutureAcceptance.cpp @@ -0,0 +1,33 @@ +// Include files +#include "InCaloFutureAcceptance.h" + +// ============================================================================ +/** @class InHcalFutureAcceptance + * The precofigured instance of InCaloFutureAcceptance Tool + * @author Victor EGORYCHEV Victor.Egorychev@cern.ch + * @author Vanya BELYAEV ibelyaev@phsycis.syr.edu + * @date 2006-05-28 + */ +// ============================================================================ + +struct InHcalFutureAcceptance final : InCaloFutureAcceptance { + /// standard constructor + InHcalFutureAcceptance(const std::string& type, const std::string& name, + const IInterface* parent) + : InCaloFutureAcceptance(type, name, parent) { + _setProperty("CalorimeterFuture", DeCalorimeterLocation::Hcal); + _setProperty("UseFiducial", "true"); + _setProperty("Tolerance", "10"); /// 10 * Gaudi::Units::mm + }; + + /// C++11 non-copyable idiom + InHcalFutureAcceptance() = delete; + InHcalFutureAcceptance(const InHcalFutureAcceptance&) = delete; + InHcalFutureAcceptance& operator=(const InHcalFutureAcceptance&) = delete; +}; + +// ============================================================================ + +DECLARE_COMPONENT( InHcalFutureAcceptance ) + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/InHcalFutureAcceptanceAlg.cpp b/CaloFuture/CaloFuturePIDs/src/InHcalFutureAcceptanceAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b44299fddd8c42d93e9f392d11bdb95a5c2572b6 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/InHcalFutureAcceptanceAlg.cpp @@ -0,0 +1,33 @@ +// Include files +#include "InCaloFutureAcceptanceAlg.h" + +// ============================================================================ +/** @class InHcalFutureAcceptanceAlg InHcalFutureAcceptanceAlg.cpp + * the preconfigured instance of InCaloFutureAcceptanceAlg + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-17 + */ +// ============================================================================ + +struct InHcalFutureAcceptanceAlg final : InCaloFutureAcceptanceAlg { + /// Standard constructor + InHcalFutureAcceptanceAlg(const std::string& name, ISvcLocator* pSvc) + : InCaloFutureAcceptanceAlg(name, pSvc) { + using LHCb::CaloFutureAlgUtils::CaloFutureIdLocation; + + Gaudi::Functional::updateHandleLocation( + *this, "Output", CaloFutureIdLocation("InHcal", context())); + + _setProperty("Tool", "InHcalFutureAcceptance/InHcalFuture"); + // track types: + _setProperty("AcceptedType", Gaudi::Utils::toString<int>( + LHCb::Track::Types::Long, LHCb::Track::Types::Downstream, + LHCb::Track::Types::Ttrack)); + } +}; + +// ============================================================================ + +DECLARE_COMPONENT( InHcalFutureAcceptanceAlg ) + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/InPrsFutureAcceptance.cpp b/CaloFuture/CaloFuturePIDs/src/InPrsFutureAcceptance.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d0ddcea85ec848d19bbd0f083471a7679d63de6 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/InPrsFutureAcceptance.cpp @@ -0,0 +1,33 @@ +// Include files +#include "InCaloFutureAcceptance.h" + +// ============================================================================ +/** @class InPrsFutureAcceptance + * The precofigured instance of InCaloFutureAcceptance Tool + * @author Victor EGORYCHEV Victor.Egorychev@cern.ch + * @author Vanya BELYAEV ibelyaev@phsycis.syr.edu + * @date 2006-05-28 + */ +// ============================================================================ + +struct InPrsFutureAcceptance final : InCaloFutureAcceptance { + /// standard constructor + InPrsFutureAcceptance(const std::string& type, const std::string& name, + const IInterface* parent) + : InCaloFutureAcceptance(type, name, parent) { + _setProperty("CalorimeterFuture", DeCalorimeterLocation::Prs); + _setProperty("UseFiducial", "false"); + _setProperty("Tolerance", "10"); /// 10 * Gaudi::Units::mm + }; + + /// C++11 non-copyable idiom + InPrsFutureAcceptance() = delete; + InPrsFutureAcceptance(const InPrsFutureAcceptance&) = delete; + InPrsFutureAcceptance& operator=(const InPrsFutureAcceptance&) = delete; +}; + +// ============================================================================ + +DECLARE_COMPONENT( InPrsFutureAcceptance ) + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/InPrsFutureAcceptanceAlg.cpp b/CaloFuture/CaloFuturePIDs/src/InPrsFutureAcceptanceAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b606a247629cdc4260706a432302f16b966e674 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/InPrsFutureAcceptanceAlg.cpp @@ -0,0 +1,33 @@ +// Include files +#include "InCaloFutureAcceptanceAlg.h" + +// ============================================================================ +/** @class InPrsFutureAcceptanceAlg InPrsFutureAcceptanceAlg.cpp + * the preconfigured instance of InCaloFutureAcceptanceAlg + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-17 + */ +// ============================================================================ + +struct InPrsFutureAcceptanceAlg final : InCaloFutureAcceptanceAlg { + /// Standard constructor + InPrsFutureAcceptanceAlg(const std::string& name, ISvcLocator* pSvc) + : InCaloFutureAcceptanceAlg(name, pSvc) { + using LHCb::CaloFutureAlgUtils::CaloFutureIdLocation; + + Gaudi::Functional::updateHandleLocation(*this, "Output", + CaloFutureIdLocation("InPrs", context())); + + _setProperty("Tool", "InPrsFutureAcceptance/InPrs"); + // track types: + _setProperty("AcceptedType", Gaudi::Utils::toString<int>( + LHCb::Track::Types::Long, LHCb::Track::Types::Downstream, + LHCb::Track::Types::Ttrack)); + } +}; + +// ============================================================================ + +DECLARE_COMPONENT( InPrsFutureAcceptanceAlg ) + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/InSpdFutureAcceptance.cpp b/CaloFuture/CaloFuturePIDs/src/InSpdFutureAcceptance.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f5b6f78cd82baa0285af6a8d58853c0492f8f5f5 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/InSpdFutureAcceptance.cpp @@ -0,0 +1,33 @@ +// Include files +#include "InCaloFutureAcceptance.h" + +// ============================================================================ +/** @class InSpdFutureAcceptance + * The precofigured instance of InCaloFutureAcceptance Tool + * @author Victor EGORYCHEV Victor.Egorychev@cern.ch + * @author Vanya BELYAEV ibelyaev@phsycis.syr.edu + * @date 2006-05-28 + */ +// ============================================================================ + +struct InSpdFutureAcceptance final : InCaloFutureAcceptance { + /// standard constructor + InSpdFutureAcceptance(const std::string& type, const std::string& name, + const IInterface* parent) + : InCaloFutureAcceptance(type, name, parent) { + _setProperty("CalorimeterFuture", DeCalorimeterLocation::Spd); + _setProperty("UseFiducial", "false"); + _setProperty("Tolerance", "1"); /// 1 * Gaudi::Units::mm + }; + + /// C++11 non-copyable idiom + InSpdFutureAcceptance() = delete; + InSpdFutureAcceptance(const InSpdFutureAcceptance&) = delete; + InSpdFutureAcceptance& operator=(const InSpdFutureAcceptance&) = delete; +}; + +// ============================================================================ + +DECLARE_COMPONENT( InSpdFutureAcceptance ) + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/InSpdFutureAcceptanceAlg.cpp b/CaloFuture/CaloFuturePIDs/src/InSpdFutureAcceptanceAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..488ebad43787908ae72893a410a009694469f6e1 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/InSpdFutureAcceptanceAlg.cpp @@ -0,0 +1,33 @@ +// Include files +#include "InCaloFutureAcceptanceAlg.h" + +// ============================================================================ +/** @class InSpdFutureAcceptanceAlg InSpdFutureAcceptanceAlg.cpp + * the preconfigured instance of InCaloFutureAcceptanceAlg + * @author Vanya BELYAEV ibelyaev@physics.syr.edu + * @date 2006-06-17 + */ +// ============================================================================ + +struct InSpdFutureAcceptanceAlg final : InCaloFutureAcceptanceAlg { + /// Standard constructor + InSpdFutureAcceptanceAlg(const std::string& name, ISvcLocator* pSvc) + : InCaloFutureAcceptanceAlg(name, pSvc) { + using LHCb::CaloFutureAlgUtils::CaloFutureIdLocation; + + Gaudi::Functional::updateHandleLocation(*this, "Output", + CaloFutureIdLocation("InSpd", context())); + + _setProperty("Tool", "InSpdFutureAcceptance/InSpd"); + // track types: + _setProperty("AcceptedType", Gaudi::Utils::toString<int>( + LHCb::Track::Types::Long, LHCb::Track::Types::Downstream, + LHCb::Track::Types::Ttrack)); + } +}; + +// ============================================================================ + +DECLARE_COMPONENT( InSpdFutureAcceptanceAlg ) + +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/Linear.h b/CaloFuture/CaloFuturePIDs/src/Linear.h new file mode 100644 index 0000000000000000000000000000000000000000..7e615c709c1a06a55b3339850a49027c148d457a --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/Linear.h @@ -0,0 +1,155 @@ +// ============================================================================ +#ifndef CALOFUTUREPIDS_LINEAR_H +#define CALOFUTUREPIDS_LINEAR_H 1 +// ============================================================================ +// Include files +// ============================================================================ +// Event +// ============================================================================ +#include "Event/State.h" +#include "Event/TrackTypes.h" +// ============================================================================ +// LHCbMath +// ============================================================================ +#include "LHCbMath/Line.h" +#include "LHCbMath/GeomFun.h" +// ============================================================================ +// Math Definitions +// ============================================================================ +#include "GaudiKernel/Plane3DTypes.h" +// ============================================================================ + +namespace Utils +{ + namespace Linear + { + /** make a linear extrapiolation of the state to a certain Z + * @param state (input/output) state to be extrapolated + * @param newZ (input) z-position + * @return status code + */ + inline + StatusCode propagate + ( LHCb::State& state , + const double newZ ) + { + // make a linear extrapolation of state to new Z-position + if ( newZ == state.z() ) { return StatusCode::SUCCESS ; } + // + const double dz = newZ - state.z() ; + // correct the positions: + state.setZ ( newZ ) ; + Gaudi::TrackVector& vct = state.stateVector(); + + vct[0] += dz*vct[2] ; + vct[1] += dz*vct[3]; + + // correct the covarinaces: + Gaudi::TrackSymMatrix& cov = state.covariance() ; + // + const double dz2 = dz * dz ; + // + enum { + X = 0 , + Y = 1 , + TX = 2 , + TY = 3 , + QP = 4 + } ; + // + const double _cxx = cov ( X , X ) ; + const double _cxy = cov ( X , Y ) ; + const double _cxtx = cov ( X , TX ) ; + const double _cxty = cov ( X , TY ) ; + const double _cxqp = cov ( X , QP ) ; + // + const double _cyy = cov ( Y , Y ) ; + const double _cytx = cov ( Y , TX ) ; + const double _cyty = cov ( Y , TY ) ; + const double _cyqp = cov ( Y , QP ) ; + // + const double _ctxtx = cov ( TX , TX ) ; + const double _ctxty = cov ( TX , TY ) ; + const double _ctxqp = cov ( TX , QP ) ; + // + const double _ctyty = cov ( TY , TY ) ; + const double _ctyqp = cov ( TY , QP ) ; + // + // const double _cqpqp = cov ( QP , QP ) ; + // + // update the matrix + // + cov ( X , X ) = _cxx + 2*dz*_cxtx + dz2 * _ctxtx ; + cov ( X , Y ) = _cxy + dz*(_cxty+_cytx) + dz2 * _ctxty ; + cov ( X , TX ) = _cxtx + dz * _ctxtx ; + cov ( X , TY ) = _cxty + dz * _ctxty ; + cov ( X , QP ) = _cxqp + dz * _ctxqp ; + // + cov ( Y , Y ) = _cyy + 2*dz*_cyty + dz2 * _ctyty ; + cov ( Y , TX ) = _cytx + dz * _ctxty ; + cov ( Y , TY ) = _cyty + dz * _ctyty ; + cov ( Y , QP ) = _cyqp + dz * _ctyqp ; + // + // + return StatusCode::SUCCESS ; + } + /** make a linear extrapiolation of the state to a certain Z + * @param s1 (input) state to be extrapolated + * @param newZ (input) z-position + * @param s2 (output) extrapoalted state + * @return status code + */ + inline StatusCode propagate + ( const LHCb::State& s1 , + const double newZ , + LHCb::State& s2 ) + { + // copy the state + s2 = s1 ; + // propagate it + return propagate ( s2 , newZ ) ; + } + /** make a linear extrapolation of the state to a certain 3D-plane + * @param state (input/output) state to be extrapolated + * @param plane (input) plane + * @return status code + */ + inline StatusCode propagate + ( LHCb::State& state , + const Gaudi::Plane3D& plane ) + { + typedef Gaudi::Math::Line<Gaudi::XYZPoint,Gaudi::XYZVector> Line ; + // construct the line form the state + const Line line = Line( state.position() , state.slopes () ) ; + Gaudi::XYZPoint point ; + double mu = 0 ; + // find the interseciton of the line with plane + if ( !Gaudi::Math::intersection ( line , plane , point , mu ) ) + { return StatusCode::FAILURE ; } + // propagate to a certain Z + return propagate ( state , point.Z() ) ; + } + /** make a linear extrapolation of the state to a certain 3D-plane + * @param s1 (input) state to be extrapolated + * @param pl (input) plane + * @param s2 (output) extrapoalted state + * @return status code + */ + inline StatusCode propagate + ( const LHCb::State& s1 , + const Gaudi::Plane3D& pl , + LHCb::State& s2 ) + { + // copy the state + s2 = s1 ; + // propagate it + return propagate ( s2 , pl ) ; + } + } +} + +// ============================================================================ +// The END +// ============================================================================ +#endif // LINEAR_H +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/ToString.h b/CaloFuture/CaloFuturePIDs/src/ToString.h new file mode 100644 index 0000000000000000000000000000000000000000..f7e987254ebef3033d0ce5dbc720724b13f6aa6f --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/ToString.h @@ -0,0 +1,27 @@ +// ============================================================================ +#ifndef CALOFUTUREPIDS_TOSTRING_H +#define CALOFUTUREPIDS_TOSTRING_H 1 +// ============================================================================ +// Include files +// ============================================================================ +// STD & STL +// ============================================================================ +#include <vector> +#include <sstream> +#include "GaudiKernel/ToStream.h" +// ============================================================================ +namespace Gaudi +{ + namespace Utils + { + inline std::string toString ( const std::string& o ) + { return "\"" + o + "\"" ; } + } // end of namespace Utils +} // end of namespace Gaudi +// ============================================================================ + +// ============================================================================ +// The END +// ============================================================================ +#endif // CALOFUTUREPIDS_TOSTRING_H +// ============================================================================ diff --git a/CaloFuture/CaloFuturePIDs/src/ToVector.h b/CaloFuture/CaloFuturePIDs/src/ToVector.h new file mode 100644 index 0000000000000000000000000000000000000000..538fc148d082100f00af167ddfac9f4d35517996 --- /dev/null +++ b/CaloFuture/CaloFuturePIDs/src/ToVector.h @@ -0,0 +1,41 @@ +// ============================================================================ +#ifndef CALOFUTUREPIDS_TOVECTOR_H +#define CALOFUTUREPIDS_TOVECTOR_H 1 +// ============================================================================ +// Include files +// ============================================================================ +// STD & STL +// ============================================================================ +#include <vector> +#include <type_traits> +#include <string> +// ============================================================================ +// Local +// ============================================================================ +#include "ToString.h" +// ============================================================================ + +namespace Gaudi +{ + namespace Utils + { + // ======================================================================== + template <typename... TYPE> + std::vector<typename std::common_type<TYPE...>::type> toVector( const TYPE&... o ) + { return { o... }; } + // ======================================================================== + + // ======================================================================== + template <typename... TYPE> + std::string toString( const TYPE&... o ) + { return toString( toVector( o... ) ) ; } + // ======================================================================== + + } // end of namespace Utils +} // end of namespace Gaudi + +// ============================================================================ +// The END +// ============================================================================ +#endif // TOVECTOR_H +// ============================================================================ diff --git a/CaloFuture/CaloFutureReco/CMakeLists.txt b/CaloFuture/CaloFutureReco/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..468b2640d250d44fbfb926accf532eb0aa6bf3b3 --- /dev/null +++ b/CaloFuture/CaloFutureReco/CMakeLists.txt @@ -0,0 +1,24 @@ +################################################################################ +# Package: CaloFutureReco +################################################################################ +gaudi_subdir(CaloFutureReco v5r28) + +gaudi_depends_on_subdirs(CaloFuture/CaloFutureDAQ + CaloFuture/CaloFutureInterfaces + CaloFuture/CaloFuturePIDs + CaloFuture/CaloFutureUtils + Kernel/Relations) + +find_package(Boost) +find_package(ROOT) +include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS}) + +gaudi_add_module(CaloFutureReco + src/*.cpp + INCLUDE_DIRS CaloFuture/CaloFutureDAQ + LINK_LIBRARIES CaloFutureUtils RelationsLib) + +gaudi_install_python_modules() + +gaudi_env(SET CALOFUTURERECOOPTS \${CALOFUTURERECOROOT}/options) + diff --git a/CaloFuture/CaloFutureReco/doc/release.notes b/CaloFuture/CaloFutureReco/doc/release.notes new file mode 100755 index 0000000000000000000000000000000000000000..0c2ee2ef0314eb8b21bca44024e544b9c19d2ac7 --- /dev/null +++ b/CaloFuture/CaloFutureReco/doc/release.notes @@ -0,0 +1,1277 @@ +! ----------------------------------------------------------------------------- +! Package : CaloFuture/CaloFutureReco +! Responsible : Olivier Deschamps odescham@in2p3.fr +! Purpose : Main Package for CaloFuturerimeter Reconstruction Software +! ----------------------------------------------------------------------------- + +! 2017-08-10 - O.Deschamps + - reduce verbosity in CaloFutureShowerOverlapTool and CaloFutureECorrection (HLT request) + +! 2016-08-16 - Olivier Deschamps + - implement counter() switch based on FutureCounterLevel tool + - Configurable : propagate counter() switch to all CaloFuture sequences + - CaloFutureCorrectionBase : CaloFuture HLT Speed update (from G. Raven - see LHCBPS-1620) + + -06-04 - Olivier Deschamps + - CaloFutureCorrectionBase : add protection to avoid repeated Condition registration when running TCK in Moore + + +!========================= CaloFutureReco v5r28 2016-03-17 ========================= +! 2016-03-05 - Olivier Deschamps + - CaloFutureProcessor configurables : add slots to configure the Accepted Track::Types at CaloFuturePID level + +! 2016-02-25 - Olivier Deschamps + - fix a clang warning + +! 2016-02-24 - Olivier Deschamps + - fix clang warning in friend declarations of ToolFactory (class->struct) + +! 2016-02-18 - Olivier Deschamps + - CaloFutureMergedPi0 : replace setOuputLevel with setProperty("OutputLevel", ...) to please Gaudi_HEAD + +! 2016-02-17 - Olivier Deschamps + - Configuration.py : - fix : propagate cluster mask to SplitClusters + - revert change done in 2015-12-05 : the exception handling to check TES was done on purpose - to avoid triggering the splitcluster onDemand with another instance + of the same algorithm ! + + +! 2016-02-02 - Olivier Deschamps + - Fix EnergyTags & PositionTags property setting in configurable. + +!========================= CaloFutureReco v5r27 2016-01-28 ========================= +! 2015-12-16 - Marco Cattaneo + - CaloFutureCorrectionBase.cpp: add workaround to prevent wierd FPE with clang + +! 2015-12-05 - Gerhard Raven + - avoid the use of exception handling to find out whether there already is an + object on the TES... + +!========================= CaloFutureReco v5r26 2015-10-23 ========================== + +! 2015-10-16 - Olivier Deschamps + - python configurable : propagate same Et threshold for mergedPi0 and for splitCluster production + +!========================= CaloFutureReco v5r25p1 2015-10-13 ========================= +! 2015-08-12 - Gerhard Raven + - remove #include of obsolete Gaudi headers + +!========================= CaloFutureReco v5r25 2015-04-21 ========================= +! 2015-04-15 - Olivier Deschamps + - python/CaloFutureReco/Configuration : in CaloFutureProcessor : give CaloFutureProcessor-name-dependent naming for the neutralProtoPAlg + +!========================= CaloFutureReco v5r24 2015-03-31 ========================= +! 2015-03-30 - Olivier Deschamps + - python/CaloFutureReco/Configuration : in CaloFutureProcessor : give CaloFutureProcessor-name-dependent naming for the algorithms updating charged ProtoP + +! 2015-03-29 - Roel Aaij + - Fix bad assert. + +! 2015-03-26 - Gerhard Raven + - CaloFutureCorrectionBase::getParams: + o don't create an empty vector if it won't be needed + o cache counters by (type, areaName) instead of creating a string containing + both every single time, and then looking them up by string + This reduces the # of calls to new/delete in the HLT by ~10% (!), and speeds up + the HLT (in its preliminary 2015 configuration) by ~1%. + +!========================= CaloFutureReco v5r23 2015-02-23 ========================= +! 2015-01-21 - Daria Savrina + - Corrected a typo in CaloFuture/CaloFutureReco/python/CaloFutureReco/Reconstruction.py, line 160 + (there were too few arguments to format a string) + +! 2015-01-15 - Olivier Deschamps + - CaloFutureCorrectionBase : add boolean method to flag condition update (hasConditionChanged()) + - FutureClusterCovarianceMatrixTool : update parameters via BeginEvent incident only when condition changed + +!========================= CaloFutureReco v5r22 2014-12-11 ========================= +! 2014-11-26 - Marco Cattaneo + - Fix unprotected debug in CaloFutureSCorrection.cpp + +!========================= CaloFutureReco v5r21p1 2014-09-28 ========================= +! 2014-09-28 + - CaloFutureMergedPi0 : fix bug that affect sub-seed definition in some configuration + - Configuration.py : decrease MergedPi0Pt threshold from 2 GeV to 1.5 GeV + (applies on cluster pT before merged hypothesis is fully reconstructed) + +!========================= CaloFutureReco v5r21 2014-09-08 ========================= +! 2014-08-22 - Gerhard Raven + - various CPU performance improvements. + +! 2014-07-26 - Dima Golubkov + - CaloFutureECorrection.cpp, CaloFutureSCorrection.cpp : correct defaults for missing correction functions in CondDB and add more protection + +! 2014-07-23 - Olivier Deschamps for Dima + - CaloFutureCorrectionBase/CaloFutureECorrection/CaloFutureSCorrection : implement correction propagation to Covariance + + +!========================= CaloFutureReco v5r20 2014-07-14 ========================= +! 2014-07-11 - Olivier Deschamps + - CaloFutureECorrection/CaloFutureCorrectionBase : add energy offset correction (allowing sin(theta) dependency to have transverse energy correction) + + +! 2014-07-08 - Olivier Deschamps + - CaloFutureECorrection : fix unapplied correction + +! 2014-07-08 - Olivier Deschamps + - CaloFutureCorrectionBase/CaloFutureECorrection : add possible non-linear dependency to Prs corrections + +! 2014-07-03 - Olivier Deschamps + - FutureClusterCovarianceMatrixTool : allow for covariance parametrization per CaloFuture area - improve DB access + - FutureSubClusterSelectorTool : improve DB access + - add Hcal default settings for Jet-related reconstruction + +! 2014-07-02 - Olivier Deschamps + - CaloFutureShowerOverlapTool : add protection in case of missing ShowerProfile + - CaloFutureMergedPi0 : add minimal ET cut on splitPhoton (applied to both cluster and corrected CaloFutureHypo) + - CaloFutureXCorrection : skip correction in case of negative energy + +! 2014-07-01 - Olivier Deschamps + - Photon/Electron/MergedPi0 CaloFutureHypos : skip CaloFutureHypos with negative energy (if any) + +! 2014-06-30 - Olivier Deschamps + - Reconstruction.py : skip single-cell "clusters" for CaloFutureHypo building + - CaloFutureSelectCluster : add a cut on entries.size() + - CaloFutureMergedPi0 : fix property name causing a crash in Moore + +! 2014-06-30 - Marco Cattaneo + - fix verbosity of CaloFuture{L,E,S}Correction.cpp constructor + +! 2014-06-30 - Olivier Deschamps + - fix electronPt/photonPt cluster thresholds for CaloFutureHypo production + +! 2014-06-29 - Olivier Deschamps + - fix default parameters for Covariance estimation + +! 2014-06-29 - Olivier Deschamps + - fix FPE's, compilation warnings & verbosity excess + +! 2014-06-27 - Olivier Deschamps + - add new specific ClusterSelector's : FutureSubClusterSelector2x2 , FutureSubClusterSelectorSwissCross.h + - and a generic tool to access condDB and tag the clusters : FutureSubClusterSelectorTool.h + - src/CaloFutureShowerOverlapTool : new tool to substract overlap energy in cluster pair (note : CaloFutureSharedCellAlg.cpp is now obsolete) + - src/CaloFutureMergedPi0 & CaloFutureShowerOverlap : mergePi0 reconstruction and ClusterOverlap based on the above tool (note : CaloFutureMergedPi0Alg is now obsolete) + + - adapt to change in cluster masking : CaloFutureClusterizationTool, FutureSubClusterSelectorBase, CaloFutureClusterCovarianceAlg, FutureSubClusterSelector3x3, FutureClusterCovarianceMatrixTool + - CaloFutureCorrectionBase : map new corrections and implement generic DB access for cluster masks + - CaloFutureSCorrection.cpp : add new Alexis' correction + + - python/CaloFutureReco/Configuration.py : new slots to select cluster masks : ClusterEnergyMasks and ClusterPositionMasks (default : get mask setting from DB) + - python/CaloFutureReco/Reconstruction.py : propagate masks to ClusterCovariance , ClusterOverlap & MergedPi0 + : use CaloFutureMergedPi0 (replacing the now obsolete CaloFutureMergedPi0Alg) + : use CaloFutureShowerOverlap (replacing the now obsolete CaloFutureSharedCellAlg) + + + +!========================= CaloFutureReco v5r19 2014-03-18 ========================= +! 2014-03-06 - Olivier Deschamps + - python/Configuration.py : propagate OutputLevel value to calo sequences only when the property is explicity set + +! 2014-03-05 - Olivier Deschamps + - python/Configuration.py : dactivate Spd/Prs Decoders in DecoderDB when noSpdPrs=True + - add DAQSys dependency + +! 2014-02-27 - Olivier Deschamps + - CaloFutureMergedPi0Alg : remove default tools property triggering Prs/Spd decoding + +!========================= CaloFutureReco v5r18 2013-12-10 ========================= +! 2013-10-30 - Olivier Deschamps + - python/CaloFutureReco/Configuration.py : fix typo in CaloFutureLines method. + +!========================= CaloFutureReco v5r17 2013-10-24 ========================= +! 2013-10-09 - Olivier Deschamps + - python/CaloFutureReco/*.py : + - possibility to set-up a configuration without active Spd/Prs (NoSpdPrs = <False> flag) + - configure the caloReco/Pids algorithms in order they don't access Prs/Spd detectorElement nor Digits + - remove any component related to Prs/Spd in the reconstruction sequence : + digits decoding via CaloFutureDigitsConf, cluster filtering, photonID, pi0/gamma separation, neutral/charged ID + - NoSpdPrs flag propagated to CaloFuturePIDs configuration via CaloFutureProcessor and CaloFutureDigitsConf configured with [Ecal,Hcal] only + + - src/CaloFutureMergedPi0AlgAlg : protect against accessing Prs/Spd digits when they don't exist + +!========================= CaloFutureReco v5r16p1 2013-06-03 ======================= +! 2013-05-27 - Marco Cattaneo + - Fix clang32 warnings + +!========================= CaloFutureReco v5r16 2012-11-28 ========================= +! 2012-11-22 - Marco Clemencic + - Added CMake configuration file. + +! 2012-10-08 - Marco Cattaneo + - In Brunel.opts, remove setting of MeasureTime=true in sequencers, + should not be the default, and should in any case use TimingAuditor. + +! 2012-10-08 - Olivier Deschamps + - fix coverity problems + +!========================= CaloFutureReco v5r15 2012-06-25 ========================= +! 2012-06-24 - Olivier Deschamps + - FutureClusterCovarianceMatrixTool : get covariance parameters from condDB when + available + +! 2012-06-23 - Olivier Deschamps + - CaloFutureMergedPi0Alg : add covariance matrix for SplitClusters & SplitPhotons + (assume no correlation) + - CaloFutureECorrection : allow spd-dependent PileUp subtraction + +! 2011-12-10 - Olivier Deschamps + - Configurable CaloFutureLine : add ClusterizationLevel tag for L0CaloFuture2CaloFuture + (set to 2 by default) + +!========================= CaloFutureReco v5r14 2012-02-28 ========================= +! 2012-02-27 - Marco Cattaneo + - CaloFutureMergedPi0Alg: Fix potential memory leak, probably never fired + (Coverity defect 17572) + - Fix UNINIT_CTOR defects + - Fix trivial icc remarks + +!========================= CaloFutureReco v5r13 2011-11-26 ========================= +! 2011-11-25 - Olivier Deschamps + - CaloFutureMergedPi0Rec : fix abusive 'return 0' + +!========================= CaloFutureReco v5r12 2011-08-29 ========================= +! 2011-08-27 - Olivier Deschamps + - fix tracks list reset in CaloFutureProcessor.XXSequence when called from CaloFutureLines + - python/Configuration.py : remove dependency on GlobalRecoConf (was producing loop in configurable). + TrackTypes & TrackCuts is now private property with the same default + as in GlobalRecoConf so far + + +!========================= CaloFutureReco v5r11 2011-07-27 ========================= +! 2011-07-27 - Marco Cattaneo + - Protect unprotected MSG::DEBUG, also using UNLIKELY macro + +! 2011-07-08 - Albert Puig + - python/Configuration.py : correctly propagate track locations in CaloFutureLines. + +! 2011-07-04 - Olivier Deschamps + - python/Configuration.py : apply default GlobalRecoConf settings for + chargedProtoPMaker (when activated on-demand in CaloFutureProcessor) + +!========================= CaloFutureReco v5r10 2011-06-15 ========================= +! 2011-06-06 - Olivier Deschamps + - python/Configuration.py : consolid sequencer() methods + new configurable : CaloFutureLines for HLT fast reconstruction + + - src/CaloFutureClusterizationTool : limit the number of clusterization pass to 10 + +! 2011-05-16 - Olivier Deschamps + - CaloFutureClusterizationTool : fix interfacing with L0CaloFuture2CaloFutureTool + +! 2011-05-09 - Olivier Deschamps + - fix protoP maker DoD in CaloFutureProcessor (no DoD setting by default) + +!========================= CaloFutureReco v5r9p1 2011-05-09 ========================= +! 2011-05-09 - Gerhard Raven + - do not check Hlt context, but honour the EnableOnDemand property of the + Configurable instead (i.e. as it was in v5r8!) + +! 2011-05-09 - Roel Aaij + - Add check for Hlt context before adding to DoD in CaloFutureProcessor. + +!========================= CaloFutureReco v5r9 2011-04-27 ========================= +! 2011-04-24 - Olivier Deschamps + - update CaloFutureProcessor configurable with 'MakeExternalClustersWithTag' slot + +! 2011-04-24 - Olivier Deschamps + - update CaloFutureProcessor configurable with 'ExternalClusters' slot + +!========================= CaloFutureReco v5r8p1 2011-01-28 ======================== + +! 2011-02-23 - Olivier Deschamps + - CaloFutureCorrectionBase : add missing protection + - remove obsolete CellularAutomaton.cpp + +! 2011-02-17 - Olivier Deschamps + - clean CaloFutureClusterisationTool + - remove obsolete CellularAutomaton.cpp + +! 2011-02-17 - Marco Clemencic + - Fixed an infinite loop with associated memory leak. + +! 2011-02-17 - Chris Jones + - Some trivial coverity and icc fixes + +! 2011-07-02 - Olivier Deschamps + - CaloFutureECorrection : cluster energy offset via CaloFutureDAQ/ICaloFutureDigitFilterTool + - Add : digit masking/offset in Cluster sequence (Brunel.opts/Reconstruction.py) + - Add : Et threshold in cluster selection for hypo building + - few protections here and ther requirements : add depencency on CaloFutureUtils + +!========================= CaloFutureReco v5r8 2011-01-17 ======================== + +- 2010-12-20 - Olivier Deschamps + - reduce verbosity and fix untested StatusCode + +- 2010-12-16 - Olivier Deschamps : + - Update CaloFutureCorrectionBase to handle S/L-corrections + ShowerProfile parametrisation from condDB + - Update CaloFutureSCorrection, CaloFutureLCorrection and CaloFutureMergedPi0Alg to get parameters from DB. + - updates options/python accordingly + +!========================= CaloFutureReco v5r7p1 2010-10-28 ========================= +- 2010-10-15 - Olivier Deschamps : + - Clean obsolete options file + + +!========================== CaloFutureReco v5r7 2010-09-24 ======================= +- 2010-09-24 - Olivier Deschamps : + - Uncomment correction + +- 2010-09-23 - Olivier Deschamps : + - SinglePhotonAlg : fix typo in default setting + +- 2010-09-23 - Olivier Deschamps : + - CaloFutureCorrection : + - add new functions in CaloFutureCorrectionBase + - adapt CaloFutureLCorrection to the new correction framework (adapt options and configurable) + - CaloFutureECorrection : allow for beta_prs dependency with energy + + +! 2010-09-20 - Olivier Deschamps + - CaloFutureMergedPi0Alg : fix window compilation warning + +! 2010-09-03 - Olivier Deschamps + - Configuration.py : fix interference between unpack/calo sequence DoD setting + - CaloFutureMergedPi0Alg : paranoid protection against already existing SplitCluster container + +! 2010-08-27 - Olivier Deschamps + - CaloFutureMergedPi0Alg : add extraDigit tool to both mergedPi0 and splitPhotons + update python/Reconstruction.py (and old style options) + +!========================== CaloFutureReco v5r6 2010-06-01 ======================= +! 2010-08-17 - Olivier Deschamps + - python/Configuration.py : CaloFutureProcessor adapted to change in CaloFuturePIDs (PIDList) + consolidation of the configurables + + +!========================== CaloFutureReco v5r5p2 2010-06-01 ======================= +! 2010-06-01 - Gerhard Raven + - suppress printout of another error from CaloFutureClusterCovarianceAlg, but keep + summary at the end of the job + +!========================== CaloFutureReco v5r5p1 2010-05-27 ======================== +! 2010-05-27 - Olivier Deschamps + - CaloFutureCorrectionBase : reduce verbosity + +! 2010-05-26 - Olivier Deschamps + - python/Configuration.py : set correctly the charged protop location in combinedProtoP algo + +!========================== CaloFutureReco v5r5 2010-05-21 ======================== +! 2010-05-21 - Olivier Deschamps + - python/Configuration.py : full protoP reprocessing (incl. combination) in protoSequence + +! 2010-05-20 - Olivier Deschamps + + - CaloFutureCorrectionBase : new base algorithm for CaloFutureCorrections (access to dataBase, handling parameters) + - adapt CaloFutureECorrection.h/cpp : use (new) condDB table for correction parameters - if not use options driven parametrization + - adap CaloFutureECorrection.opts & python/Correction.py to the new property syntax + + - so far options contains parametrization for MC data. Data correction should be defined via new table in condDB. + - TODO : + - adapt CaloFutureSCorrection and CaloFutureLCorrection accordingly + - review parametrization for MC2010 + - adapt CaloFutureMergedPi0Rec parametrization + + + - CaloFutureSelect** tools : add summary counters + + - Brunel.opts : add missing setting for MergedID/SplitPhotonID + + - python/Configuration : fix bug in ElectronRec setting (Chi2(track-cluster) selection was not applied + --> size of CaloFutureHypo container for electron should be reduced (factor ~2 ?) + +! 2010-05-19 - Gerhard Raven + - suppress printout of error from CaloFutureClusterCovarianceAlg, but keep + summary at the end of the job (see http://savannah.cern.ch/bugs/?67077) + +! 2010-04-29 - Olivier Deschamps + - Reconstruction.py : fix splitCluster onDemand setting + - fix Brunel.opts + +!========================== CaloFutureReco v5r4p2 2010-04-09 ======================== +! 2010-03-27 - Olivier Deschamps + - add missing Prs threshold in Standalone Electron selection (CaloFutureStandaloneClusterSelection.opts) + + +!========================== CaloFutureReco v5r4p1 2010-03-31 ========================= +! 2010-03-27 - V. Gligorov + - Fix incorrect configuration of CaloFuturePIDsConf and CaloFutureDigitsConf in Configuration.py + Please see (https://savannah.cern.ch/task/index.php?12691) for futuredetails + + +!========================== CaloFutureReco v5r4 2010-03-19 ========================= +! 2010-03-13 - Olivier Deschamps + - CaloFutureSharedCellAlg : fix non-reproducible processing (additional sort -> small impact on processing time) + + +! 2010-03-10 - Olivier Deschamps + - CaloFutureProcessor CU : + - add neutralProtoSequence() + chargedProtoSequence + - all sequence() : add ProtoPrefixLocation as argument + - Context have the priority over instanceName when set. If not Context = instance + - problem with NeutralID OnDemand : neutralID activated only in CaloFuturePIDs + + + +! 2010-03-09 - Marco Cattaneo + - In requirements, add dependencies on CaloFuture/CaloFuturePIDs and CaloFuture/CaloFutureDAQ, due to + build time dependencies on CaloFuturePIDsConf and CaloFutureDigitConf in Configuration.py + +! 2010-03-08 - Olivier Deschamps + - Configurables : + - adapt to changes in CaloKernel/ConfUtils + - make all component context-dependent + - add few slots (SkipNeutral, usePrs, ...) + - new CU : + - CaloFutureProcessor() : produce CaloFutureRecoPID / CaloFuture-ProtoPUpdate / Full sequencers for a given track location(s) + - fully instantiable + - to be used for HLT2's processings + - syntax examples : + from Configurables import CaloFutureProcessor + _tracks = ['Rec/Track/Best] + CaloFutureProcessor('Repro').sequence( _tracks ) ## returns a full (Reco/Pid/ProtoUpdate) sequence for context = 'Repro' + CaloFutureProcessor('Hlt2/Fitted').caloSequence( _tracks ) ## returns the calo (Reco/Pid) sequence for context = 'Hlt2/Fitted' + CaloFutureProcessor('Hlt2').protoSequence(_tracks) ## return the proto Update sequence for context = 'Hlt2' + CaloFutureProcessor('Partial', SkipNeutrals = True , CaloFuturePIDs = False ).sequence() ## return Charged Reco only for default track locations + + + - properly configure SplitCluster on-demand + - add missing 'CaloFutureStandalone' mode + + - options : + - clean options (remove obsolete) + - add temporarly NeutralPIDs.opts (config to be passed via condD asap) + + - src : + - CaloFutureSelectCluster : add Et cut + + - TODO : + - Configurables : special Hlt's settings to speed up the processing (Cluster Et cut , Et cut of electron before track match, ...) + - CaloFutureProcessor() CU : split ProtoP update by CaloFuturePID technique (to be synchronized with CaloFuturePIDsConf) + - CellularAutomaton : EtCut + level !=0 to be active simultaneously + +!========================== CaloFutureReco v5r3 2009-11-13 ========================= +! 2009-11-13 - Rob Lambert + - Tagged v5r3 + +! 2009-11-09 - Marco Cattaneo + - In CaloFutureReco configurable, propagate OutputLevel to CaloFutureDigitConf + +! 2009-11-05 - Dmitry GOLUBKOV + - CaloFutureClusterizationTool.cpp,h : remove look_neigh(), use CaloFutureFunctors::neighbours() + +! 2009-10-30 - Dmitry GOLUBKOV + - CaloFutureClusterizationTool.cpp : fix uninitialized neighbour cell list for level=1 + +! 2009-10-27 - Vanya Belyaev + - make usage off CaloFutureDigitConf configurable to access digits + +! 2009-10-26 - Olivier Deschamps + - CaloFutureRecoOnDemand : CaloFutureDigitsSeq imported from CaloFutureDAQ + - CaloFutureElectronAlg : fix hypothesis setting (uncorrect since a while!) + +!========================== CaloFutureReco v5r2 2009-10-22 ========================= +! 2009-10-22 - Marco Cattaneo + - Fix python import problems causing errors in make + +! 2009-10-15 - Marco Cattaneo + - Remove CaloFuturePacking.py, moved to GaudiConf + +! 2009-10-10 - Vanya Belyaev + - CaloFutureReco/CaloFuturePacking.py + new function to control packing/unpacking of CaloFuturerimeter objects on DST + +! 2009-09-28 - Vanya Belyaev + - add the possibility to use both Tracks and Spd ( in *OR* mode) + as neutrality criterion for clusters + +! 2009-09-26 - Juan Palacios + - python/CaloFutureReco/Reconstruction.py + . Bug fix from Gerhard Raven: unpack the digits. + - cmt/requirements + . Increase version to v5r1p1 + +! 2009-09-17 - Olivier Deschamps + - CaloFutureStandaloneClusterSelection.opts : fix bug in Photon selection + +! 2009-09-14 - Olivier Deschamps + - Brunel.opts, HltCaloFutureSeq.opts, python/Reconstruction.py : + remove CaloFutureGetterInit/CaloFutureDigitGetter (no longer needed) + +!========================== CaloFutureReco v5r1 2009-09-04 ========================= +! 2009-09-04 - Olivier Deschamps + - remove Warning verbosity in CaloFutureElectronAlg initialize + +! 2009-09-01 - Vanya BELYAEV + - fix warnings for Configurables + - cmt/requirements + version increment to v5r1 + +!========================== CaloFutureReco v5r0 2009-08-31 ========================= +! 2009-08-21 - Olivier Deschamps + + - adapt old syntax .opts to change in CaloFutureReco (public->private tool) + - implement generic context-dependent TES I/O + +! 2009-08-13 - Chris Jones + - Add missing #include <memory> for std::auto_ptr + +! 2009-08-10 - Vanya BELYAEV + - further polishing of configurables + +! 2009-08-05 - Vanya BELYAEV + - add proper configurables for calorimetr recontruction + - version increment to v5r0 + +!========================== CaloFutureReco v4r21 2009-07-28 ========================= +! 2009-07-28 - Marco Cattaneo + - Remove obsolete file CaloFutureReco_dll.cpp + +! 2009-07-24 - Olivier Deschamps + - options/CaloFutureRecoOnDemand.opts : Add digit sequence in CaloFutureCluster-onDemand + to please HLT + +!========================== CaloFutureReco v4r20 2009-06-30 ======================= +! 2009-06-22 - Marco Cattaneo + - Remove unused m_e member from CaloFutureAutoTaggedCell. It was not initialised and + was causing FPE on slc4_ia32_gcc34_dbg + - Fix WIN32 warning about type conversion + - Replace all endreq by endmsg + - Fix untested StatusCodes when calling Warning() and Error() + +! 2009-06-17 O. Deschamps + - CelAutoTaggedCell : resurrect constructor/destructor + (without the id argument leading to warnings) + +! 2009-06-17 O. Deschamps for V. Egorychev + - CaloFutureClusterisationTool : prepare for fast HLT clusterisation + +!========================== CaloFutureReco v4r19p1 2009-05-25 ======================= +! 2009-05-10 - Vanya Belyaev + - FutureClusterSpreadTool.cpp + add (debug) printout of counters for spread-corrected clusters + + - cmt/requirements + version increment to v4r19p1 + +!========================== CaloFutureReco v4r19 2009-05-08 ========================= +! 2008-04-17 - Olivier Deschamps + - new alg CaloFutureGetterInit : create a public instance of CaloFutureGetterTool + (from CaloFutureTools) and process the event-update + - Brunel.opts/HltCaloFutureSeq.opts : add CaloFutureGetterInit in the reconstruction + sequence to have fast access to CaloFutureDigits + +! 2009-04-16 - Olivier Deschamps + - fix minor bug in HltClusterSelection.opts + adapt to change in CaloFutureTools + - CaloFutureClusterisationTool : reduce verbosity + +!========================== CaloFutureReco v4r18 2009-03-11 ========================= +! 2009-03-11 - Marco Cattaneo + - Added file CaloFuturePIDs-DC06.opts, for DC06 pdf histograms + - Brunel.opts no longer includes CaloFuturePIDs.opts. Instead, RecSysConf includes + either CaloFuturePIDs.opts or CaloFuturePIDs-DC06.opts + +! 2009-03-11 - Victor Egorychev + - CaloFuturePIDs_DC09_v1.root file with new PDF for DC09 in BrunelPID.opts and CaloFuturePIDs.opt + +! 2009-03-10 - Marco Cattaneo + - Clean up messages in CaloFutureMergedPi0Alg: + . Protect debug() with MsgLevel(MSG::DEBUG) + . Fix untested status codes from Warning() and Error() + . Replace endreq with endmsg + +! 2009-03-10 - Olivier Deschamps + - Fix FPE occurring in CaloFutureMergedPi0Alg (missing initialization) + +! 2009-03-09 - Olivier Deschamps + - options/CaloFutureECorrectionParam.opts : 2nd iteration of DC09 tuning (Ecorrection for electron from e/p) + +! 2009-03-05 - Olivier Deschamps + - options/CaloFutureECorrectionParam.opts : preliminary DC09 tuning + - options/UnpackCaloFutureHypoOnDemand.opts : new options to unpack packed CaloFutureHypo on-demand (same as done in DstConf.py) + +!========================== CaloFutureReco v4r17p1 2009-02-12 ======================= +! 2009-02-12 - Marco Cattaneo for Vanya + - Fix FPE occurring in CaloFutureClusterizationTool on ia32 only + - Fix some doxygen warnings + +!========================== CaloFutureReco v4r17 2009-01-12 ========================= +! 2009-01-09 Olivier Deschamps + - FutureCellularAutomatonAlg.cpp : put cluster container before cluster is sorted - + to be bakward compatible with CellularAutomaton (-> if not trouble with calo + MC-association for DC06 data reconstruced with CellularAutomaton) + - options/Brunel.opts : remove CaloFutureClusterCorrect3x3Position/EcalPosition + (obsolete, handled by the clusterisation) + - options/HltCaloFutureSeq.opts + . use FutureCellularAutomatonAlg as default clusterisation algorithm + (as already done for offline sequence) + . remove obsolete CaloFutureClusterCorrect3x3Position/EcalPosition + (handled by the clusterisation) + - options/(Hlt)ClusterSelection.opts : add default protection against negative + cluster energy ( e > threshold = 0 ) + +! 2008-10-02 - Olivier Deschamps + - fix typo in (HLT)MergedPi0Rec.opts + +!========================== CaloFutureReco v4r16 2008-10-02 ========================= +! 2008-10-02 - Olivier Deschamps + - fix bad setting in HltClusterSelection.opts + +! 2008-09-14 - Olivier Deschamps + - new cluster selection tools : + - CaloFutureSelectCluster : cluster selection with energy and #entries + - CaloFutureSelectClusterWithPrs : cluster selection with Prs energy and multiplicity + - CaloFutureSelectNeutralClusterWithSpd : cluster selection with Spd hits multiplicity + - CaloFutureSelectNeutralClusterWithTracks (replace CaloFutureSelectNeutralCluster) + - CaloFutureExtraDigits : use of the new CaloFutureHypo2CaloFuture tool (located inCaloFutureTools) + as CaloFutureSelectClusterWithPrs & CaloFutureSelectNeutralClusterWithSpd + Bonus : the matching now takes the actual calo alignment into account + + - CaloFutureElectronAlg : remove hardcoded Prs/Spd criteria (use selection tool instead) + + - CellularAutomaton & FutureCellularAutomatonAlg & CaloFutureClusterizationTool : + - fix problem of incomplete clusteriwation due to rare digits configuration + - add statistics printout in finalize() + - complete FutureCellularAutomatonAlg (Level property + missing HLT/CaloFuture context) + - include the possibility to select digit for energy computation using + CaloFutureUtils/CellSelector (mask by options) : default '3x3' mask + --> CaloFutureClusterCorrect3x3Energy in principle obsolete. + Could be remove from options (To be checked) + + - FutureCellularAutomatonAlg is now the default in Brunel options (and on-Demand) + and replace 'CellularAutomaton' everywhere + (obsolete now and to be remove in the next release) + + - new options : + - (Hlt)ClusterSelection.opts : based on tracks (default) + - CaloFutureStandaloneClusterSelection.opts : based on Prs/Spd + - CaloFutureStandalonePartialReco.opts : partial reco (no pid) to be used for commissioning + - remove ExtraDigits.opts (default setting now in CaloFutureTools/CaloFutureHypo2CaloFuture) + - Et(cluster)>2GeV is now the default for offline MergedPi0 reconstruction (as for Hlt) + + - adapt here and there to change in CaloFutureUtils & CaloFutureTools + +!========================== CaloFutureReco v4r15 2008-09-04 ========================= +! 2008-08-14 - Olivier Deschamps + - HltCaloFutureSeq.opts : CaloFutureDigits created via the on-Demand service to avoid + conflict with offline processing. + +!========================== CaloFutureReco v4r14 2008-07-18 =================== +! 2008-07-18 - Olivier Deschamps + - make the Hlt stream fully independent of the offline sequence in options/ + - fix missing prefix in CaloFutureOnDemand.opts + +!========================== CaloFutureReco v4r13 2008-07-02 =================== +! 2008-06-27 - Olivier Deschamps + - use default HLT locations for the HLT context in all algorithm/tool + - Set default location to run the clusterisation sequence on Hcal (depends on the instance name) + - new options : HltCaloFutureSeq with setting to run the Reco/PID within HLT framework + +! 2008-06-06 - Victor Egorychev + - Fix id warning in CelAutoTaggedCell.h + - version was increased + +!========================== CaloFutureReco v4r12 2008-06-04 =================== +! 2008-06-04 - Marco Cattaneo + - Fix doxygen warning + +! 2008-06-03 Olivier Deschamps + - change incident type EndEvent to BeginEvent in CaloFutureSelectNeutralCluster.cpp + and CaloFutureExtraDigits.cpp + +!========================== CaloFutureReco v4r11 2008-04-22 =================== +! 2008-04-22 - Marco Cattaneo + - In CaloFutureRecoOnDemand.opts, replace DataOnDemandSvc.Algorithms with .AlgMap + +! 2008-04-21 - Victor Egorychev + - New FutureCellularAutomatonAlg.cpp and CellularAtomatonAlg.h were added + - New CaloFutureClusterizationTool.cpp and CaloFutureClustrerizationTool.h were added + - version was increased + +!========================== CaloFutureReco v4r10 2007-12-20 =================== +! 2007-12-19 - Olivier Deschamps + - Fix unprotected array index in CaloFutureMergedPi0.cpp + (causes an infinite loop when running in debug mode on amd64) + +!========================== CaloFutureReco v4r9 2007-09-20 =================== +! 2007-08-24 - Olivier Deschamps + - Fix the unchecked StatusCodes + +!========================== CaloFutureReco v4r8 2007-05-26 =================== +! 2007-05-26 - Victor Egorychev + - options/Brunel.opts, options/BrunelPIDs.opts + - added new DLL hist for CaloFuture PIDe/mu (CaloFuturePIDs_DC06_v2.root) in ECAL, HCAL, Prs + and Brem + - cmt/requirement + version increment to v4r8 + +!========================== CaloFutureReco v4r7 2007-03-05 ========================== +! 2007-03-05 - Marco Cattaneo + - Remove LHCbDefinitions includes + - Remove obsolete CaloFutureReco_load.cpp file + - Remove obsolete ApplicationMgr.DLLs option + +!========================== CaloFutureReco v4r6 2006-12-01 ========================== +! 2006-12-01 - Olivier Deschamps + - update CaloFutureECorrection.cpp & CaloFutureECorrectionParam.opts for electron calibration + +! 2006-11-28 - Marco Cattaneo + - use DECLARE_xxx_FACTORY macros + - Remove unneccessary GaudiKernel includes + +! 2006-11-28 - Olivier Deschamps + - update CaloFutureMergedPi0Alg and CaloFutureXCorrection tools + - update MergedPi0Rec.opts + - DC06 tuning for merged pi0 + - version increment to v4r6 + +!========================== CaloFutureReco v4r5 2006-11-06 =================== +! 2006-11-06 - Victor Egorychev + - options/Brunel.opts, options/BrunelPIDs.opts + - added new DLL hist for CaloFuture PIDe/mu (CaloFuturePIDs_DC06_v1.root) in ECAL, HCAL, Prs + for different types of tracks + - old hist for Brem PIDe (CaloFuturePIDs.root) + - cmt/requirement + version increment to v4r5 + +! 2006-10-27 - Olivier Deschamps + - Preliminary setting for DC06 (CaloFutureECorrections.opts) + - fix Cluster CaloFuturePosition in CaloFutureMergedPi0Alg.cpp + (was undefined when cluster on-Demand is requested). + +!========================== CaloFutureReco v4r4 2006-10-17 =================== +! 2006-10-17 - Olivier Deschamps + - fix CaloFutureMergedPi0Alg +! 2006-10-13 - Olivier Deschamps + - Modify CaloFutureMergedPi0Alg to allow the separate creation of CaloFutureClusters and CaloFutureHypos + - Add DVCaloFutureRecoOnDemand.opts : CaloFutureDigits and CaloFutureClusters on-Demand for DaVinci usage + +!========================== CaloFutureReco v4r3 2006-09-08 =================== +! 2006-09-07 - Olivier Deschamps + - Remove CaloFutureBank.opts (moved to CaloFutureDAQ as CaloFutureBanksHandler.opts) + +!========================== CaloFutureReco v4r2 2006-07-19 =================== +! 2006-07-19 - Marco Cattaneo + - Fix constructor in CaloFutureClusterCorrect3x3Position, for Gaudi v18r6 + - Fix Brunel.opts for pedantic new options parser + +! 2006-07-18 - Olivier Deschamps + - Fix SVector constructor in CaloFutureClusterCorrect3x3Position.cpp + +!========================== CaloFutureReco v4r1 2006-06-28 =================== +! 2006-06-27 - Olivier Deschamps + - 3rd step of the migration towards DC06 software : repackaging + - remove obsolete tools (CaloFuture-Track matching stuff rewritten in CaloFuturePIDs) + - move CaloFutureSingleGammaTool/CaloFuturePhotonEstimatorTool to CaloFuturePIDs/ + - adapt to change in RecEvent (enums) + - simplify the dependency in cmt/requirements (remove TrackXX/LHCbMath dependency) + - increment the release number in cmt/requirements + +!========================== CaloFutureReco v4r0 2006-06-22 =================== +! 2006-06-21 - Vanya BELYAEV + - introduce a bit more hierarchy into CaloFuture-sequence. + +! 2006-06-20 - Olivier Deschamps + - new CaloFutureReco/CaloFuturePIDs sequence in Brunel.opts + - add options/UseForwardTracksOnly.opts + - THERE ARE OBSOLETE TOOLS SINCE NEW CALOFUTUREPIDS IS AVAILABLE + WILL BE REMOVED IN NEXT RELEASE. + +! 2006-06-14 - Olivier Deschamps + - 2nd step of the migration towards DC06 software : cleaning + debugging + - Adapt to changes in LHCb v21r1 + - re-implement CaloFutureSinglePhotonAlg tools required by NeutralProtoPAlg + - add temporarly CaloFuturePhotonEstimatorTool (moved from CaloFuturePID) + options/PhotonPDF.opts + in order NeutralProtoPAlg can run work without CaloFuturePID. + - increment release number in cmt/requirements + - Final version to be reelased with next CaloFuturePID version. + +! 2006-05-29 - Olivier Deschamps + - first step of the migration towards DC06 software. + - package adapted to new Event Models, new MathLib, 1MHW DAQ, ... + - Cleaning of obsolete tools/algorithms + +!========================== CaloFutureReco v3r0 2005-11-04 =================== +! 2005-11-04 - Olivier Deschamps + - Adapt to new Track Event Model (TrackEvent v1r4) + + modified file : + src/CaloFutureTrackMatchPhoton.h + src/CaloFutureTrackMatchElectron.h + src/CaloFutureTrackMatchBremm.h + src/CaloFutureTrackMatchBrem2.h + src/CaloFutureTrackMatchBase.cpp + src/CaloFutureSelectNeutralCluster.h + src/CaloFutureCluster2TrackAlg.cpp + src/CaloFutureHypo2TrackAlg.cpp + + - cmt/requirements + version increment to v3r0 +!============================ CaloFutureReco v2r9 2005-06-02 ======================== +! 2005-06-02 - Marco Cattaneo + - Adapt Brunel.opts to new phase name Reco instead of BrunelReco + +!=========================== CaloFutureReco v2r8p2 2005-05-24 ======================= +! 2005-05-24 - P. Koppenburg + - options/CaloFutureReCorrections.opts + . New options: Moved from DaVinci + +!=========================== CaloFutureReco v2r8p1 2005-05-24 ======================= +! 2005-05-24 - P. Koppenburg + - options/CaloFutureRecoOnDemand.opts + . Fix typo in /Event/Rec/CaloFuture/ElectronMatch (no "n") + +!=========================== CaloFutureReco v2r8 2005-05-09 ========================= +! 2005-05-06 - Vanya BELYAEV + + - src/CaloFutureTrackAlg.h src/CaloFutureTrackAlg.cpp, + files are moved into CaloFuture/CaloFutureUtils package + + - src/CaloFutureCluster2TrackAlg.h, + remove this file + + - src/CaloFutureHypo2TrackAlg.h, + src/CaloFutureCluster2TrackAlg.cpp + files are updated for new location of CaloFutureTrackAlg.h + and removal of src/CaloFutureCluster2TrackAlg.h + + - options/CaloFutureRecoOnDemand.opts + the prototype (INVALID NOW) for future "CaloFuture-Reco-On-Demand" + + - cmt/requirements + version incremement to v2r8 + +!========================= CaloFutureReco v2r7p1 2005-03-07 ================== +! 2005-03-07 - Marco Cattaneo + - Fix many doxygen warnings + +! 2005-02-17 - Vanya BELYAEV + - options/NeutralCluster.opts + - options/ChargedCluster.opts + fix for new associators + - cmt/requirements + version incement to v2r7p1 + +!========================== CaloFutureReco v2r7 2004-12-13 =================== +! 2004-12-13 - Marco Cattaneo + - Fix some doxygen warnings + +! 2004-12-10 - Ivan BELYAEV + - add new algorithm: few more steps to 'Fast' (a'la HLT) CaloFuturerimeter + reconstruction + - CaloFutureHypo2TrgTrackAlg.h,.cpp + - CaloFutureTrgSelectNeutralCluster.h,.cpp + - cmt/requirements + version increment to v2r7 + +!========================== CaloFutureReco v2r6 2004-10-27 =================== +! 2004-10-27 - Vanya BELYAEV + - src/CaloFutureTrackAlg.h, src/CaloFutureTrackAlg.cpp + the algorithm is modified to take advantage from + new class TrTrackUse from CaloFuture/CaloFutureUtils package + - src/CaloFutureMergedPi0Alg.h, src/CaloFutureMergedPi0Alg.cpp + + new property "EtCut" is added to skip the processing of + clusters with small transverse energy. + The default value of this oproperty is -100*GeV + (which implies "NO CUT", and "BACKWARD-COMPATIBILITY" + in the sense of absolute reproducibility of results). + The idea comes from Olivier Deschamps and Cristina Carloganu. + + Another new property "MaxIterations" is added to reduce the + number of iterations + The default value (16) is "BACKWARD-COMPATIBLE" + The idea comes from Olivier Deschamps and Cristina Carloganu. + + In addition few "tiny" modification are applied: + - remove "count" loop + - location of spddigits and prs digits are moved from internal loop + to a top level + + The usage of EtCut=1.5*GeV and MaxIteration=6 togather with + these 'technical' optimizations + speeds up the execution of the algorithm approxmately 20 times. + + + The package *REQUIRES* : + - CaloFuture/CaloFutureUtils with versions >= v4r8 + - CaloFuture/CaloFutureEvent with version >= v13r6 + + +! 2004-10-26 - Vanya BELYAEV + - src/CaloFutureCluster2TrackAlg.h, src/CaloFutureCluster2TrackAlg.cpp + - src/CaloFutureHypo2TrackAlg.h, src/CaloFutureHypo2TrackAlg.cpp + update in properties for better dealing with track types + it is done with the helper algorithm base CaloFutureTrackAlg, + which allow to select/reject a certain track categories + according to + - general criteria (unique?error?), + - track categories ( is'*'?) + - algorithms ('*'?) +- options/BremMatch.opts +- options/Brem2Match.opts + update the configuratin files for new property names + +! 2004-10-26 - Vanya BELYAEV + - introduce FAST "photon" matching of trigger track (TrgTrach) with + CaloFuturetrimeter clusters. For a moment follow "off-line" phylosophy: + perfroam all-to-all mathcing and save result as a relation table + in TES. The supporting algorithm CaloFutureCluster2TrgTrackAlg does this job. + The execution is 5-6 times faster than the execution of + "standard" photon matching. The efficiency need to be testes + and studied. + In real environment one coudl gain addiitonal factor of 2 + (since if one uses this "o nly" fo select neutral clusters - "photons") + one does not need all-to-all matching (and one does not need to + register the table in TES!), one just che the existence of + tracks with chi2<cut, which should be "fast" procedure. + + +! 2004-10-24 - Vanya BELYAEV + - src/CaloFutureTrackMatchBrem2.h + src/CaloFutureTrackMatchBrem2.cpp + src/CaloFutureReco_load.cpp + add new 'tool' for (hopefully) improved 'bremstrahlung' matching. + the tool need to be tested with *LARGE* statistics + - options/Brem2Match.opts + new file for 'Brem2Match' algorithm configuration + - options/BremMatch.opts + add 'include' for new file Brem2Match.opts + +! 2004-10-24 - Vanya BELYAEV + - src/CaloFutureTrackMathcPhotonAlg.cpp + src/CaloFutureTrackMathcPhotonAlg.h + src/CaloFutureReco_load.cpp + remove obsolete algorithm + - src/CaloFutureTrack*.cpp + improve a little bit the error-reporting printout + +! 2004-10-22 - Vanya BELYAEV + - src/CaloFutureTrackMatchBase.h + src/CaloFutureTrackMatchBase.cpp + + 1) modify the internal match structure MatchStruct1 + to invert the matrix in the constructor + 2) modify the internal chi2 method to be more efficient + (eliminate the intermediate matrices) + 3) introduce local matrix storage + 4) itoriducet mtrxOp methods for fast evaluation of matrix products + + in overall (142) gives >10% impromevent in CPU performance + + 5) introduce new internal structure MatchStruct2 + 6) introduce set of new "chi2" methods dealing with MatchStruct2 + + (5) and (6) are the steps toward HLT matching + + - src/CellularAutomaton.cpp + change the Error-Code for 'uclusterized cells' warning message + from FAILURE to SUCCESS to redice a bit the potential confusion + +! 2004-10-22 - Vanya BELYAEV + + (requires the recent modifications in Event/CaloFutureEvent >= 13r6 ) + + - src/CellularAutomaton.h + src/CellularAutomaton.cpp + + The algorithm gas got 2 new properties + "Sort" (boolean, default = true ) - the flag which indicates wether + the sorting of clusters should + be performed + "SprtByET" (boolean, default = false) - the flag which indicates + which sorting criteria (energy + versus transverse energy) is used + for sorting + + The default settings corresponds to "backward-compatibility" + + - src/CaloFutureDeleteObject.h, src/CaloDeteleObject.cpp + remove the obsolete algorithm + one should use TESFilter algorithm from Kernel/LHCbAlgs package + + - src/CaloFutureCheckObjects.h, src/CaloFutureCheckObjects.cpp + remove obsolete algorithm + one should use TESCheck algorithm from Kernel/LHCbAlgs package + - src/CaloFutureReco_load.cpp + remove the factory instantiations for removed obsolete algorithms + + - cmt/requirements + version increment to v2r6 + +!======================= CaloFutureReco v2r5 2004-09-08 ====================== +! 2004-09-08 - Marco Cattaneo + - Remove associator factories from CaloFutureReco_load.cpp, as these have been + move to Associators/Associators package + +! 2004-09-05 - Vanya BELYAEV + - src/CelAutoTaggedCell.h + src/CellularAutomaton.h + src/CellularAutomaton.cpp + trivial modification to obtain 25% CPU gain + +! 2004-09-05 - Vanya BELYAEV + - src/CaloFutureCheckObjectsAlg.h(.cpp) + new trivial algorithm for checking the existence + (and by product, the loading!) of objects in Gaudi transient store + - src/CaloFutureReco_load.cpp + add the decalration of the new algorithm + +! 2004-09-02 - Vanya BELYAEV + - prepare for HLT/Trigger developments + +!======================= CaloFutureReco v2r4 2004-07-22 ====================== +! 2004-07-21 - Vanya BELYAEV + + - src/CaloFutureClusterCorrect3x3Position.cpp + 1. fix compilation warnings + - src/CaloFuture04ECorrection.cpp + 1. fix compilation warnings + 2. add 'info' printout for accepter hypos + 3. suppress excessive 'INFO' printout + 4. add 'EmCharged' to the list of accepted hypos + - src/CaloFuture04SCorrection.cpp + 1. fix compilation warnings + 2. add 'EmCharged' to the list of accepted hypos + 3. add 'info' printout for accepter hypos + - src/CaloFuture04LCorrection.cpp + 1. fix compilation warnings + 2. add 'info' printout for accepter hypos + 3. add 'EmCharged' to the list of accepted hypos + + ****** ALL MODIFICATIONS ARE BACKWARD COMPATIBLE ****** + + - cmt/requirements + 1. increment the version to v2r4 + +! 2004-07-20 - Vanya BELYAEV + - CaloFutureMergedPi0Alg.cpp + 1. make a fix for segmentation fault for + 3-cell cluster at the edge of calorimeter, where + only seed digit has positive energy. + For this case "subrow" and "subcol" values were not defined + it result in SubClus[1][1][1] = NULL and a further segmentation + fault. + 2. Few minor fixes to suppress compiler warnings about + the unused variables + - cmt/requirements increment the version to v2r3p2 + +!======================= CaloFutureReco v2r3p1 2004-06-03 ====================== +! 2004-06-03 - Ivan Belyaev + - src/CaloFutureReco_load.cpp + . Missing algorithm + - tagged as v2r3p1 +!======================== CaloFutureReco v2r3 2004-06-03 ======================= +! 2004-06-03 - Ivan Belyaev + - src/CaloFutureE0Correction.cpp + new version of energy corrections for DC04 + - src/CaloFutureClusterCorrect3x3Position.cpp(.h) + position correction for DC04 + - options/CaloFuture04ECorrection.opts + updated parameters for corrections + - cmt/requirement increment teh version to v2r3 + + +!======================== CaloFutureReco v2r2 2004-06-02 ======================= +! 2004-05-11 - Vanya BELYAEV + +- src/CaloFuture04ECorrection.cpp + modification of energy correction tool to be used for analysis + of DC04 data (produced with XmlDDDB >= v22r2 ) from Oliver Deschamps +- options/CaloFuture04*.opts + new parameters foe E/S/L corrections to be used for DC04 data + from Olivier Deschamps +- cmt/requirements + increment the version to v2r2 + +!======================= CaloFutureReco v2r1p1 2004-03-29 ====================== +! 2004-03-29 - Marco Cattaneo + - Fix Reco.opts to avoid multiple inclusion of options files + +!======================== CaloFutureReco v2r1 2004-03-18 ======================= +! 2004-03-17 - Vanya BELYAEV + - add new (04) Correction s from Olivier Deschamps + - remove some obsoltee stuff from 'options' directory + - few minor fixes + - cmt/requirements increment the version to v2r1 + +!======================== CaloFutureReco v2r0 2004-03-08 ======================= +! 2004-03-08 - Marco Cattaneo + - In CaloFutureCluster2TrackAlg.h/cpp, CaloFutureHypo2TrackAlg.h/cpp: + . rename m_upstream to m_downstream + . rename UseUpstream property to UseDownstream + . use new isDownstream() method of TrStoredTrack instead of upstream() + + - In CaloFutureTrackMatchBase.cpp, CaloFutureTrackMatchBremm.cpp, CaloFutureTrackMatchElectron.cpp + . use new isDownstream() method of TrStoredTrack instead of upstream() + + - In BremMatch.opts, ElectronMatch.opts, HcalPIDe.opts, PhotonMatch.opts + . rename UseUpstream property to UseDownstream + +! 2004-02-17 - Ivan BELYAEV + - update for new CaloFuture/CaloKernel and CaloFuture/CaloFutureInterface + - increase teh *MAJOR* version to v2r0 + +!======================== CaloFutureReco v1r8 2004-01-13 ======================= +! 2004-01-13 - Vanya BELYAEV + - src/CellularAutomaton.cpp + - src/CaloFutureMergedPi0Alg.cpp + 1) initialize new data field "seed" for the CaloFutureCluster + 2) set version (==2) for new container of Clusters + +!======================== CaloFutureReco v1r7 2003-12-11 ======================= +! 2003-12-11 - Marco Cattaneo + - Move to Gaudi v13, VC71 + . requirements: use CaloFutureInterfaces v3r0 + . Remove WIN32 implementations of std::max and std::min + + - Fix some doxygen warnings + +!======================= CaloFutureReco v1r6p1 2003-06-23 ======================= +! 2003-11-27 - Marco Cattaneo + - Add workarounds for missing != operator in new CaloFutureCellID from Xml + +!======================== CaloFutureReco v1r6 2003-06-23 ======================== +! 2003-06-23 - Ivan Belyaev + - Few fixes for new compiler + +! 2003-05-15 - Vanya BELYAEV + - src/CaloFutureSinglePhotonAlg.cpp + - src/CaloFutureElectronAlg.cpp + in the case of errors in used tools, the cluster/hypo is skipped now + (no error return) + - cmt/requirments increase the version + +!====================== CaloFutureReco v1r5 2003-04-30 ========================== +! 2003-04-11 - Vanya BELYAEV + new files: + - src/CaloFutureNewECorrection.h,.cpp new Energy correction from O. Deschamps + - src/CaloFutureNewSCorrection.h,.cpp new S-correctin tool from O.Deschamps + - src/CaloFutureNewLCorrection.h,.cpp new L-correction tool from O.Deschams + - options/CaloFutureNewECorrectionParam.opts parameters + - options/CaloFutureNewSCorrectionParam.opts parameters + - options/CaloFutureNewLCorrectionParam.opts parameters + modified: + - src/CaloFutureReco_load.cpp add new tools + - cmt/requirements increse the version to v1r5 + +! 2003-04-08 - Vanya BELYAEV + - src/CaloFutureHyposMerge.cpp Add split photons (CaloFutureHypoLocation::SplitPhotons) + to the default list of "merged" hypos + +!====================== CaloFutureReco v1r4 2003-03-24 ========================== +! 2003-03-13 - Vanya BELYAEV + - move *ALL* PID algorithms and tools into new package CaloFuturePIDs + - increase the version to v1r4 + - src/CaloFutureMergedPi0Alg.cpp - <<<<<<<<<<< VERY IMPORTANT BUG FIX >>>>>>>>>>>> + For merged pi0s "the first" split photons gets the extra cluster + and "the second one" gets only native/merged cluster + - src/CaloFutureHypoReShuffleAlg.h,.cpp new algorithm to fix the bug + - cmt/requirements - increase the version + + +! 2003-02-24 - Richard Beneyton + - src/CaloFutureSCorrectionFinal.cpp - re use covariance DEFINITION for S correction + - update covariance for border special correction + +!======================== CaloFutureReco v1r3p1 2003-02-13 ====================== +! 2003-02-11 - Ivan BELYAEV + - src/CaloFutureSingleGammaTool.cpp - add protection against MergedPi0s, which have no + CaloFuturePosition* field and reduce the debug printout + - cmt/requirements - increase the version number + +!======================== CaloFutureReco v1r3 2003-02-04 ======================== + +! 2003-02-04 - Ivan BELYAEV + - src/CaloFutureSingleGammaTool.h,.cpp - updated version of the tool by Frederic MACHEFERT + - src/CaloFuturePrsCorrection.h - improve calibration formula + - options/PrsCorrE.opts - new calibration constants for electrons + - options/PrsCorrG.opts - new calibration constants for photons + - options/Brunel.opts - reshuffling of "PIDs" algorithms + - cmt/requirements - increase the version + +! 2003-01-31 - Richard Beneyton + - src/CaloFutureSCorrectionFinal - update function, add border and covariance + - src/CaloFutureLCorrectionSimplev - update function + - options/LCorrectionSimple - define parameter + - options/SCorrectionFinal - define parameter + +!======================= CaloFutureReco v1r2p1 2003-01-23 ======================= +! 2003-01-22 - Ivan BELYAEV + - src/CaloFutureExtraDigits.h - tiny fix + remove unused variable + +! 2003-01-19 - Ivan Belyaev + - src/CaloFutureTrackEval.cpp - fix small "memory leak" (1 TrState per job) + + +!========================= CaloFutureReco v1r2 2002-12-09 ===================== +! 2002-12-09 - Ivan Belyaev + - Various bug fixes to Electron and Photon Algs + +! 2002-11-22 - Florence Ranjard + - requirements - use new versions + +!======================== CaloFutureReco v1r1 2002-12-02 ===================== +! 2002-11-29 - Ivan Belyaev + - cmt/requirements version update + - src/CaloFutureTrackEval.h,.cpp new generic tool for Spd/Prs/Ecal/HCal + energy evaluation for given track by V.Romanovsky + default parameters configured for Hcal + - src/CaloFutureTrackMatchBremm.h,.cpp improved error printout + - src/CaloFutureSCorrectionFinal.cpp check the position before using it + CONFIGURATION + - options/PhotonRec.opts switch OFF S-corrections by R.Beneyton + a) no covarioance matrix yet + b) no border treatment + use 2TANH correction from K.Beloous + - options/SShape2Tanh.opts new (tuned) parametrisations from S-corrections + + - options/ElectronRec.opts switch OFF S-corrections by R.Beneyton + use 2TANH correction from K.Beloous + +! 2002-11-20 - Richard Beneyton + - Add parabolic modilisation in CaloFutureLCorrectionSimple + with updated parameters + +!======================== CaloFutureReco v1r0 2002-11-18 ===================== +! 2002-11-18 - Marco Cattaneo + - Add missing factory for CaloFutureSCorrectionFinal Tool + - Add missing factory for CaloFutureHyposMerge algorithm + +! 2002-11-18 - Ivan Belyaev + - options/Brunel.opts quick fix to remove Hcal estrimators + - options/PrsPID*.opts remove "pragma" directives used for debugging + +! 2002-11-17 - Ivan Belyaev + - src/CaloFutureSCorrectionFinal.cpp - add missing std::max fro WIN32 compilation +! 2002-11-17 - Ivan Belyaev + - src/CaloFutureTrackIdEval.cpp,.h - remove these prototypes + - CaloFutureTrack2EstimatorAlg.cpp,.h - new generic algorithm for building the + generic relations of tracks and + some caloriemter estimators + (e.g. energy in Hcal or energy in Prs) + - CaloFutureTrack2IdAlg.cpp, .h - new generic algorithm to build + the actual PID estimators from + measured values using reference + "Signal" and "Background" distributions + + - CaloFutureTrackEcalEval.cpp,.h - concrete tool, which frm given chi2 table + gets Ecal estimator + - CaloFutureTrackHcalEval.cpp,.h - prototype of concrete tool, which evaluates + the energy in Hcal for given track + - CaloFutureTrackPrsEval.cpp,.h - concrete tool, which evaluates + the energy in Prs for given track + + - options/*.opts - a lot of new configuration options, + need to ne tuned next week + +! 2002-11-14 - Richard Beneyton + - Update L Correction coeff and calcul in CaloFutureLCorrectionSimple + with default parameters in code (supressed in option file) + - Add CaloFutureSCorrectionFinal with hardcoded default coeff + supressed in option file) + rq.: alg not based on CaloFutureSCorrectionSequence due to special + energies definition + +! 2002-10-31 - Ivan Belyaev + - New package + - All algorithms from CaloFutureAlgs,CaloFutureRec,CaloFutureTools,CaloFutureTrackTools + are grouped together diff --git a/CaloFuture/CaloFutureReco/options/Brunel.opts b/CaloFuture/CaloFutureReco/options/Brunel.opts new file mode 100755 index 0000000000000000000000000000000000000000..88848e4bb00d04f47d4596ddad34a5cebb785c71 --- /dev/null +++ b/CaloFuture/CaloFutureReco/options/Brunel.opts @@ -0,0 +1,124 @@ +// $Id: Brunel.opts,v 1.29 2010-04-29 21:13:59 odescham Exp $ +// ============================================================================ +// CVS tag $Name: not supported by cvs2svn $, version $Revision: 1.29 $ +// ============================================================================ + +/** @file + * The job-options file to run CaloFuturerimeter Reconstruction in Brunel + * @author Olivier Deschamps odescham@in2p3.fr + * & Vanya Belyaev Ivan.Belyaev@cern.ch + * @date 2006-26-05 + */ + +// The main stream : +RecoCALOFUTURESeq.Members += { "GaudiSequencer/CaloFutureDigits" , + //"CaloFutureGetterInit/CaloFutureDigitGetter", // NO LONGER NEEDED + "GaudiSequencer/CaloFutureClusters", + "GaudiSequencer/CaloFutureTrackMatch" , + "GaudiSequencer/CaloFutureRec", + "GaudiSequencer/CaloFuturePIDs" }; + +//------ Unpack the rawBanks & create CaloFutureDigit on TES +CaloFutureDigits.Members = { "CaloFutureZSupAlg/FutureEcalZSup", + "CaloFutureZSupAlg/FutureHcalZSup", + "CaloFutureDigitsFromRaw/FuturePrsFromRaw", + "CaloFutureDigitsFromRaw/FutureSpdFromRaw"}; + + +//------ Clusterize, clean & compute cluster parameters +CaloFutureClusters.Members += { "CaloFutureDigitFilterAlg/CaloFutureDigitFilter", + "FutureCellularAutomatonAlg/EcalClust", + "CaloFutureSharedCellAlg/EcalShare", + "CaloFutureClusterCovarianceAlg/EcalCovar"}; + +//------ Track-Cluster 2D matching for Neutral/Charged cluster selection + +CaloFutureTrackMatch.Members += { "GaudiSequencer/CaloFutureAcceptance", + "FuturePhotonMatchAlg/ClusterMatch" } ; + +//------ Acceptance Filters +CaloFutureAcceptance.Members = { "InSpdFutureAcceptance Alg/InSPD" , + "InPrsFutureAcceptance Alg/InPRS" , + "InEcalFutureAcceptance Alg/InECAL", + "InHcalFutureAcceptance Alg/InHCAL" , + "FutureInBremFutureAcceptanceAlg/InBREM" }; + + +//------ Merged Pi0, Single Photon & Electron reconstruction + +CaloFutureRec.Members += {"CaloFutureMergedPi0Alg/MergedPi0Rec", + "CaloFutureHypoAlg/PhotonFromMergedRec", + "CaloFutureSinglePhotonAlg/SinglePhotonRec", + "CaloFutureElectronAlg/ElectronRec"}; + + +#include "$CALOFUTURERECOOPTS/ClusterSelection.opts" +#include "$CALOFUTURERECOOPTS/MergedPi0Rec.opts" +#include "$CALOFUTURERECOOPTS/PhotonFromMergedRec.opts" +#include "$CALOFUTURERECOOPTS/SinglePhotonRec.opts" +#include "$CALOFUTURERECOOPTS/ElectronRec.opts" +// Configure Tools +#include "$CALOFUTURERECOOPTS/CaloFutureECorrectionParam.opts" +#include "$CALOFUTURERECOOPTS/CaloFutureSCorrectionParam.opts" +#include "$CALOFUTURERECOOPTS/CaloFutureLCorrectionParam.opts" + +//------- Track- charged/neutral cluster 3D matching for electron/bremStrahlung evaluation + +CaloFuturePIDs.Members += + { + // 3D Matching + "GaudiSequencer/CaloFutureMatch" + // Energy Deposit along track path + ,"GaudiSequencer/CaloFutureEnergy" + // CaloFutureID DLL's + ,"GaudiSequencer/CaloFutureDLLs" + // Neutral IDs + ,"GaudiSequencer/NeutralPIDs" + } ; + +NeutralPIDs.Members += { + "CaloFuturePhotonIdAlg/PhotonID", + "CaloFuturePhotonIdAlg/MergedID", + "CaloFuturePhotonIdAlg/SplitPhotonID" + }; + +MergedID.Type = "MergedID"; +SplitPhotonID.Type= "PhotonFromMergedID"; + +CaloFutureMatch.Members += + { + "FutureElectronMatchAlg/ElectronMatch" + ,"BremMatchAlg/BremMatch" + }; +CaloFutureEnergy.Members = + { + "FutureTrack2SpdEAlg/SpdE" + ,"FutureTrack2PrsEAlg/PrsE" + ,"FutureTrack2EcalEAlg/EcalE" + ,"FutureTrack2HcalEAlg/HcalE" + }; +CaloFutureDLLs.Members += + { + // convert tables into plain Chi2's + "FutureEcalChi22ID" + , "BremChi22ID" + , "FutureClusChi22ID" + // evaluate proper DLL + , "FuturePrsPIDeAlg/PrsPIDe" + , "BremPIDeAlg/BremPIDe" + , "FutureEcalPIDeAlg/EcalPIDe" + , "FutureHcalPIDeAlg/HcalPIDe" + , "FutureEcalPIDmuAlg/EcalPIDmu" + , "FutureHcalPIDmuAlg/HcalPIDmu" + }; + + +CaloFutureDigits.MeasureTime = true ; +CaloFutureClusters.MeasureTime = true ; +CaloFutureTrackMatch.MeasureTime = true ; +CaloFutureRec.MeasureTime = true ; +CaloFuturePIDs.MeasureTime = true ; +CaloFutureAcceptance.MeasureTime = true ; +CaloFutureMatch.MeasureTime = true ; +CaloFutureEnergy.MeasureTime = true ; +CaloFutureDLLs.MeasureTime = true ; diff --git a/CaloFuture/CaloFutureReco/options/CaloFutureECorrectionParam.opts b/CaloFuture/CaloFutureReco/options/CaloFutureECorrectionParam.opts new file mode 100755 index 0000000000000000000000000000000000000000..07c14c15de3423e8cccf817cf3ce5ebcd547c9fc --- /dev/null +++ b/CaloFuture/CaloFutureReco/options/CaloFutureECorrectionParam.opts @@ -0,0 +1,51 @@ +// MC-based paramatrisation for CaloFutureECorrection (to be re-evaluated for recent MC). +// to be applied on MC data - Real data correction come with condDB + +// Single Photon =========================== +SinglePhotonRec.ECorrection.Parameters += { + // function #param params : outer | middle | inner + "alphaG" : { 0 , 1 , 1.0 , 1.0 , 1.0 }, + "alphaE" : { 0 , 2 , 1.0105 , 1.0208 , 1.0325 , + 0.11561E-06 , 0.33802E-07 , -0.28272E-07 }, + "alphaB" : { 0 , 2 , 1.0159 , 1.0210 , 1.0256 , + -0.67500E-01 ,-0.78525E-01 , -0.8901E-01 }, + "alphaX" : { 0 , 2 , 1,1,1, 0. , 0.0171 , 0.0315 }, + "alphaY" : { 0 , 2 , 1,1,1, 0. , 0.0362 , 0.0479 }, + "beta" : { 1 , 1 , 8.3 , 8.8 , 9.5 }, + "globalC" : { 0 , 1 , 0.977 , 0.977 , 0.977 } +}; + + +// Photon from MergedPi0 =========================== +PhotonFromMergedRec.ECorrection.Parameters += { + // function #param params : outer | middle | inner + "alphaG" : { 0 , 1 , 1.0 , 1.0 , 1.0 }, + "alphaE" : { 0 , 2 , 1.0105 , 1.0208 , 1.0325 , + 0.11561E-06 , 0.33802E-07 , -0.28272E-07 }, + "alphaB" : { 0 , 2 , 1.0159 , 1.0210 , 1.0256 , + -0.67500E-01 ,-0.78525E-01 , -0.8901E-01 }, + "alphaX" : { 0 , 2 , 1,1,1, 0. , 0.0171 , 0.0315 }, + "alphaY" : { 0 , 2 , 1,1,1, 0. , 0.0362 , 0.0479 }, + "beta" : { 1 , 1 , 8.3 , 8.8 , 9.5 }, + "globalC" : { 0 , 1 , 0.977 , 0.977 , 0.977 } +}; + + +// Single Electron =========================== +ElectronRec.ECorrection.Parameters += { + // function #param params : outer | middle | inner + "alphaG" : { 0 , 1 , 0.988 , 0.988 , 0.988 }, + "alphaE" : { 0 , 2 , 1.0105 , 1.0208 , 1.0325 , + 0.11561E-06 , 0.33802E-07 , -0.28272E-07 }, + "alphaB" : { 0 , 2 , 1.0159 , 1.0210 , 1.0256 , + -0.67500E-01 ,-0.78525E-01 , -0.8901E-01 }, + "alphaX" : { 0 , 2 , 1,1,1, 0. , 0.0171 , 0.0315 }, + "alphaY" : { 0 , 2 , 1,1,1, 0. , 0.0362 , 0.0479 }, + "beta" : { 1 , 1 , 8.3 , 8.8 , 9.5 } +}; + + + + + + diff --git a/CaloFuture/CaloFutureReco/options/CaloFutureECorrectionParam_Data2010.opts b/CaloFuture/CaloFutureReco/options/CaloFutureECorrectionParam_Data2010.opts new file mode 100644 index 0000000000000000000000000000000000000000..a9beccbace829b63ba66a31dbe48929f1f609ad0 --- /dev/null +++ b/CaloFuture/CaloFutureReco/options/CaloFutureECorrectionParam_Data2010.opts @@ -0,0 +1,48 @@ +// paramatrisation for CaloFutureECorrection as extracted from first 2010 DATA (2010/05/20) +// should come via condDB - keep options file for further development + + + +// Single Photon =========================== +SinglePhotonRec.ECorrection.Parameters += { + // function #param params : outer | middle | inner + "alphaG" : { 0 , 1 , 1.0353 , 1.0553 , 1.1000 }, + "alphaB" : { 0 , 2 , 1.9984 , 1.0106 , 1.0152 , + -0.6635E-01 ,-0.7772E-01 , -0.8811E-01 }, + "alphaX" : { 0 , 2 , 1,1,1, 0. , 0.0171 , 0.0315 }, + "alphaY" : { 0 , 2 , 1,1,1, 0. , 0.0362 , 0.0479 }, + "beta" : { 1 , 1 , 8.7 , 9.7 , 11.0 }, + "globalC" : { 1 , 1 , 1.0762 , 1.0545 , 1.0390 } +}; + + +// Photon from MergedPi0 =========================== +PhotonFromMergedRec.ECorrection.Parameters += { + // function #param params : outer | middle | inner + "alphaG" : { 0 , 1 , 1.1110 , 1.1356 , 1.2152 }, + "alphaB" : { 0 , 2 , 1.9984 , 1.0106 , 1.0152 , + -0.6635E-01 ,-0.7772E-01 , -0.8811E-01 }, + "alphaX" : { 0 , 2 , 1,1,1, 0. , 0.0171 , 0.0315 }, + "alphaY" : { 0 , 2 , 1,1,1, 0. , 0.0362 , 0.0479 }, + "beta" : { 1 , 1 , 8.7 , 9.7 , 11.0 }, + "globalC" : { 1 , 1 , 1.0762 , 1.0545 , 1.0390 } +}; + + +// Single Electron =========================== +ElectronRec.ECorrection.Parameters += { + // function #param params : outer | middle | inner + "alphaG" : { 0 , 1 , 1.0353 , 1.0553 , 1.1000 }, + "alphaB" : { 0 , 2 , 1.9984 , 1.0106 , 1.0152 , + -0.6635E-01 ,-0.7772E-01 , -0.8811E-01 }, + "alphaX" : { 0 , 2 , 1,1,1, 0. , 0.0171 , 0.0315 }, + "alphaY" : { 0 , 2 , 1,1,1, 0. , 0.0362 , 0.0479 }, + "beta" : { 1 , 1 , 8.7 , 9.7 , 11.0 }, + "globalC" : { 1 , 1 , 1.08379 , 1.07990 , 1.07923 } +}; + + + + + + diff --git a/CaloFuture/CaloFutureReco/options/CaloFutureLCorrectionParam.opts b/CaloFuture/CaloFutureReco/options/CaloFutureLCorrectionParam.opts new file mode 100755 index 0000000000000000000000000000000000000000..f9ea09a084098ad6644fd694e789ef5f91fecec1 --- /dev/null +++ b/CaloFuture/CaloFutureReco/options/CaloFutureLCorrectionParam.opts @@ -0,0 +1,36 @@ +//SinglePhotonRec.LCorrection.OutputLevel = 2; + + +SinglePhotonRec.LCorrection.Parameters += { + // function #param params : outer | middle | inner + "gamma0" : { 1 , 1 , 22.305 , 19.053 , 17.936 }, + "gammaP" : { 2 , 2 , 2.04 , 1.53 , 1.15 , + -0.0281 , -0.455 , -0.0392 }, + "delta0" : { 1 , 1 , 49.04 , 51.87 , 45.54 }, + "deltaP" : { 2 , 2 , 4.38 , 4.15 , 4.02 , + -0.0247 , -0.0597 , -0.0308 } +}; + + +ElectronRec.LCorrection.Parameters += { + // function #param params : outer | middle | inner + "gamma0" : { 1 , 1 , 22.305 , 19.053 , 17.936 }, + "gammaP" : { 2 , 2 , 2.04 , 1.53 , 1.15 , + -0.0281 , -0.455 , -0.0392 }, + "delta0" : { 1 , 1 , 49.04 , 51.87 , 45.54 }, + "deltaP" : { 2 , 2 , 4.38 , 4.15 , 4.02 , + -0.0247 , -0.0597 , -0.0308 } +}; + +PhotonFromMergedRec.LCorrection.Parameters += { + // function #param params : outer | middle | inner + "gamma0" : { 1 , 1 , 22.305 , 19.053 , 17.936 }, + "gammaP" : { 2 , 2 , 2.04 , 1.53 , 1.15 , + -0.0281 , -0.455 , -0.0392 }, + "delta0" : { 1 , 1 , 49.04 , 51.87 , 45.54 }, + "deltaP" : { 2 , 2 , 4.38 , 4.15 , 4.02 , + -0.0247 , -0.0597 , -0.0308 } +}; + + + diff --git a/CaloFuture/CaloFutureReco/options/CaloFutureRecoOnDemand.opts b/CaloFuture/CaloFutureReco/options/CaloFutureRecoOnDemand.opts new file mode 100755 index 0000000000000000000000000000000000000000..646ea86c3eef331422dc45df242e89599f9fe27e --- /dev/null +++ b/CaloFuture/CaloFutureReco/options/CaloFutureRecoOnDemand.opts @@ -0,0 +1,29 @@ +// +// author : Olivier Deschamps odescham@in2p3.fr +// +// Setup the CaloFutureReco on-Demand for DaVinci usage +// + +// CaloFutureDigits on-demand +#include "$CALOFUTUREDAQROOT/options/CaloFutureDigitsOnDemand.opts" + +// CaloFutureClusters on-demand +DataOnDemandSvc.AlgMap += { + "Rec/Calo/EcalClusters" : "GaudiSequencer/CaloFutureClusterOnDemand" + ,"Rec/Calo/EcalSplitClusters" : "CaloFutureMergedPi0Alg/MergedPi0Rec" +}; + +// Add digit sequence in CaloFutureCluster-onDemand to please HLT +CaloFutureClusterOnDemand.Members += { "GaudiSequencer/CaloFutureDigitsSeq", + "FutureCellularAutomatonAlg/EcalClust", + "CaloFutureSharedCellAlg/EcalShare", + "CaloFutureClusterCovarianceAlg/EcalCovar", + "CaloFutureClusterCorrect3x3Position/EcalPosition"}; +#include "$CALOFUTUREDAQROOT/options/CaloFutureDigitsSeq.opts" + +// +MergedPi0Rec.CreateSplitClustersOnly = true; +#include "$CALOFUTURERECOOPTS/MergedPi0Rec.opts" + +// Other CaloFuture objects (CaloFutureHypo, CaloFuturePIDs) are available on DST +// TODO : matching tables ... diff --git a/CaloFuture/CaloFutureReco/options/CaloFutureSCorrectionParam.opts b/CaloFuture/CaloFutureReco/options/CaloFutureSCorrectionParam.opts new file mode 100755 index 0000000000000000000000000000000000000000..b531d42b6fdc6bc41c674cbcaedee91919e4714b --- /dev/null +++ b/CaloFuture/CaloFutureReco/options/CaloFutureSCorrectionParam.opts @@ -0,0 +1,61 @@ +ElectronRec.SCorrection.Parameters = { + // function #param params : outer | middle | inner + "shapeX" : { 5 , 1 , 0.102 , 0.129 , 0.144 }, + "shapeY" : { 5 , 1 , 0.102 , 0.129 , 0.144 }, + "residual" : { 1 , 8 , -0.47496E-03, -0.97712E-05, -0.14401E-03, + 0.44911 , 0.33898 , 0.29037, + -0.34187E-01, 0.14566E-01, 0.28848E-01, + -9.0335 , -5.9958 , -5.1697, + 0.46190 , -0.13533 , -0.34664, + 53.041 , 32.711 , 26.885, + -1.2801 , 0.33460E-01, 0.99928, + -97.865 ,-58.743 ,-45.032}, + "asymP" : { 1 , 3 , 0.24742E-01, 0.28587E-01, 0.19870E-01, + 0.11487E-01, 0.11557E-01, 0.38043E-02, + -0.32640 ,-0.31548 ,-0.21436}, + "asymM" : { 1 , 3 , -0.29386E-01,-0.28587E-01,-0.19870E-01, + 0.11472E-01, 0.11557E-01, 0.38043E-02, + 0.35928 , 0.31548 , 0.21436} +}; + +SinglePhotonRec.SCorrection.Parameters = { + // function #param params : outer | middle | inner + "shapeX" : { 5 , 1 , 0.102 , 0.129 , 0.144 }, + "shapeY" : { 5 , 1 , 0.102 , 0.129 , 0.144 }, + "residual" : { 1 , 8 , -0.47496E-03, -0.97712E-05, -0.14401E-03, + 0.44911 , 0.33898 , 0.29037, + -0.34187E-01, 0.14566E-01, 0.28848E-01, + -9.0335 , -5.9958 , -5.1697, + 0.46190 , -0.13533 , -0.34664, + 53.041 , 32.711 , 26.885, + -1.2801 , 0.33460E-01, 0.99928, + -97.865 ,-58.743 ,-45.032}, + "asymP" : { 1 , 3 , 0.24742E-01, 0.28587E-01, 0.19870E-01, + 0.11487E-01, 0.11557E-01, 0.38043E-02, + -0.32640 ,-0.31548 ,-0.21436}, + "asymM" : { 1 , 3 , -0.29386E-01,-0.28587E-01,-0.19870E-01, + 0.11472E-01, 0.11557E-01, 0.38043E-02, + 0.35928 , 0.31548 , 0.21436} +}; + + +PhotonFromMergedRec.SCorrection.Parameters = { + // function #param params : outer | middle | inner + "shapeX" : { 5 , 1 , 0.102 , 0.129 , 0.144 }, + "shapeY" : { 5 , 1 , 0.102 , 0.129 , 0.144 }, + "residual" : { 1 , 8 , -0.47496E-03, -0.97712E-05, -0.14401E-03, + 0.44911 , 0.33898 , 0.29037, + -0.34187E-01, 0.14566E-01, 0.28848E-01, + -9.0335 , -5.9958 , -5.1697, + 0.46190 , -0.13533 , -0.34664, + 53.041 , 32.711 , 26.885, + -1.2801 , 0.33460E-01, 0.99928, + -97.865 ,-58.743 ,-45.032}, + "asymP" : { 1 , 3 , 0.24742E-01, 0.28587E-01, 0.19870E-01, + 0.11487E-01, 0.11557E-01, 0.38043E-02, + -0.32640 ,-0.31548 ,-0.21436}, + "asymM" : { 1 , 3 , -0.29386E-01,-0.28587E-01,-0.19870E-01, + 0.11472E-01, 0.11557E-01, 0.38043E-02, + 0.35928 , 0.31548 , 0.21436} +}; + diff --git a/CaloFuture/CaloFutureReco/options/CaloFutureStandaloneClusterSelection.opts b/CaloFuture/CaloFutureReco/options/CaloFutureStandaloneClusterSelection.opts new file mode 100755 index 0000000000000000000000000000000000000000..32352be144c784bde7b11cfa03fce5ca5785cc6e --- /dev/null +++ b/CaloFuture/CaloFutureReco/options/CaloFutureStandaloneClusterSelection.opts @@ -0,0 +1,27 @@ +//------------------------------------------- +// Select neutral clusters for Photon hypo +//------------------------------------------- +SinglePhotonRec.SelectionTools = { + "CaloFutureSelectCluster/PhotonClusterSelect", + "CaloFutureSelectClusterWithPrs/EcalClusterWithPrs", + "CaloFutureSelectNeutralClusterWithSpd/EcalClusterWithNoSpd" +}; +SinglePhotonRec.EcalClusterWithPrs.MinEnergy = 10*MeV ; +SinglePhotonRec.PhotonClusterSelect.MinEnergy = 150; +//SinglePhotonRec.PhotonClusterSelect.MaxDigits = 99; + + +//------------------------------------------- +// Select charged clusters for Electron hypo +//------------------------------------------- +ElectronRec.SelectionTools = { + "CaloFutureSelectCluster/ElectronClusterSelect", + "CaloFutureSelectClusterWithPrs/EcalClusterWithPrs", + "CaloFutureSelectChargedClusterWithSpd/EcalClusterWithSpd" +}; +ElectronRec.EcalClusterWithPrs.MinEnergy = 10*MeV ; +ElectronRec.ElectronClusterSelect.MinEnergy = 150; +//ElectronRec.ElectronClusterSelect.MaxDigits = 99; + + + diff --git a/CaloFuture/CaloFutureReco/options/CaloFutureStandalonePartialReco.opts b/CaloFuture/CaloFutureReco/options/CaloFutureStandalonePartialReco.opts new file mode 100755 index 0000000000000000000000000000000000000000..f45c2ffc08a2c102fccfea74c024da20c0ab85b0 --- /dev/null +++ b/CaloFuture/CaloFutureReco/options/CaloFutureStandalonePartialReco.opts @@ -0,0 +1,38 @@ + +PartialRecoCALOFUTURESeq.Members += { "GaudiSequencer/CaloFutureDigits" + ,"GaudiSequencer/CaloFutureClusters" + ,"GaudiSequencer/CaloFutureRec" +}; + +//------ Unpack the rawBanks & create CaloFutureDigit on TES +CaloFutureDigits.Members = { "CaloFutureZSupAlg/FutureEcalZSup", + "CaloFutureZSupAlg/FutureHcalZSup", + "CaloFutureDigitsFromRaw/FuturePrsFromRaw", + "CaloFutureDigitsFromRaw/FutureSpdFromRaw"}; + + +//------ Clusterize, clean & compute cluster parameters +CaloFutureClusters.Members += { "FutureCellularAutomatonAlg/EcalClust", + "CaloFutureSharedCellAlg/EcalShare", + "CaloFutureClusterCovarianceAlg/EcalCovar", + "CaloFutureClusterCorrect3x3Position/EcalPosition"}; + + +//------ Merged Pi0, Single Photon & Electron reconstruction +CaloFutureRec.Members += {"CaloFutureMergedPi0Alg/MergedPi0Rec", + "CaloFutureHypoAlg/PhotonFromMergedRec", + "CaloFutureSinglePhotonAlg/SinglePhotonRec", + "CaloFutureElectronAlg/ElectronRec"}; + +//EcalClust.CellSelectorForEnergy = ""; + +#include "$CALOFUTURERECOOPTS/SinglePhotonRec.opts" +#include "$CALOFUTURERECOOPTS/ElectronRec.opts" +#include "$CALOFUTURERECOOPTS/MergedPi0Rec.opts" +#include "$CALOFUTURERECOOPTS/PhotonFromMergedRec.opts" +#include "$CALOFUTURERECOOPTS/CaloFutureStandaloneClusterSelection.opts" +#include "$CALOFUTURERECOOPTS/CaloFutureECorrectionParam.opts" +#include "$CALOFUTURERECOOPTS/CaloFutureSCorrectionParam.opts" +#include "$CALOFUTURERECOOPTS/CaloFutureLCorrectionParam.opts" + + diff --git a/CaloFuture/CaloFutureReco/options/ClusterSelection.opts b/CaloFuture/CaloFutureReco/options/ClusterSelection.opts new file mode 100755 index 0000000000000000000000000000000000000000..a377e4a8697fa4eae93d64f671a3eaac7983fad4 --- /dev/null +++ b/CaloFuture/CaloFutureReco/options/ClusterSelection.opts @@ -0,0 +1,28 @@ +//------------------------------------------- +// Select neutral clusters for Photon hypo +//------------------------------------------- +SinglePhotonRec.SelectionTools = { + "CaloFutureSelectCluster/PhotonClusterSelect", + "CaloFutureSelectNeutralClusterWithTracks/NeutralCluster" +} ; +SinglePhotonRec.NeutralCluster.MinChi2 = 4 ; +SinglePhotonRec.PhotonClusterSelect.MinEnergy = 150; +//SinglePhotonRec.PhotonClusterSelect.MaxDigits = 99; + + +//------------------------------------------- +// Select charged clusters for Electron hypo +//------------------------------------------- +ElectronRec.SelectionTools = { + "CaloFutureSelectCluster/ElectronClusterSelect", + "CaloFutureSelectChargedClusterWithSpd/ClusterWithSpd", + "CaloFutureSelectClusterWithPrs/ClusterWithPrs", + "CaloFutureSelectorNOT/ChargedCluster" +}; + +ElectronRec.ChargedCluster.SelectorTools = { "CaloFutureSelectNeutralClusterWithTracks/NotNeutralCluster"} ; +ElectronRec.ChargedCluster.NotNeutralCluster.MinChi2 = 25 ; +ElectronRec.ClusterWithPrs.MinEnergy = 10.*MeV; +ElectronRec.ElectronClusterSelect.MinEnergy = 150; +//ElectronRec.ElectronClusterSelect.MaxDigits = 99; + diff --git a/CaloFuture/CaloFutureReco/options/ElectronRec.opts b/CaloFuture/CaloFutureReco/options/ElectronRec.opts new file mode 100755 index 0000000000000000000000000000000000000000..9918fa16764f778f2f479e8893450ea4cf6ace99 --- /dev/null +++ b/CaloFuture/CaloFutureReco/options/ElectronRec.opts @@ -0,0 +1,7 @@ + + +ElectronRec.HypoTools = { "CaloFutureExtraDigits/SpdPrsExtraE" } ; +ElectronRec.CorrectionTools2 = { "CaloFutureECorrection/ECorrection" } ; +ElectronRec.CorrectionTools2 += { "CaloFutureSCorrection/SCorrection" } ; +ElectronRec.CorrectionTools2 += { "CaloFutureLCorrection/LCorrection" } ; + diff --git a/CaloFuture/CaloFutureReco/options/MergedPi0Rec.opts b/CaloFuture/CaloFutureReco/options/MergedPi0Rec.opts new file mode 100755 index 0000000000000000000000000000000000000000..08ed7f453ebe79ba825e343319eb89b993e7cd35 --- /dev/null +++ b/CaloFuture/CaloFutureReco/options/MergedPi0Rec.opts @@ -0,0 +1,54 @@ +// ============================================================================ +/** @file + * Options file to run CaloFutureMergedPi0Alg "MergedPi0Rec" + * @author Olivier Deschamps + */ +// ============================================================================ + +MergedPi0Rec.Pi0Tools = {"CaloFutureExtraDigits/SpdPrsExtraM"}; + + +MergedPi0Rec.ShowerProfile.Parameters = { + // function #param params : outer | middle | inner + "profile" : { 6 , 10 , + -0.0060, 0.0464 ,0.0981, + 2.4956, 2.0384, 2.2529, + 115.0827, 36.5885, 33.8837, + 9.8842, 8.0260, 8.0532, + 0.0320, 0.0460, 0.0654, + 2.0982, 2.3936, 2.2046, + 1.0302, 1.0703, 1.1092, + 0.0409, 0.1611, 0.1645, + 0.0030, 0.0238, 0.0248, + -9.6135, -5.8899, -5.7248}, + + // converted photons + "profileC" :{ 6 , 10 , + 0.0486, 0.0882, 0.1111, + 2.7847, 1.7910, 1.7909, + 68.4815, 24.4324, 18.0852, + 9.0870, 7.4802, 7.1122, + 0.0116, 0.0258, 0.0261, + 1.2591, 2.7719, 1.3889, + 1.0464, 1.1294, 1.1846, + -0.0900, -0.0802, -0.0934, + 0.0005, 0.0024, 0.0029, + -12.9098, -9.7273, -8.9966} +}; + + +MergedPi0Rec.Pi0SCorrection.Parameters ={ + "shapeX" : { 5 , 1 , 0.102 , 0.129 , 0.144 }, + "shapeY" : { 5 , 1 , 0.102 , 0.129 , 0.144 } +}; + +MergedPi0Rec.Pi0LCorrection.Parameters ={ + "gamma0" : { 1 , 1 , 22.305 , 19.053 , 17.936 }, + "gammaP" : { 2 , 2 , 2.04 , 1.53 , 1.15 , + -0.0281 , -0.455 , -0.0392 }, + "delta0" : { 1 , 1 , 49.04 , 51.87 , 45.54 }, + "deltaP" : { 2 , 2 , 4.38 , 4.15 , 4.02 , + -0.0247 , -0.0597 , -0.0308 } +}; +// +MergedPi0Rec.EtCut = 2.*GeV; diff --git a/CaloFuture/CaloFutureReco/options/PhotonFromMergedRec.opts b/CaloFuture/CaloFutureReco/options/PhotonFromMergedRec.opts new file mode 100755 index 0000000000000000000000000000000000000000..dbd94b1a4311d03106ccb598c9637dbd300cc29c --- /dev/null +++ b/CaloFuture/CaloFutureReco/options/PhotonFromMergedRec.opts @@ -0,0 +1,6 @@ +PhotonFromMergedRec.HypoType = "SplitPhotons"; +PhotonFromMergedRec.Tools += { "CaloFutureECorrection/ECorrection" }; // Ecorrection +PhotonFromMergedRec.Tools += { "CaloFutureSCorrection/SCorrection" }; // Scorrection +PhotonFromMergedRec.Tools += { "CaloFutureLCorrection/LCorrection" }; // Lcorrection +PhotonFromMergedRec.Tools += { "CaloFutureExtraDigits/SpdPrsExtraS" }; // ExtraDigits + diff --git a/CaloFuture/CaloFutureReco/options/SinglePhotonRec.opts b/CaloFuture/CaloFutureReco/options/SinglePhotonRec.opts new file mode 100755 index 0000000000000000000000000000000000000000..e9926c3784bae8c6bf09c049082988a0ac00937d --- /dev/null +++ b/CaloFuture/CaloFutureReco/options/SinglePhotonRec.opts @@ -0,0 +1,6 @@ + + +SinglePhotonRec.HypoTools = { "CaloFutureExtraDigits/SpdPrsExtraG" } ; +SinglePhotonRec.CorrectionTools2 = { "CaloFutureECorrection/ECorrection" } ; +SinglePhotonRec.CorrectionTools2 += { "CaloFutureSCorrection/SCorrection" } ; +SinglePhotonRec.CorrectionTools2 += { "CaloFutureLCorrection/LCorrection" } ; diff --git a/CaloFuture/CaloFutureReco/options/UnpackCaloFutureHypoOnDemand.opts b/CaloFuture/CaloFutureReco/options/UnpackCaloFutureHypoOnDemand.opts new file mode 100644 index 0000000000000000000000000000000000000000..0ec8a117fe2033f9116cc0e57fb038d7e076e77d --- /dev/null +++ b/CaloFuture/CaloFutureReco/options/UnpackCaloFutureHypoOnDemand.opts @@ -0,0 +1,19 @@ +ApplicationMgr.ExtSvc += { "DataOnDemandSvc" }; +DataOnDemandSvc.AlgMap += { "/Event/Rec/Calo/Photons" : "UnpackCaloFutureHypo/UnpackPhotons" , + "/Event/Rec/Calo/MergedPi0s" : "UnpackCaloFutureHypo/UnpackMergedPi0s", + "/Event/Rec/Calo/Electrons" : "UnpackCaloFutureHypo/UnpackElectrons", + "/Event/Rec/Calo/SplitPhotons": "UnpackCaloFutureHypo/UnpackSplitPhotons" + }; + + + +UnpackPhotons.InputName = "/Event/pRec/Calo/Photons" ; +UnpackMergedPi0s.InputName = "/Event/pRec/Calo/MergedPi0s"; +UnpackElectrons.InputName = "/Event/pRec/Calo/Electrons"; +UnpackSplitPhotons.InputName = "/Event/pRec/Calo/SplitPhotons"; + +UnpackPhotons.OutputName = "/Event/Rec/Calo/Photons" ; +UnpackMergedPi0s.OutputName = "/Event/Rec/Calo/MergedPi0s"; +UnpackElectrons.OutputName = "/Event/Rec/Calo/Electrons"; +UnpackSplitPhotons.OutputName = "/Event/Rec/Calo/SplitPhotons"; + diff --git a/CaloFuture/CaloFutureReco/options/UseForwardTracksOnly.opts b/CaloFuture/CaloFutureReco/options/UseForwardTracksOnly.opts new file mode 100755 index 0000000000000000000000000000000000000000..dab864e6f041abf297f6e99a4eaffd9ca200b84f --- /dev/null +++ b/CaloFuture/CaloFutureReco/options/UseForwardTracksOnly.opts @@ -0,0 +1,19 @@ + +InSPD.Inputs = {"Rec/Track/Forward"}; +InPRS.Inputs = {"Rec/Track/Forward"}; +InECAL.Inputs = {"Rec/Track/Forward"}; +InHCAL.Inputs = {"Rec/Track/Forward"}; +InBREM.Inputs = {"Rec/Track/Forward"}; + +ClusterMatch.Tracks = {"Rec/Track/Forward"}; +ElectronMatch.Tracks = {"Rec/Track/Forward"}; +BremMatch.Tracks = {"Rec/Track/Forward"}; + +EcalE.Inputs = {"Rec/Track/Forward"}; +HcalE.Inputs = {"Rec/Track/Forward"}; +PrsE.Inputs = {"Rec/Track/Forward"}; +SpdE.Inputs = {"Rec/Track/Forward"}; + +FutureEcalChi22ID.Tracks = {"Rec/Track/Forward"}; +BremChi22ID.Tracks = {"Rec/Track/Forward"}; +FutureClusChi22ID.Tracks = {"Rec/Track/Forward"}; diff --git a/CaloFuture/CaloFutureReco/python/CaloFutureReco/Configuration.py b/CaloFuture/CaloFutureReco/python/CaloFutureReco/Configuration.py new file mode 100644 index 0000000000000000000000000000000000000000..88db7789ef54ab6224aa42727b7fffd1d656caf3 --- /dev/null +++ b/CaloFuture/CaloFutureReco/python/CaloFutureReco/Configuration.py @@ -0,0 +1,1061 @@ +#!/usr/bin/env gaudirun.py +# ============================================================================= +## Confurable for CaloFuturerimeter Reconstruction +# @author Vanya BELYAEV Ivan.Belyaev@nikhe.nl +# @date 2008-07-17 +# ============================================================================= +""" +Configurable for CaloFuturerimeter Reconstruction +""" + +# ============================================================================= +__author__ = "Vanya BELYAEV Ivan.Belyaev@nikhef.nl" +__version__ = "CVS tag $Name: not supported by cvs2svn $, version $Revision: 1.16 $" +# ============================================================================= +__all__ = ( + 'HltCaloFutureRecoConf' , + 'OffLineCaloFutureRecoConf' , + 'CaloFutureRecoConf', + 'CaloFutureProcessor', + 'CaloFutureLines' + ) +# ============================================================================= + +from LHCbKernel.Configuration import * + + +from GaudiKernel.SystemOfUnits import MeV, GeV +from CaloKernel.ConfUtils import ( addAlgs , + printOnDemand , + prntCmp , + hltContext , + setTheProperty , + getAlgo + ) +from Reconstruction import ( clusterFutureReco , + photonFutureReco , + electronFutureReco , + mergedPi0FutureReco ) + +from Configurables import CaloFutureDigitConf +from Configurables import CaloFuturePIDsConf +##from Configurables import GlobalRecoConf +from Configurables import GaudiSequencer + + +import logging +_log = logging.getLogger ('CaloFutureReco') + +import os +# ============================================================================= +## @class CaloFutureRecoConf +# Configurable for CaloFuturerimeter Reconstruction +# @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl +# @date 2008-07-17 +class CaloFutureRecoConf(LHCbConfigurableUser): + """ + Class/Configurable to define the calorimeter reconstruction + + """ + ## define the slots + __slots__ = { + ## + "Context" : '' # The context to run (default = offline) + , "MeasureTime" : False # Measure the time for sequencers + , "OutputLevel" : INFO # The global output level + ## + , 'Sequence' : None # The sequencer to add the CALOFUTURE reconstruction algorithms to + , 'RecList' : [ 'Digits' , + 'Clusters' , + 'Photons' , + 'MergedPi0s' , + 'SplitPhotons' , # the same action as 'MergedPi0s' + 'Electrons' ] # + , 'ForceDigits' : True # Force digits recontruction to be run with Clusters + , 'CreateADCs' : False # Create CaloFuture-ADCs + , 'UseTracks' : True # Use Tracks as Neutrality Criteria + , 'UseSpd' : False # Use Spd as Neutrality Criteria + , 'UsePrs' : False # Use Prs to select Neutral clusters + , 'UseTracksE' : True # Use Tracks as Charge Criteria + , 'UseSpdE' : True # Use Spd as Charged Criteria + , 'UsePrsE' : True # Use Prs to select Charged clusters + , 'UseTracksM' : True # Use Tracks for MergedPi0s-ID + , 'CaloFutureStandalone' : False # useTrackX = false + usePrs/Spd = true + , 'NeutralID' : False # Apply neutralID (CaloFuturePIDs is in charge + problems with onDemand to be fixed) + , 'EnableRecoOnDemand' : False # Enable Reco-On-Demand (only for components on RecList) + , 'TrackLocation' : '' # Track location (Neutral/Charged cluster selection with UseTrack(E) ) + , 'ClMatchTrTypes' : [] # Accepted track types for cluster matching (default Long, Downstream , TTracks) + , 'ExternalClusters' : '' # Start the reconstruction sequence from an external cluster container (HLT) + , 'FastReco' : False # faster reconstruction (HLT) + , 'SkipNeutrals' : False + , 'SkipCharged' : False + , 'ForceOnDemand' : False # force DoD for ALL components (incl. those not in RecList) + , 'PhotonPt' : 50.*MeV # Min Cluster Et + , 'ElectronPt' : 50.*MeV # Min Cluster Et + , 'MergedPi0Pt' : 1.5*GeV + , 'ClusterPt' : 0. + , 'MakeExternalClustersWithTag': '' + , 'NoSpdPrs' : False + , 'ClusterEnergyMasks' : [] + , 'ClusterPositionMasks' : [] + , 'Verbose' : False + , 'SetCounters' : 1 # Quiet is the default + ## + } + ## documentation lines + _propertyDocDct = { + ## + "Context" : """ The context to run """ + , "MeasureTime" : """ Measure the time for sequencers """ + , "OutputLevel" : """ The global output level """ + ## + , 'Sequence' : """ The sequencer to add the CALOFUTURE reconstruction algorithms to """ + , 'RecList' : """ The recontruction sketch """ + , 'ForceDigits' : """ Force digits recontruction to be run with Clusters """ + , 'CreateADCs' : """ Create CaloFuture-ADCs """ + , 'UseTracks' : """ Use Tracks as Neutrality criterion """ + , 'UseSpd' : """ Use Spd as Neutrality criterion """ + , 'UsePrs' : """ Use Prs as EM criterion for neutrals """ + , 'UseTracksE' : """ Use Tracks as Charge criterion """ + , 'UseSpdE' : """ Use Spd as Charge criterion """ + , 'UsePrsE' : """ Use Prs as EM criterion for charged """ + , 'UseTracksM' : """ Use Tracks for MergedPi0s-ID """ + , 'CaloFutureStandalone' : """ UseTrack = false + usePrs/Spd = true """ + , 'NeutralID' : """ Apply neutralID """ + , 'EnableRecoOnDemand' : """ Enable Reco-On-Demand (for components in RecList) """ + , 'TrackLocation' : """ TrackLocation (Photon/Electron selection)""" + , 'ClMatchTrTypes' : """ Accepted track types for cluster matching (default Long, Downstream , TTracks) """ + , 'SkipNeutrals' : """ Skip Neutral reco components in RecList""" + , 'SkipCharged' : """ Skip Charged reco components in RecList""" + , 'ForceOnDemand' : """ force DoD for ALL components""" + , 'FastReco' : """ Speed-up reconstruction (empty so far)""" + , 'ExternalClusters' : """ Start the reconstruction sequence from an external cluster container (HLT)""" + , 'PhotonPt' : """ Photon Hypo Pt cut """ + , 'ElectronPt' : """ Electron Hypo Pt cut """ + , 'MergedPi0Pt' : """ MergedPi0 Pt cut """ + , 'ClusterPt' : """ Cluster Pt """ + , 'MakeExternalClustersWithTag' :""" Build tagged external clusters in the sequence (only if ExternalClusters != '')""" + , 'NoSpdPrs' : """ Upgrade configuration without Prs/Spd - implies UsePrs/Spd = False """ + , 'ClusterEnergyMasks' : """ Set the cluster mask for energy evaluation (default : set from DB) """ + , 'ClusterPositionMasks': """ Set the cluster mask for position evaluation (default : set from DB) """ + , 'Verbose' : """ Verbose printout""" + , 'SetCounters' : """ Counters verbosity""" + ## + } + + ## used configurables + __used_configurables__ = ( + (CaloFutureDigitConf,None) , + ) + + ## configure processing of Digits + def digits ( self ) : + """ + Configure processing of Digits + """ + digitConf=CaloFutureDigitConf() + digitConf.Context="Offline" + digitConf.OutputLevel = self.getProp ('OutputLevel' ) + digitConf.EnableDigitsOnDemand = self.getProp ('EnableRecoOnDemand') + digitConf.CreateADCs = self.getProp ('CreateADCs' ) + digitConf.Verbose = self.getProp ('Verbose' ) + if self.getProp('NoSpdPrs') : + digitConf.Detectors = ['Ecal','Hcal'] + # deactivate Spd/Prs in DecoderDB + from DAQSys.Decoders import DecoderDB + from DAQSys.DecoderClass import Decoder + Decoder("CaloFutureDigitsFromRaw/FutureSpdFromRaw",active=False,conf=DecoderDB) + Decoder("CaloFutureDigitsFromRaw/FuturePrsFromRaw",active=False,conf=DecoderDB) + + return digitConf.digits() + + ## Configure reconstruction of Ecal Clusters + def clusters ( self ) : + """ + Configure reconstruction of Ecal Clusters + """ + cmp = clusterFutureReco ( self.getProp('Context') , + self.getProp('EnableRecoOnDemand' ) , + self.getProp('ClusterPt') , + self.getProp('FastReco') , + self.getProp('ExternalClusters') , + self.getProp('MakeExternalClustersWithTag'), + self.getProp('NoSpdPrs'), + self.getProp('ClusterEnergyMasks'), + self.getProp('ClusterPositionMasks'), + self.getProp('MergedPi0Pt') + ) + _log.info ('Configured Ecal Clusters Reco : %s ' % cmp.name() ) + + if self.getProp ( 'ForceDigits' ) : + ## insert digits into Cluster Sequence + cmp.Members = [ self.digits() ] + cmp.Members + + ## + return cmp + + ## reconstruct the photons + def photons ( self ) : + """ + Define the reconstruction of Photons + """ + uTracks = self.getProp ( 'UseTracks' ) + uSpd = self.getProp ( 'UseSpd' ) + uPrs = self.getProp ( 'UsePrs' ) + if self.getProp('CaloFutureStandalone') : + uTracks = False + uSpd = True + uPrs = True + + cmp = photonFutureReco ( self.getProp ( 'Context' ) , + self.getProp ( 'EnableRecoOnDemand') , + uTracks, + uSpd, + uPrs, + self.getProp( 'TrackLocation' ), + self.getProp( 'NeutralID' ) , + self.getProp('PhotonPt') , + self.getProp('FastReco') , + self.getProp('ExternalClusters') , + self.getProp('NoSpdPrs') , + self.getProp('ClMatchTrTypes') + ) + ## + _log.info ('Configured Single Photons Reco : %s ' % cmp.name() ) + return cmp + + ## Configure recontruction of Electrons + def electrons ( self ) : + """ + Configure recontruction of Electrons + """ + uTracks = self.getProp ( 'UseTracksE' ) + uSpd = self.getProp ( 'UseSpdE' ) + uPrs = self.getProp ( 'UsePrsE' ) + if self.getProp('CaloFutureStandalone') and not self.getProp( 'NoSpdPrs') : + uTracks = False + uSpd = True + uPrs = True + + cmp = electronFutureReco ( self.getProp( 'Context' ) , + self.getProp( 'EnableRecoOnDemand' ) , + uTracks, + uSpd, + uPrs, + self.getProp('TrackLocation') , + self.getProp('ElectronPt') , + self.getProp('FastReco') , + self.getProp('ExternalClusters'), + self.getProp('NoSpdPrs') , + self.getProp('ClMatchTrTypes') + ) + + + ## + _log.info ('Configured Electron Hypos Reco : %s ' % cmp.name() ) + return cmp + + ## Configure recontruction of Merged Pi0 + def mergedPi0s ( self ) : + """ + Configure recontruction of Merged Pi0 + """ + uTracks = self.getProp ( 'UseTracksM' ) + if self.getProp('CaloFutureStandalone') : + uTracks = False + + cmp = mergedPi0FutureReco ( self.getProp ( 'Context' ) , + self.getProp ( 'EnableRecoOnDemand' ) , + False , + self.getProp ( 'NeutralID' ) , + uTracks, + self.getProp('MergedPi0Pt') , + self.getProp('FastReco') , + self.getProp('ExternalClusters'), + self.getProp('NoSpdPrs'), + self.getProp('ClusterEnergyMasks'), + self.getProp('ClusterPositionMasks') + ) + + + ## + _log.info ('Configured Merged Pi0 Reco : %s ' % cmp.name() ) + return cmp + + ## Check the configuration + def checkConfiguration ( self ) : + """ + Check the configuration + """ + _log.debug('Configuration is not checked !') + + + def setCounterLevel( self) : + # == Counter level + from Configurables import ToolSvc,CounterLevel,CaloFutureDigitFilterTool + tsvc=ToolSvc() + tsvc.addTool(CounterLevel,name="CounterLevel") + tsvc.addTool(CaloFutureDigitFilterTool,'FutureFilterTool') + level= self.getProp('SetCounters') + _log.info( 'Configurabe : Counter level is %s ', level); + tsvc.CounterLevel.SetLevel=level + tsvc.FutureFilterTool.SetCounterLevel=level + + + + def printConf(self,verbose=False) : + if self.getProp('NoSpdPrs') : + _log.info("CaloFutureRecoConf : upgrade configuration without Spd/Prs") + if self.getProp('Verbose') or verbose: + _log.info ( self ) + + + ## Calorimeter Reconstruction Configuration + def applyConf ( self ) : + """ + Calorimeter Reconstruction Configuration + """ + + self.printConf() + + _log.info ('Apply CaloFutureRecoConf configuration for %s ', self.getProp('RecList')) + + recList = self.getProp ( 'RecList') + skipNeutrals = self.getProp('SkipNeutrals') + skipCharged = self.getProp('SkipCharged') + forceOnDemand = self.getProp('ForceOnDemand') + + seq = [] + + # configure all components for DoD + if forceOnDemand : + _log.info('Force Data-On-Demand for all components') + self.setProp ( 'EnableRecoOnDemand', 'True' ) + self.digits() + self.clusters() + self.photons() + self.mergedPi0s() + self.electrons() + + if self.getProp('NoSpdPrs') : + self.setProp('UseSpd',False) + self.setProp('UsePrs',False) + self.setProp('UseSpdE',False) + self.setProp('UsePrsE',False) + # configure the public getter tool + from Configurables import ToolSvc,CaloFutureGetterTool + tsvc=ToolSvc() + tsvc.addTool(CaloFutureGetterTool,name="CaloFutureGetter") + tsvc.CaloFutureGetter.DetectorMask=12 + + self.setCounterLevel() + + # add only the requested components to the sequence + if 'Digits' in recList : + addAlgs ( seq , self.digits() ) + CaloFutureDigitConf().printConf() + if 'Clusters' in recList : + addAlgs ( seq , self.clusters() ) + if 'Digits' not in recList : + CaloFutureDigitConf().printConf() + if not skipNeutrals : + if 'Photons' in recList : addAlgs ( seq , self.photons() ) + if 'MergedPi0s' in recList or 'SplitPhotons' in recList : addAlgs ( seq , self.mergedPi0s() ) + if not skipCharged : + if 'Electrons' in recList : addAlgs ( seq , self.electrons() ) + + setTheProperty ( seq , 'Context' , self.getProp ( 'Context' ) ) + setTheProperty ( seq , 'MeasureTime' , self.getProp ( 'MeasureTime' ) ) + if self.isPropertySet("OutputLevel") : + setTheProperty ( seq , 'OutputLevel' , self.getProp ( 'OutputLevel' ) ) + + if self.isPropertySet('Sequence') : + main = self.getProp('Sequence') + addAlgs ( main , seq ) + _log.info ('Configure main CaloFuture Reco Sequence : %s '% main.name() ) + if self.getProp('Verbose') : + _log.info ( prntCmp ( main ) ) + else : + _log.info ('Configure CaloFuturerimeter Reco blocks ' ) + if self.getProp('Verbose') : + _log.info ( prntCmp ( seq ) ) + + if self.getProp( 'EnableRecoOnDemand' ) : + _log.info("CaloFutureReco onDemand enabled") + if self.getProp('Verbose') : + _log.info ( printOnDemand () ) + + +# ============================================================================= +## @class HltCaloFutureRecoConf +# Configurable for CaloFuturerimeter Reconstruction in Hlt context +# @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl +# @date 2008-07-17 +class HltCaloFutureRecoConf(CaloFutureRecoConf): + """ + Class/Configurable to define the calorimeter reconstruction for Hlt + + """ + __slots__ = {} + + ## Check the configuration + def checkConfiguration ( self ) : + """ + Check the configuration + """ + if not hltContext ( self.getProp('Context') ) : + raise AttributeError, 'Invalid context for HltCaloFutureRecoConf' + +# ============================================================================= +## @class OffLineCaloFutureRecoConf +# Configurable for CaloFuturerimeter Reconstruction in OffLine context +# @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl +# @date 2008-07-17 +class OffLineCaloFutureRecoConf(CaloFutureRecoConf): + """ + Class/Configurable to define the calorimeter reconstruction for Off-Line + + """ + __slots__ = {} + + ## Check the configuration + def checkConfiguration ( self ) : + """ + Check the configuration + """ + if hltContext ( self.getProp( 'Context' ) ) : + raise AttributeError, 'Invalid context for OffLineCaloFutureRecoConf' + +# ============================================================================= +class CaloFutureProcessor( CaloFutureRecoConf,LHCbConfigurableUser ): + """ + Class/Configurable to define the Full calorimeter reconstruction + """ + +## -- re-use CaloFutureRecoConf and add caloPIDs and ProtoP [double-inheritance fails due to conflicts] + + ## define the additional slots + __slots__ = { + 'CaloFutureReco' : True , ## process CaloFutureReco part + 'CaloFuturePIDs' : True , ## process CaloFuturePID part + 'EnableOnDemand' : False, ## overwrite EnableRecoOnDemand & EnablePIDsOnDemand + 'ProtoOnDemand' : False, + 'NeutralProtoLocation':'', + 'ChargedProtoLocation':'', + 'CaloFutureSequencer' : None, + 'ProtoSequencer' : None, + 'NeutralProtoSequencer' : None, + 'ChargedProtoSequencer' : None, + ## PRIVATE TrackTypes & TrackCuts property (as in GlobalRecoConf) : for ChargedProto creation OnD. + "TrackTypes" : [ "Long", "Upstream", "Downstream" ], + "TrackCuts" : { "Long" : { "Chi2Cut" : [0,10] } + ,"Upstream" : { "Chi2Cut" : [0,10] } + ,"Downstream" : { "Chi2Cut" : [0,10] } }, + ## + 'DataType' : 'MC09', + 'CaloFuturePIDTrTypes' : [] , + 'BremPIDTrTypes' : [] , + 'PIDList' : ['InAcceptance', + 'Match', + 'Energy', + 'Chi2', + 'DLL', + 'NeutralPID' + ] # List of PID fragments to be included (alternative full sequence per technique : [ 'EcalPID', 'BremPID', 'HcalPID','PrsPID', 'SpdPID', 'NeutralPID' ] ) + } + + + ## used configurables + __used_configurables__ = ( + (CaloFuturePIDsConf,None ), + (CaloFutureDigitConf,None ) + ) + + def caloPIDs ( self ) : + + pidConf=CaloFuturePIDsConf('CaloFuturePIDsFor'+self.getName()) + pidConf.Verbose=self.getProp('Verbose') + pidConf.Context=self.getProp( 'Context') + pidConf.EnablePIDsOnDemand=self.getProp( 'EnableOnDemand' ) + pidConf.PIDList=self.getProp('PIDList') + pidConf.TrackLocation=self.getProp('TrackLocation') + pidConf.ClMatchTrTypes=self.getProp('ClMatchTrTypes') + pidConf.CaloFuturePIDTrTypes=self.getProp('CaloFuturePIDTrTypes') + pidConf.BremPIDTrTypes=self.getProp('BremPIDTrTypes') + pidConf.SkipNeutrals=self.getProp('SkipNeutrals') + pidConf.SkipCharged=self.getProp('SkipCharged') + pidConf.FastPID=self.getProp('FastReco') + pidConf.ExternalClusters=self.getProp('ExternalClusters') + pidConf.NoSpdPrs=self.getProp('NoSpdPrs') + pidConf.DataType= self.getProp('DataType') + pidConf.OutputLevel=self.getProp('OutputLevel') + pidConf.printConf() + ## + return pidConf.caloPIDs() + + def caloFutureSequence ( self, tracks='' ) : + _log.info("TEST: caloFutureSequence") + seq = GaudiSequencer ( self.getName() + 'CaloFutureSeq' ) + seq.Members[:] = [] + self.setProp("CaloFutureSequencer", seq) + context = self.getProp('Context') + if context == '' : + self.setProp("Context", self.getName() ) + if tracks: + self.setProp("TrackLocation", tracks) + _log.info("CaloFutureProcessor.caloFutureSequence : update TrackLocation %s: " % tracks) + + self.applyConf() + return seq + def protoSequence ( self, tracks='' , protoPrefix = '' ) : + _log.info("TEST: photonFutureSequence") + seq = GaudiSequencer (self.getName() + 'ProtoPUpdateSeq' ) + seq.Members[:] = [] + self.setProp("ProtoSequencer", seq) + if self.getProp('Context') == '' : + self.setProp("Context", self.getName() ) + if tracks: + self.setProp("TrackLocation", tracks) + _log.info("CaloFutureProcessor.protoSequence : update TrackLocation %s: " % tracks) + if protoPrefix: + nloc = os.path.join(protoPrefix, 'Neutrals') + cloc = os.path.join(protoPrefix, 'Charged') + self.setProp("ChargedProtoLocation",cloc) + self.setProp("NeutralProtoLocation",nloc) + _log.info("CaloFutureProcessor.protoSequence : update protoP Location with prefix %s: " % protoPrefix) + self.applyConf() + return seq + def chargedProtoSequence ( self, tracks = '', protoPrefix = '' ) : + _log.info("TEST: chargedProtoFutureSequence") + seq = GaudiSequencer ( self.getName() + 'ChargedProtoPUpdateSeq' ) + seq.Members[:] = [] + self.setProp("ChargedProtoSequencer", seq) + if self.getProp('Context') == '' : + self.setProp("Context", self.getName() ) + if tracks: + self.setProp("TrackLocation", tracks) + _log.info("CaloFutureProcessor.chargedProtoSequence : update TrackLocation %s: " % tracks) + if protoPrefix: + cloc = protoPrefix + if not cloc.endswith('Charged'): + cloc = os.path.join( protoPrefix, 'Charged') + self.setProp("ChargedProtoLocation",cloc) + _log.info("CaloFutureProcessor.chargedProtoSequence : update protoP Location with prefix %s: " % protoPrefix) + + self.applyConf() + return seq + def neutralProtoSequence ( self, tracks = '', protoPrefix = '' ) : + _log.info("TEST: neutralProtoSequence") + seq = GaudiSequencer ( self.getName() + 'NeutralProtoPUpdateSeq' ) + seq.Members[:] = [] + self.setProp("NeutralProtoSequencer", seq) + if self.getProp('Context') == '' : + self.setProp("Context", self.getName() ) + if tracks: + self.setProp("TrackLocation", tracks ) + _log.info("CaloFutureProcessor.neutralProtoSequence : update TrackLocation %s: " % tracks) + if protoPrefix: + nloc = protoPrefix + if not nloc.endswith('Neutrals'): + nloc = os.path.join( protoPrefix,'Neutrals' ) + self.setProp("NeutralProtoLocation",nloc) + _log.info("CaloFutureProcessor.neutralProtoSequence : update protoP Location with prefix %s: " % protoPrefix) + self.applyConf() + return seq + def sequence ( self, tracks='', protoPrefix = '' ) : + _log.info("TEST: sequence") + seq = GaudiSequencer ( self.getName() + 'FullSeq' ) + seq.Members[:] = [] + self.setProp("Sequence", seq) + if self.getProp('Context') == '' : + self.setProp("Context", self.getName() ) + if tracks: + self.setProp("TrackLocation", tracks) + _log.info("CaloFutureProcessor.sequence : update TrackLocation %s: " % tracks) + if protoPrefix: + nloc = os.path.join(protoPrefix, 'Neutrals') + cloc = os.path.join(protoPrefix, 'Charged') + self.setProp("ChargedProtoLocation",cloc) + self.setProp("NeutralProtoLocation",nloc) + _log.info("CaloFutureProcessor.sequence : update protoP Location with prefix %s: " % protoPrefix) + + self.applyConf() + return seq + + + def printConf( self,verbose=False) : + if self.getProp('NoSpdPrs') : + _log.info("CaloFutureProcessor : upgrade configuration without Spd/Prs") + if self.getProp('Verbose') or verbose: + _log.info ( self ) + + + def applyConf ( self) : + + _log.info ('Apply CaloFutureProcessor configuration for %s and %s', self.getProp('RecList'), self.getProp('PIDList')) + + self.printConf() + + knownMasks = ['3x3','2x2','SwissCross'] + + for tag in self.getProp('ClusterEnergyMasks') : + if tag not in knownMasks : + raise AttributeError,'ClusterEnergyMasks contains unknown tag'+tag+' -should be in' + knownMasks + for tag in self.getProp('ClusterPositionMasks') : + if tag not in knownMasks : + raise AttributeError,'PositionEnergyMasks contains unknown tag '+tag+' -should be in' + knownMasks + + + + from Configurables import ( GaudiSequencer, + ChargedProtoParticleAddEcalInfo, + ChargedProtoParticleAddBremInfo, + ChargedProtoParticleAddHcalInfo, + ChargedProtoParticleAddPrsInfo, + ChargedProtoParticleAddSpdInfo, + FutureChargedProtoParticleAddEcalInfo, + FutureChargedProtoParticleAddBremInfo, + FutureChargedProtoParticleAddHcalInfo, + FutureChargedProtoParticleAddPrsInfo, + FutureChargedProtoParticleAddSpdInfo, + ChargedProtoParticleMaker, + ChargedProtoCombineDLLsAlg + ) + + fullSeq = [] + + + if self.getName() == 'CaloFutureProcessor' and ( self.getProp('Context') == '' or self.getProp('Context') == 'CaloFutureProcessor' ) : + self.setProp('Context','Offline') # default is Offline is neither context nor name is specified + + # prepare the NoSpdPrs configuration + if self.getProp('NoSpdPrs') : + self.setProp('UseSpd',False) + self.setProp('UsePrs',False) + self.setProp('UseSpdE',False) + self.setProp('UsePrsE',False) + # configure the public getter tool + from Configurables import ToolSvc,CaloFutureGetterTool + tsvc=ToolSvc() + tsvc.addTool(CaloFutureGetterTool,name="CaloFutureGetter") + tsvc.CaloFutureGetter.DetectorMask=12 + + self.setCounterLevel() + # overwrite Reco & PID onDemand + dod = self.getProp('EnableOnDemand') + pdod = self.getProp('ProtoOnDemand') + + if dod : + pdod = dod + self.setProp('EnableRecoOnDemand',dod) + + ## define the calo sequence + caloSeq = [] + + doReco = self.getProp('CaloFutureReco') + doPIDs = self.getProp('CaloFuturePIDs') + skipNeutrals = self.getProp('SkipNeutrals') + skipCharged = self.getProp('SkipCharged') + context = self.getProp('Context') + + + # CaloFutureReco sequence + recoSeq = getAlgo( GaudiSequencer , "CaloFutureRecoFor"+self.getName() , context ) + recoSeq.Members[:] = [] + recList = self.getProp ( 'RecList') + + + # configure all components by default (DoD) + forceOnDemand = self.getProp('ForceOnDemand') + if forceOnDemand : + self.setProp('EnableOnDemand','True') + self.setProp('EnableRecoOnDemand','True') + dig=self.digits() + clu=self.clusters() + pho=self.photons() + mer=self.mergedPi0s() + ele=self.electrons() + + + # add only the requested components to the sequence + if 'Digits' in recList : + addAlgs ( recoSeq , self.digits() ) + CaloFutureDigitConf().printConf() + if 'Clusters' in recList : + addAlgs ( recoSeq , self.clusters() ) + if 'Digits' not in recList : + CaloFutureDigitConf().printConf() + + if not skipNeutrals : + if 'Photons' in recList : addAlgs ( recoSeq , self.photons() ) + if 'MergedPi0s' in recList or 'SplitPhotons' in recList : addAlgs ( recoSeq , self.mergedPi0s() ) + if not skipCharged : + if 'Electrons' in recList : addAlgs ( recoSeq , self.electrons() ) + + # CaloFuturePIDs sequence + # pidSeq = getAlgo( GaudiSequencer , "CaloFuturePIDsSeq" , context ) + # addAlgs ( pidSeq , self.caloPIDs () ) + + pidSeq=self.caloPIDs() + + + # update CaloFutureSequence + if doReco : + addAlgs ( caloSeq , recoSeq ) + if doPIDs : + addAlgs ( caloSeq , pidSeq ) + + + ## propagate the global properties + setTheProperty ( caloSeq , 'Context' , self.getProp ( 'Context' ) ) + setTheProperty ( caloSeq , 'MeasureTime' , self.getProp ( 'MeasureTime' ) ) + if self.isPropertySet("OutputLevel") : + setTheProperty ( caloSeq , 'OutputLevel' , self.getProp ( 'OutputLevel' ) ) + + + ######## ProtoParticle update ########## + protoSeq = [] + cProtoSeq = [] + nProtoSeq = [] + # ProtoParticle locations + nloc = self.getProp('NeutralProtoLocation') + cloc = self.getProp('ChargedProtoLocation') + # try automatic location if not explicit for HLT's sequence + if hltContext ( self.getProp('Context') ) : + if not nloc: + nloc = os.path.join( context, 'ProtoP/Neutrals' ) + if not cloc: + cloc = os.path.join( context, 'ProtoP/Charged' ) + + # ChargedProtoParticle + if not self.getProp('SkipCharged') : + suffix="For"+self.getName() + if self.getProp("NoSpdPrs") : + ecal = getAlgo( FutureChargedProtoParticleAddEcalInfo,"FutureChargedProtoPAddEcal"+suffix, context) + brem = getAlgo( FutureChargedProtoParticleAddBremInfo,"FutureChargedProtoPAddBrem"+suffix, context) + hcal = getAlgo( FutureChargedProtoParticleAddHcalInfo,"FutureChargedProtoPAddHcal"+suffix, context) + else: + ecal = getAlgo( ChargedProtoParticleAddEcalInfo,"ChargedProtoPAddEcal"+suffix, context) + brem = getAlgo( ChargedProtoParticleAddBremInfo,"ChargedProtoPAddBrem"+suffix, context) + hcal = getAlgo( ChargedProtoParticleAddHcalInfo,"ChargedProtoPAddHcal"+suffix, context) + if not self.getProp('NoSpdPrs') : + prs = getAlgo( ChargedProtoParticleAddPrsInfo ,"ChargedProtoPAddPrs"+suffix , context) + spd = getAlgo( ChargedProtoParticleAddSpdInfo ,"ChargedProtoPAddSpd"+suffix , context) + comb = getAlgo( ChargedProtoCombineDLLsAlg, "ChargedProtoPCombineDLLs"+suffix, context) + + # ChargedProtoP Maker on demand (not in any sequencer) #### + maker = getAlgo( ChargedProtoParticleMaker, "ChargedProtoMaker" , context, cloc , pdod ) + # protoPMaker settings (from GlobalRecoConf) + from Configurables import DelegatingTrackSelector,GaudiSequencer + ## ppConf = GlobalRecoConf('DummyConf',RecoSequencer=GaudiSequencer('DummySeq')) + ##ttypes = ppConf.getProp('TrackTypes') + ##tcuts = ppConf.getProp('TrackCuts') + + ttypes = self.getProp('TrackTypes') + tcuts = self.getProp('TrackCuts') + + maker.addTool( DelegatingTrackSelector, name="TrackSelector" ) + maker.TrackSelector.TrackTypes = ttypes + from Configurables import TrackSelector + for type in ttypes : + maker.TrackSelector.addTool(TrackSelector,name=type) + ts = getattr(maker.TrackSelector,type) + ts.TrackTypes = [type] + if type in tcuts : + for name,cut in tcuts[type].iteritems() : + ts.setProp("Min"+name,cut[0]) + ts.setProp("Max"+name,cut[1]) + ######################################### + if cloc: + maker.Output = cloc + + if not hltContext( self.getProp( 'Context' ) ) and self.getProp('TrackLocation'): + maker.Inputs = [self.getProp('TrackLocation')] + + # location + if cloc: + ecal.ProtoParticleLocation = cloc + brem.ProtoParticleLocation = cloc + hcal.ProtoParticleLocation = cloc + if not self.getProp('NoSpdPrs') : + prs.ProtoParticleLocation = cloc + spd.ProtoParticleLocation = cloc + comb.ProtoParticleLocation = cloc + # Fill the sequence + cpSeq = getAlgo( GaudiSequencer , self.getName()+"ChargedProtoPCaloFutureUpdateSeq", context ) + cpSeq.Members = [ ecal,brem,hcal ] + if not self.getProp('NoSpdPrs') : + cpSeq.Members += [ prs,spd ] + cpSeq.Members += [ comb ] + addAlgs(protoSeq , cpSeq ) + addAlgs(cProtoSeq, cpSeq.Members ) + + + + # NeutralProtoParticleProtoP components + if not self.getProp('SkipNeutrals') : + from Configurables import NeutralProtoPAlg, FutureNeutralProtoPAlg + suffix="For"+self.getName() + if self.getProp('NoSpdPrs') : + neutral = getAlgo( FutureNeutralProtoPAlg,"FutureNeutralProtoPMaker"+suffix, context) + else: + neutral = getAlgo( NeutralProtoPAlg,"NeutralProtoPMaker"+suffix, context) + # location + if nloc: + neutral.ProtoParticleLocation = nloc + # fill the sequence + addAlgs(protoSeq, neutral ) + addAlgs(nProtoSeq, neutral ) + + + ## propagate the global properties + setTheProperty ( protoSeq , 'Context' , self.getProp ( 'Context' ) ) + setTheProperty ( protoSeq , 'MeasureTime' , self.getProp ( 'MeasureTime' ) ) + if self.isPropertySet("OutputLevel") : + setTheProperty ( protoSeq , 'OutputLevel' , self.getProp ( 'OutputLevel' ) ) + + setTheProperty ( nProtoSeq , 'Context' , self.getProp ( 'Context' ) ) + setTheProperty ( nProtoSeq , 'MeasureTime' , self.getProp ( 'MeasureTime' ) ) + if self.isPropertySet("OutputLevel") : + setTheProperty ( nProtoSeq , 'OutputLevel' , self.getProp ( 'OutputLevel' ) ) + + setTheProperty ( cProtoSeq , 'Context' , self.getProp ( 'Context' ) ) + setTheProperty ( cProtoSeq , 'MeasureTime' , self.getProp ( 'MeasureTime' ) ) + if self.isPropertySet("OutputLevel") : + setTheProperty ( cProtoSeq , 'OutputLevel' , self.getProp ( 'OutputLevel' ) ) + + # Full sequence + addAlgs( fullSeq, caloSeq ) + addAlgs( fullSeq, protoSeq ) + + + ## define the sequencers + if self.isPropertySet('Sequence') : + main = self.getProp('Sequence') + main.Members[:]=[] + addAlgs ( main , fullSeq ) + _log.info ('Configure full sequence %s with '% main.name() ) + _log.info (' Reco : %s '% self.getProp('RecList')) + _log.info (' PIDs : %s '% self.getProp('PIDList')) + _log.info (' and ProtoParticle update') + if self.getProp('Verbose') : + _log.info ( prntCmp ( main ) ) + + if self.isPropertySet('CaloFutureSequencer') : + calo = self.getProp('CaloFutureSequencer') + calo.Members[:]=[] + addAlgs ( calo , caloSeq ) + _log.info ('Configure caloFutureSequencer : %s '% calo.name() ) + if self.getProp('Verbose') : + _log.info ( prntCmp ( calo ) ) + + if self.isPropertySet('ProtoSequencer') : + proto = self.getProp('ProtoSequencer') + proto.Members[:]=[] + addAlgs ( proto , protoSeq ) + _log.info ('Configure protoSequencer : %s '% proto.name() ) + if self.getProp('Verbose') : + _log.info ( prntCmp ( proto ) ) + + + if self.isPropertySet('ChargedProtoSequencer') : + cproto = self.getProp('ChargedProtoSequencer') + cproto.Members[:]=[] + addAlgs ( cproto , cProtoSeq ) + _log.info ('Configure chargedProtoSequencer : %s '% cproto.name() ) + if self.getProp('Verbose') : + _log.info ( prntCmp ( cproto ) ) + + if self.isPropertySet('NeutralProtoSequencer') : + nproto = self.getProp('NeutralProtoSequencer') + nproto.Members[:]=[] + addAlgs ( nproto , nProtoSeq ) + _log.info ('Configure neutralProtoSequencer : %s '% nproto.name() ) + if self.getProp('Verbose') : + _log.info ( prntCmp ( nproto ) ) + + if self.getProp( 'EnableOnDemand' ) : + _log.info("CaloFutureProcessor onDemand enabled") + if self.getProp('Verbose') : + _log.info ( printOnDemand () ) + + +##################################### +class CaloFutureLines(LHCbConfigurableUser): + """ + Class/Configurable to define the HLT2 fast reconstruction for high-ET photon, low-ET photon/pi0 & low-ET electrons + """ + + +# __used_configurables__ = [ CaloFutureProcessor ] + + ## define the additional slots + __slots__ = { + "Context" : '' , # The context to run (default = offline) + 'TrackLocation' : '', # Track location (Neutral/Charged cluster selection with UseTrack(E) ) + 'HighPhoton' : True , ## process the highEt-threshold photon reconstruction + 'LowPhoton' : True , ## process the lowEt-threshold photon reconstruction + 'LowElectron' : True , ## process the LowEt-threshold electron reconstruction + 'EnableOnDemand' : False, ## overwrite EnableRecoOnDemand & EnablePIDsOnDemand + 'HighEt' : 2000.*MeV , + 'LowEt' : 300.*MeV, + 'ClusterEtFactor' : 1., # pre-cut on cluster Et is factor * Low(High)ET (should be <=1) + 'L0CaloFuture2CaloFuture' : True, + 'ClusterizationLevel': 2, # clusterizationLevel (when L0CaloFuture2CaloFuture == True only) + 'ProtoOnDemand' : False, + 'Sequencer' : None, + 'OutputLevel' : INFO, + 'HighEtProtoPPrefix' : '', + 'LowEtProtoPPrefix' : '', + 'NoSpdPrs' : False + } + + + + + def sequence ( self, tracks='' ) : + _log.info("TEST: def sequence") + seq = GaudiSequencer ( 'CaloFutureLines' + self.getName() ) + seq.Members[:] = [] + self.setProp("Sequencer", seq) + context = self.getProp('Context') + if context == '' : + self.setProp("Context", self.getName() ) + self.setProp("TrackLocation", tracks) + self.applyConf() + return seq + + + def applyConf ( self ) : + + + from Configurables import ( GaudiSequencer, + HltL0CaloFutureCandidates + ) + + + if self.getName() == 'CaloFutureLines' and ( self.getProp('Context') == '' or self.getProp('Context') == 'CaloFutureLines' ) : + self.setProp('Context','Offline') # default is Offline is neither context nor name is specified + + + + # overwrite Reco & PID onDemand + dod = self.getProp('EnableOnDemand') + pdod = self.getProp('ProtoOnDemand') + if dod : + pdod = dod + + trackLocation = self.getProp('TrackLocation') + + ### + caloLines = GaudiSequencer( 'CaloFutureLinesSeq' + self.getName() ) + caloLines.Members[:] = [] + + if self.getProp('L0CaloFuture2CaloFuture') : + l0calo2calo=HltL0CaloFutureCandidates('L0CaloFuture2CaloFuture') + if self.getProp('ClusterizationLevel') > 0 : + level = self.getProp('ClusterizationLevel') + l0calo2calo.ClusterizationLevel=level + addAlgs( caloLines, l0calo2calo ) + tagHighP = '' + tagLowP = '' + tagLowE = '' + else : + tagHighP = 'HighPhoton' + tagLowP = 'LowPhoton' + tagLowE = 'LowElectron' + + name = self.getName() + fac = self.getProp('ClusterEtFactor') + + if self.getProp('HighPhoton') : + context = self.getProp('Context') + if context != '' : + context = context +'HighPhoton' + hp = CaloFutureProcessor(name+'HighPhoton' + ,TrackLocation = trackLocation + ,Context = context + ,RecList = ['Digits','Clusters','Photons'] + ,CaloFuturePIDs = False + ,ExternalClusters="/Event/Rec/Calo/HighEtPhotons" + ,ClusterPt = self.getProp('HighEt')*fac + ,PhotonPt = self.getProp('HighEt') + ,MakeExternalClustersWithTag = tagHighP + ,NoSpdPrs=self.getProp('NoSpdPrs') + ) + + addAlgs( caloLines, hp.caloFutureSequence(tracks=trackLocation) ) + + if self.getProp('HighEtProtoPPrefix') == '' : + hploc = name+'HighPhoton/ProtoP' + else : + hploc = self.getProp('HighEtProtoPPrefix') + addAlgs( caloLines, hp.neutralProtoSequence(protoPrefix = hploc, tracks=trackLocation) ) + + if self.getProp('LowPhoton') : + context = self.getProp('Context') + if context != '' : + context = context +'LowPhoton' + lp = CaloFutureProcessor(name+'LowPhoton' + ,TrackLocation = trackLocation + ,Context = context + ,RecList = ['Digits','Clusters','Photons','MergedPi0s','SplitPhotons'] + ,ExternalClusters="/Event/Rec/Calo/LowEtPhotons" + ,CaloFuturePIDs = False + ,ClusterPt = self.getProp('LowEt')*fac + ,PhotonPt = self.getProp('LowEt') + ,MakeExternalClustersWithTag = tagLowP + ,NoSpdPrs=self.getProp('NoSpdPrs') + ) + addAlgs( caloLines , lp.caloFutureSequence(tracks=trackLocation) ) + if self.getProp('LowEtProtoPPrefix') == '' : + lploc = name+'LowPhoton/ProtoP' + else : + lploc = self.getProp('LowEtProtoPPrefix') + addAlgs( caloLines , lp.neutralProtoSequence(protoPrefix=lploc, tracks=trackLocation)) + + + if self.getProp('LowElectron') : + context = self.getProp('Context') + if context != '' : + context = context +'LowElectron' + le = CaloFutureProcessor(name+'LowElectron' + ,TrackLocation = trackLocation + ,Context = context + ,RecList = ['Digits','Clusters','Electrons'] + ,ExternalClusters="/Event/Rec/Calo/LowEtElectrons" + ,ClusterPt = self.getProp('LowEt')*fac + ,ElectronPt = self.getProp('LowEt') + ,SkipNeutrals = True + ,ProtoOnDemand = pdod + ,MakeExternalClustersWithTag = tagLowE + ,NoSpdPrs=self.getProp('NoSpdPrs') + ) + addAlgs( caloLines , le.caloFutureSequence(tracks=trackLocation)) + if self.getProp('LowEtProtoPPrefix') == '' : + leloc = name+'LowElectron/ProtoP' + else : + leloc = self.getProp('LowEtProtoPPrefix') + addAlgs( caloLines , le.chargedProtoSequence(protoPrefix=leloc, tracks=trackLocation)) + + + caloLines.IgnoreFilterPassed = True + ## propagate the global properties + if self.isPropertySet("OutputLevel") : + setTheProperty ( caloLines , 'OutputLevel' , self.getProp ( 'OutputLevel' ) ) + + ## define the sequencers + if self.isPropertySet('Sequencer') : + main = self.getProp('Sequencer') + addAlgs ( main , caloLines ) + + + +# ============================================================================= +if '__main__' == __name__ : + print __doc__ + print __author__ + print __version__ + + + diff --git a/CaloFuture/CaloFutureReco/python/CaloFutureReco/Corrections.py b/CaloFuture/CaloFutureReco/python/CaloFutureReco/Corrections.py new file mode 100644 index 0000000000000000000000000000000000000000..0580acb12b0bd8bd8f0375a3f1dfcf7d1a2d8c46 --- /dev/null +++ b/CaloFuture/CaloFutureReco/python/CaloFutureReco/Corrections.py @@ -0,0 +1,153 @@ + +#!/usr/bin/env python +# ============================================================================= +# $Id: Corrections.py,v 1.4 2010-05-20 09:47:06 odescham Exp $ +# ============================================================================= +## @file CaloFutureReco/Corrections.py +# Set of E/S/L-correction parameters +# @see CaloFutureECorrection +# @see CaloFutureSCorrection +# @see CaloFutureLCorrection +# @todo Move the correction to Conditions Data Base +# ============================================================================= +""" +Set of CaloFuture E/S/L-correction parameters +""" +# ============================================================================= +__version__ = "CVS tag $Name: not supported by cvs2svn $, version $Revision: 1.4 $" +# ============================================================================= +__all__ = ( + 'eCorrection' , ## E-corretions + 'sCorrection' , ## S-corretions + 'lCorrection' , ## L-corretions + 'showerProfile' ## Transversal shower profile + ) +# ============================================================================= +from Gaudi.Configuration import log +# ============================================================================= +## function which sets the E-correction parameters +# @see CaloFutureECorrection +def eCorrection ( ecorr , version = None ) : + """ + Function which sets the E-correction parameters: + + >>> tool = ... + >>> eCorrection ( tool ) + """ + # ============================================================================ + # function #params Outer Middle Inner + # ============================================================================ + ecorr.Parameters["alphaG"] = [ 0 , 1 , 1.0 , 1.0 , 1.0 ] + ecorr.Parameters["alphaE"] = [ 0 , 2 , 1.0105 , 1.0208 , 1.0325 , 0.11561E-06 , 0.33802E-07 , -0.28272E-07 ] + ecorr.Parameters["alphaB"] = [ 0 , 2 , 1.0159 , 1.0210 , 1.0256 , -0.67500E-01 ,-0.78525E-01 , -0.8901E-01 ] + ecorr.Parameters["alphaX"] = [ 0 , 2 , 1,1,1, 0. , 0.0171 , 0.0315 ] + ecorr.Parameters["alphaY"] = [ 0 , 2 , 1,1,1, 0. , 0.0362 , 0.0479 ] + ecorr.Parameters["beta"] = [ 1 , 1 , 8.3 , 8.8 , 9.5 ] + ecorr.Parameters["globalC"] = [ 0 , 1 , 0.977 , 0.977 , 0.977 ] + + ## + log.debug ('Configure E-Corrections for Ecal hypotheses: %s' % ecorr.name () ) + # ecorr.OutputLevel = 2 + return ecorr + +# ============================================================================= +## function which sets the S-correction parameters +# @see CaloFutureSCorrection +def sCorrection ( scorr , version = None ) : + """ + Function which sets the S-correction parameters: + + >>> tool = ... + >>> sCorrection ( tool ) + """ + scorr.Parameters["shapeX"] = [ 5 , 1 , 0.102 , 0.129 , 0.144] + scorr.Parameters["shapeY"] = [ 5 , 1 , 0.102 , 0.129 , 0.144] + scorr.Parameters["residual"] = [ 1 , 8 , + -0.47496E-03, -0.97712E-05, -0.14401E-03, + 0.44911 , 0.33898 , 0.29037, + -0.34187E-01, 0.14566E-01, 0.28848E-01, + -9.0335 , -5.9958 , -5.1697, + 0.46190 , -0.13533 , -0.34664, + 53.041 , 32.711 , 26.885, + -1.2801 , 0.33460E-01, 0.99928, + -97.865 ,-58.743 ,-45.032] + scorr.Parameters["asymP"] = [ 1 , 3 , + 0.24742E-01, 0.28587E-01, 0.19870E-01, + 0.11487E-01, 0.11557E-01, 0.38043E-02, + -0.32640 ,-0.31548 ,-0.21436] + scorr.Parameters["asymM"] = [ 1 , 3 , + -0.29386E-01,-0.28587E-01,-0.19870E-01, + 0.11472E-01, 0.11557E-01, 0.38043E-02, + 0.35928 , 0.31548 , 0.21436] + ## + log.debug ('Configure S-Corrections for Ecal hypotheses: %s' % scorr.name () ) + return scorr + + +# ============================================================================= +## function which sets the L-correction parameters +# @see CaloFutureLCorrection +def lCorrection ( lcorr , version = None ) : + """ + Function which sets the L-correction parameters: + + >>> tool = ... + >>> lCorrection ( tool ) + """ + lcorr.Parameters["gamma0"] = [ 1 , 1 , 22.305 , 19.053 , 17.936 ] + lcorr.Parameters["gammaP"] = [ 2 , 2 , 2.04 , 1.53 , 1.15 , -0.0281, -0.455, -0.0392] + lcorr.Parameters["delta0"] = [ 1 , 1 , 49.04 , 51.87 , 45.54 ] + lcorr.Parameters["deltaP"] = [ 2 , 2 , 4.38 , 4.15 , 4.02 , -0.0247, -0.0597 , -0.0308 ] + + ## + log.debug ('Configure L-Corrections for Ecal hypotheses: %s' % lcorr.name () ) + return lcorr + + + +# ============================================================================= +## function which provide the Transversal Shower profile (for MergedPi0 reconstruction) +# @see CaloFutureMergedPi0ALg +def showerProfile ( shape , version = None ) : + """ + Function which sets the E-correction parameters: + """ + + # ============================================================================ + # function #params Outer Middle Inner + # ============================================================================ + shape.Parameters["profile"] = [6 , 10 , + -0.0060, 0.0464 ,0.0981, + 2.4956, 2.0384, 2.2529, + 115.0827, 36.5885, 33.8837, + 9.8842, 8.0260, 8.0532, + 0.0320, 0.0460, 0.0654, + 2.0982, 2.3936, 2.2046, + 1.0302, 1.0703, 1.1092, + 0.0409, 0.1611, 0.1645, + 0.0030, 0.0238, 0.0248, + -9.6135, -5.8899, -5.7248] + shape.Parameters["profileC"] = [6 , 10 , + 0.0486, 0.0882, 0.1111, + 2.7847, 1.7910, 1.7909, + 68.4815, 24.4324, 18.0852, + 9.0870, 7.4802, 7.1122, + 0.0116, 0.0258, 0.0261, + 1.2591, 2.7719, 1.3889, + 1.0464, 1.1294, 1.1846, + -0.0900, -0.0802, -0.0934, + 0.0005, 0.0024, 0.0029, + -12.9098, -9.7273, -8.9966] + + + ## + log.debug ('Configure showerShape for Ecal hypotheses: %s' % shape.name () ) + # shape.OutputLevel = 2 + return shape + + +# ============================================================================= +if '__main__' == __name__ : + print __doc__ + print __version__ + diff --git a/CaloFuture/CaloFutureReco/python/CaloFutureReco/Reconstruction.py b/CaloFuture/CaloFutureReco/python/CaloFutureReco/Reconstruction.py new file mode 100644 index 0000000000000000000000000000000000000000..f23dfcb360aaedb80c0c3ca0a50674576099ba8d --- /dev/null +++ b/CaloFuture/CaloFutureReco/python/CaloFutureReco/Reconstruction.py @@ -0,0 +1,458 @@ +#!/usr/bin/env python +# ============================================================================= +# $Id: Reconstruction.py,v 1.12 2010-05-20 09:47:06 odescham Exp $ +# ============================================================================= +## The major building blocks of CaloFuturerimeter Reconstruction +# @author Vanya BELYAEV Ivan.Belyaev@nikhe.nl +# @date 2008-07-17 +# ============================================================================= +""" +The major building blocks of CaloFuturerimeter Reconstruction +""" + +# ============================================================================= +__author__ = "Vanya BELYAEV Ivan.Belyaev@nikhef.nl" +__version__ = "CVS tag $Name: not supported by cvs2svn $, version $Revision: 1.12 $" +# ============================================================================= +__all__ = ( + 'clustersReco' , + 'photonsReco' , + 'mergedPi0sReco' + ) +# ============================================================================= +from Gaudi.Configuration import * + +from Configurables import GaudiSequencer + +from GaudiKernel.SystemOfUnits import MeV, GeV + + +from CaloKernel.ConfUtils import ( prntCmp , + addAlgs , + hltContext , + setTheProperty , + onDemand , + caloOnDemand , + getAlgo ) + +import logging +_log = logging.getLogger('CaloFutureReco') + +# ============================================================================= +## prepare the digits for the recontruction +def digitsFutureReco ( context , + enableRecoOnDemand , + createADC ) : + """ + Prepare the digits for the recontruction + """ + + from CaloFutureDAQ.CaloFutureDigits import caloDigits + + _log.warning('CaloFutureReco.digitsFutureReco is deprecated, use CaloFutureDigitConf instead') + + # warning : the caloDigits TES should be context-independent + return caloDigits ( context , + enableRecoOnDemand , + createADC ) + +## ============================================================================ +## define the recontruction of Ecal clusters +def clusterFutureReco ( context , enableRecoOnDemand , clusterPt = 0. , fastReco = False , external = '', makeTag=False, + noSpdPrs=False , masksE=[] , masksP=[] , mergedPi0Pt = 2* GeV) : + """ + Define the recontruction of Ecal Clusters + """ + + from Configurables import ( CaloFutureDigitFilterAlg , + CaloFutureDigitFilterTool , + FutureCellularAutomatonAlg , + CaloFutureShowerOverlap , + # CaloFutureSharedCellAlg , # obsolete + CaloFutureClusterCovarianceAlg , + CaloFutureClusterizationTool) + + # cluster TES is 'almost' context-independent : single HLT TES whatever the HLT-type else 'offline' TES + ## Warning MUST be synchronous with CaloFutureAlgUtils TES settings + ### Exception when external clusters location is given + + if external == '' : + _cont = context + if '' != context and 'OFFLINE' != _cont.upper() and _cont.upper().find( 'HLT' ) != -1 : + context = 'Hlt' + else : + context = '' + elif makeTag != '': + context = makeTag + + + ## Define the context-dependent sequencer + seq = getAlgo ( GaudiSequencer , "ClusterFutureReco", context , "Rec/Calo/EcalClusters" , enableRecoOnDemand ) + + seq.Members[:]=[] + filter= getAlgo ( CaloFutureDigitFilterAlg , "CaloFutureDigitFilter",context) + if noSpdPrs : + filter.PrsFilter=0 + filter.SpdFilter=0 + + clust = getAlgo ( FutureCellularAutomatonAlg , "FutureEcalClust" , context ) +# share = getAlgo ( CaloFutureSharedCellAlg , "EcalShare" , context ) # obsolete + share = getAlgo ( CaloFutureShowerOverlap , "FutureEcalShare" , context ) + covar = getAlgo ( CaloFutureClusterCovarianceAlg , "FutureEcalCovar" , context ) + + if masksE != [] : + share.EnergyTags = masksE + covar.EnergyTags = masksE + if masksP != [] : + share.PositionTags = masksP + covar.PositionTags = masksP + + if external != '' : # use non-default clusters + share.InputData = external + covar.InputData = external + if makeTag != '' : # make the non-default clusters + seq.Members += [ filter, clust ] + clust.OutputData = external + else : + seq.Members += [ filter, clust ] # make default clusters + + + if clusterPt > 0 : + from Configurables import CaloFutureClusterizationTool + clust.addTool(CaloFutureClusterizationTool,'CaloFutureClusterizationTool') + clust.CaloFutureClusterizationTool.ETcut = clusterPt + clust.CaloFutureClusterizationTool.withET = True + + seq.Members += [ share , covar ] + setTheProperty ( seq , 'Context' , context ) + + + ## setup onDemand for SplitClusters + if enableRecoOnDemand : + splitSeq = mergedPi0Reco( context , enableRecoOnDemand , True, False, False,mergedPi0Pt,False,'',noSpdPrs,masksE,masksP) + onDemand ( 'Rec/Calo/EcalSplitClusters' , splitSeq , context ) + + + ## printout + _log.debug ( 'Configure Ecal Cluster Reco Seq : %s for %s : ' % (seq.name() , context) ) + if enableRecoOnDemand : + _log.info ('ClusterFutureReco onDemand') + + ## + return seq + +# ============================================================================ +## define the recontruction of Single Photons +def photonFutureReco ( context , enableRecoOnDemand, useTracks = True , useSpd = False, usePrs = False , trackLocation = '', neutralID = True, + photonPt=50.*MeV, fastReco = False, external = '',noSpdPrs=False,matchTrTypes=[]) : + """ + Define the recontruction of Single Photon Hypo + """ + + from Configurables import CaloFutureSinglePhotonAlg + from Configurables import CaloFutureHypoAlg + from Configurables import ( CaloFutureSelectCluster , + CaloFutureSelectClusterWithPrs , + CaloFutureSelectNeutralClusterWithTracks , + CaloFutureSelectNeutralClusterWithSpd , + CaloFutureSelectChargedClusterWithSpd , + CaloFutureSelectorNOT , + CaloFutureSelectorOR ) + + from Configurables import ( CaloFutureExtraDigits , + CaloFutureECorrection , + CaloFutureSCorrection , + CaloFutureLCorrection ) + + + + ## build the context-dependent sequence ( TrackMatch + SinglePhotonRec ) + seq = getAlgo ( GaudiSequencer , "PhotonFutureReco" , context , "Rec/Calo/Photons" , enableRecoOnDemand ) + seq.Members=[] + + # 1/ PhotonMatch from CaloFuturePIDs (if tracking is requested) + if useTracks : + from CaloFuturePIDs.PIDs import trackMatch + tm = trackMatch ( context,enableRecoOnDemand, trackLocation , matchTrTypes, fastReco, external) + addAlgs ( seq , tm ) + + + ##2/ SinglePhotonRec alg + alg = getAlgo ( CaloFutureSinglePhotonAlg, "SinglePhotonRecFuture" , context ) + alg.PropertiesPrint = False + if external != '' : + alg.InputData = external + + # cluster selection tools: + ### a/ generic selection (energy/multiplicity) + alg.addTool ( CaloFutureSelectCluster , "PhotonClusterFuture" ) + alg.SelectionTools = [ alg.PhotonClusterFuture ] + alg.PhotonClusterFuture.MinEt = photonPt + alg.PhotonClusterFuture.MinDigits = 2 # skip single-cell clusters + + ### b/ Neutral cluster (track-based and/or Spd/Prs-based) + if useTracks : + alg.addTool ( CaloFutureSelectNeutralClusterWithTracks , "NeutralClusterFuture" ) + alg.NeutralClusterFuture.MinChi2 = 4 + alg.SelectionTools += [ alg.NeutralClusterFuture ] + _log.debug ('CaloFutureReco/PhotonFutureReco: Configure Neutral Cluster Selector with Tracks : %s' % alg.NeutralClusterFuture.getFullName() ) + + if usePrs : + alg.addTool ( CaloFutureSelectClusterWithPrs , "ClusterWithPrsFuture" ) + alg.ClusterWithPrsFuture.MinEnergy = 10.*MeV + alg.SelectionTools += [ alg.ClusterWithPrsFuture ] + _log.debug ('CaloFutureReco/PhotonFutureReco: Configure Cluster Selector with Prs : %s' % alg.ClusterWithPrs.getFullName() ) + + if useSpd : + alg.addTool ( CaloFutureSelectNeutralClusterWithSpd , "NeutralClusterWithSpdFuture" ) + alg.SelectionTools += [ alg.NeutralClusterWithSpdFuture ] + _log.debug ('CaloFutureReco/PhotonFutureReco: Configure Neutral Cluster Selector with !Spd : %s ' % alg.NeutralClusterWithSpdFuture.getFullName() ) + + + ## hypo tools : add Spd/Prs digits + + if not noSpdPrs : + alg.addTool ( CaloFutureExtraDigits , 'SpdPrsExtraG' ) + alg.HypoTools = [ alg.SpdPrsExtraG ] + else : + alg.HypoTools = [] + + ## correction tools : E/S/L + alg.addTool ( CaloFutureECorrection , 'ECorrection' ) + alg.addTool ( CaloFutureSCorrection , 'SCorrection' ) + alg.addTool ( CaloFutureLCorrection , 'LCorrection' ) + + ecorr = alg.ECorrection + scorr = alg.SCorrection + lcorr = alg.LCorrection + + # tool configuration via condDB only (remove default configuration) + alg.CorrectionTools2 = [ ecorr , scorr , lcorr ] + + # update the sequence + addAlgs ( seq , alg ) + + ## 3/ PhotonID + from CaloFuturePIDs.PIDs import PhotonID + if neutralID : + pID = PhotonID ( context,enableRecoOnDemand, useTracks ) + addAlgs ( seq , pID ) + + ## global context + setTheProperty ( seq , 'Context' , context ) + + ## printout + _log.debug ( 'Configure Photon Reco Seq : %s for : %s' % (seq.name() , context ) ) + if enableRecoOnDemand : + _log.info ('PhotonFutureReco onDemand') + + return seq + +# ============================================================================ +## define the recontruction of Electorn Hypos +def electronFutureReco ( context , enableRecoOnDemand , useTracksE = True , useSpdE = True, usePrsE = True, trackLocation = '' , + electronPt=50.*MeV , fastReco = False, external = '' ,noSpdPrs=False,matchTrTypes=[]) : + """ + Define the reconstruction of + """ + + from Configurables import CaloFutureElectronAlg + from Configurables import CaloFutureHypoAlg + + from Configurables import ( CaloFutureSelectCluster , + CaloFutureSelectClusterWithPrs , + CaloFutureSelectNeutralClusterWithTracks , + CaloFutureSelectNeutralClusterWithSpd , + CaloFutureSelectChargedClusterWithSpd , + CaloFutureSelectorNOT ) + + from Configurables import ( CaloFutureExtraDigits , + CaloFutureECorrection , + CaloFutureSCorrection , + CaloFutureLCorrection ) + + + ## build the context-dependent sequence ( TrackMatch + SingleElectronRec ) + seq = getAlgo ( GaudiSequencer , "ElectronFutureReco" , context , 'Rec/Calo/Electrons' , enableRecoOnDemand ) + seq.Members=[] + + # 1/ ElectronMatch from CaloFuturePIDs (if useTracks) + if useTracksE : + from CaloFuturePIDs.PIDs import trackMatch + tm = trackMatch ( context,enableRecoOnDemand, trackLocation , matchTrTypes, fastReco , external) + addAlgs ( seq , tm ) + + ## 2/ Electron Rec alg + alg = getAlgo ( CaloFutureElectronAlg , 'SingleElectronRecFuture', context ) + alg.PropertiesPrint = False + if external != '' : + alg.InputData = external + + # cluster selection tools: + + ## 1/ generic selection (energy/multiplicity) + alg.addTool ( CaloFutureSelectCluster , "ElectronClusterFuture" ) + alg.SelectionTools = [ alg.ElectronClusterFuture ] + alg.ElectronClusterFuture.MinEt = electronPt + alg.ElectronClusterFuture.MinDigits = 2 # skip single-cell clusters + + ## 2/ hits in Spd + if useSpdE : + alg.addTool ( CaloFutureSelectChargedClusterWithSpd , "ChargedClusterWithSpdFuture" ) + alg.SelectionTools += [ alg.ChargedClusterWithSpdFuture ] + _log.debug ('CaloFutureReco/ElectronFutureReco: Configure Charged Cluster Selector with Spd : %s' % alg.ChargedClusterWithSpdFuture.getFullName() ) + + ## 3/ energy in Prs + if usePrsE : + alg.addTool ( CaloFutureSelectClusterWithPrs , "ClusterWithPrsFuture" ) + alg.ClusterWithPrsFuture.MinEnergy = 10 * MeV + alg.SelectionTools += [ alg.ClusterWithPrsFuture ] + _log.debug ('CaloFutureReco/ElectronFutureReco: Configure Cluster Selector with Prs : %s' % alg.ClusterWithPrsFuture.getFullName() ) + + ## 4/ match with tracks + if useTracksE : + alg.addTool ( CaloFutureSelectorNOT , "ChargedClusterFuture" ) + clnot = alg.ChargedClusterFuture + clnot.addTool ( CaloFutureSelectNeutralClusterWithTracks , "NotNeutralClusterFuture" ) + clnot.NotNeutralClusterFuture.MinChi2 = 25 + clnot.SelectorTools = [ clnot.NotNeutralClusterFuture ] + alg.SelectionTools += [ alg.ChargedClusterFuture ] + _log.debug ('CaloFutureReco/ElectronFutureReco: Configure Charged Cluster Selector with Tracks : %s' % alg.ChargedClusterFuture.getFullName() ) + + + ## hypo tools : add Spd/Prs digits + if not noSpdPrs : + alg.addTool ( CaloFutureExtraDigits , 'SpdPrsExtraEFuture' ) + alg.HypoTools = [ alg.SpdPrsExtraEFuture ] + else : + alg.HypoTools = [] + + ## correction tools : E/S/L + alg.addTool ( CaloFutureECorrection , 'ECorrectionFuture' ) + alg.addTool ( CaloFutureSCorrection , 'SCorrectionFuture' ) + alg.addTool ( CaloFutureLCorrection , 'LCorrectionFuture' ) + + ecorr = alg.ECorrectionFuture + scorr = alg.SCorrectionFuture + lcorr = alg.LCorrectionFuture + + # tool configuration via condDB (remove default configuration) + alg.CorrectionTools2 = [ ecorr , scorr , lcorr ] + + ## update the sequence + addAlgs ( seq , alg ) + + # global context + setTheProperty ( seq , 'Context' , context ) + + ## printout + _log.debug ( 'Configure Electron Reco Seq : %s for : %s' % (seq.name() , context )) + if enableRecoOnDemand : + _log.info ('ElectronFutureReco onDemand') + + return seq + + +# ============================================================================= +## define the reconstruction of Merged Pi0s Hypos +def mergedPi0FutureReco ( context , enableRecoOnDemand , clusterOnly = False , neutralID = True , useTracks = True, + mergedPi0Pt = 2* GeV ,fastReco = False, external = '',noSpdPrs=False, + masksE=[] , masksP=[] ) : + + """ + Define the recontruction of Merged Pi0s + """ + + from Configurables import CaloFutureMergedPi0 # CaloFutureMergedPi0Alg is obsolete (replaced by CaloFutureMergedPi0) + from Configurables import CaloFutureHypoAlg + + from Configurables import ( CaloFutureExtraDigits , + CaloFutureECorrection , + CaloFutureSCorrection , + CaloFutureLCorrection + ) + + + # build the sequences + seq = getAlgo ( GaudiSequencer , 'MergedPi0FutureReco' , context ) + sseq = getAlgo ( GaudiSequencer , 'SplitClusterFutureReco' , context ) + + ## Merged Pi0 + if clusterOnly : + pi0 = getAlgo ( CaloFutureMergedPi0 , 'SplitClustersRec', context ) + pi0.CreateSplitClustersOnly = True + sseq.Members=[pi0] + else : + pi0 = getAlgo ( CaloFutureMergedPi0 , 'MergedPi0RecFuture', context ) + + if masksE != [] : + pi0.EnergyTags = masksE + if masksP != [] : + pi0.PositionTags = masksP + + if external != '' : + pi0.InputData = external + + pi0.PropertiesPrint = False + + pi0.EtCut = mergedPi0Pt + + if clusterOnly : + setTheProperty ( sseq , 'Context' , context ) + return sseq + + ## MergedPi0 sequence + + ## 2/ SplitPhotons + # splitg = getAlgo ( CaloFutureHypoAlg , 'PhotonFromMergedRec' , context ) + # splitg.HypoType = "SplitPhotons"; + # splitg.PropertiesPrint = False + + ## Add Prs/Spd digits + if not noSpdPrs : + pi0.addTool ( CaloFutureExtraDigits , 'SpdPrsExtraSFuture' ) + pi0.addTool ( CaloFutureExtraDigits , 'SpdPrsExtraMFuture' ) + ## Pi0 correction tools + pi0.addTool ( CaloFutureECorrection , 'ECorrectionFuture' ) + pi0.addTool ( CaloFutureSCorrection , 'SCorrectionFuture' ) + pi0.addTool ( CaloFutureLCorrection , 'LCorrectionFuture' ) + + # tool configuration via condDB only (remove default configuration) + if not noSpdPrs : + pi0.PhotonTools = [ pi0.SpdPrsExtraSFuture , pi0.ECorrectionFuture,pi0.SCorrectionFuture, pi0.LCorrectionFuture ] + pi0.Pi0Tools = [ pi0.SpdPrsExtraMFuture ] + else : + pi0.PhotonTools = [ pi0.ECorrectionFuture,pi0.SCorrectionFuture, pi0.LCorrectionFuture ] + + seq.Members=[pi0] + + ## 3/ (PhotonFrom)MergedID + if neutralID : + from CaloFuturePIDs.PIDs import (MergedID , PhotonFromMergedID ) + idSeq = getAlgo( GaudiSequencer, "MergedIDSeq",context) + mID = MergedID ( context,enableRecoOnDemand, useTracks ) + pmID = PhotonFromMergedID( context, enableRecoOnDemand, useTracks ) + idSeq.Members = [ mID, pmID ] + addAlgs ( seq , idSeq ) + + # propagate the context + setTheProperty ( seq , 'Context' , context ) + + + ## onDemand + if enableRecoOnDemand : + onDemand ( 'Rec/Calo/SplitPhotons' , seq , context ) + onDemand ( 'Rec/Calo/MergedPi0s' , seq , context ) + #onDemand ( 'Rec/Calo/EcalSplitClusters' , seq , context ) ## ?? + + ## printout + _log.debug ( 'Configure MergedPi0 Reco Seq : %s for : %s' %( seq.name() , context )) + if enableRecoOnDemand : + _log.info ('MergedPi0FutureReco onDemand') + + return seq + + +# ============================================================================= +if '__main__' == __name__ : + print __doc__ diff --git a/CaloFuture/CaloFutureReco/python/CaloFutureReco/__init__.py b/CaloFuture/CaloFutureReco/python/CaloFutureReco/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..3a678ef87471205a06d9465af67c9fc71c40f1a5 --- /dev/null +++ b/CaloFuture/CaloFutureReco/python/CaloFutureReco/__init__.py @@ -0,0 +1,11 @@ +# $Id: __init__.py,v 1.2 2010-03-08 01:19:39 odescham Exp $ +# ============================================================================= +## Fictive module to define python "package" for CaloFuturerimeter Reconstruction +# @author Vanya BELYAEV Ivan.Belyaev@nikhe.nl +# @date 2008-07-17 +# ============================================================================= +__author__ = "Vanya BELYAEV Ivan.Belyaev@nikhef.nl" +__version__ = "CVS tag $Name: not supported by cvs2svn $, version $Revision: 1.2 $" +# ============================================================================= +# The END +# ============================================================================= diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureClusterCorrect3x3Position.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureClusterCorrect3x3Position.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1ae480f922356526448853a96e2abfb373bc2cad --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureClusterCorrect3x3Position.cpp @@ -0,0 +1,146 @@ +// ============================================================================ +// Include files +// STD & STL +#include <algorithm> +// from Gaudi +#include "GaudiKernel/SmartDataPtr.h" +// CaloFutureInterfaces +#include "CaloFutureInterfaces/ICaloFutureClusterTool.h" +#include "CaloFutureInterfaces/ICaloFutureHypoTool.h" +// CaloDet +#include "CaloDet/DeCalorimeter.h" +// CaloFutureEvent +#include "Event/CaloCluster.h" +#include "Event/CaloHypo.h" +#include "Event/CaloPosition.h" +// CaloFutureUtils +#include "CaloFutureUtils/CaloFutureDataFunctor.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +// Kernel +#include "Kernel/CaloCellID.h" +// local +#include "CaloFutureClusterCorrect3x3Position.h" + +// ============================================================================ +/** @file CaloFutureClusterCorrect3x3Position.cpp + * + * Implementation file for class : CaloFutureClusterCorrect3x3Position + * + * @author Olivier Deschamps + * @date 10/05/2002 + * + * Revision 1.2 2004/09/02 20:46:40 odescham + * - Transv. Shape parameters in option file + * + */ +// ============================================================================ + +DECLARE_COMPONENT( CaloFutureClusterCorrect3x3Position ) + +// ============================================================================ +/** Standard constructor + * @param name algorithm name + * @param svcloc pointer to service locator + */ +// ============================================================================ +CaloFutureClusterCorrect3x3Position::CaloFutureClusterCorrect3x3Position +( const std::string& name , + ISvcLocator* svcloc ) + : GaudiAlgorithm ( name , svcloc ) +{ + // set default data as a function of detector & context + m_detData= LHCb::CaloFutureAlgUtils::DeCaloFutureLocation( name ) ; + m_inputData = LHCb::CaloFutureAlgUtils::CaloFutureClusterLocation( name , context() ); + +} + +// ============================================================================ +/** helper function to calculate number of digits + * in the cluster with given status + * @param cluster pointet to the cluster object + * @param status digit statsu to be checked + * @return number of digits with given status. + * In the case of errors it returns -1 + */ +// ============================================================================ +long CaloFutureClusterCorrect3x3Position::numberOfDigits +( const LHCb::CaloCluster* cluster , + const LHCb::CaloDigitStatus::Status& status ) const +{ + /// check arguments + if( !cluster ) + { Error(" numberOfDigits! CaloCluster* points to NULL!").ignore(); return -1;} + /// + const auto& entries = cluster->entries(); + return std::count_if( entries.begin(), entries.end(), + [&](const LHCb::CaloClusterEntry& entry) -> bool { + return entry.status()&status; + } ); +} + +// ============================================================================ +/** standard algorithm execution + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureClusterCorrect3x3Position::execute() +{ + /// avoid long names + using namespace LHCb::CaloDataFunctor; + typedef LHCb::CaloClusters Clusters; + + /// load data + SmartDataPtr<DeCalorimeter> detector( detSvc() , m_detData ); + if( !detector ) + { return Error("could not locate calorimeter '"+m_detData+"'");} + + const DeCalorimeter* calo = getDet<DeCalorimeter>( m_detData ) ; + m_cell3x3.setDet ( calo ) ; + m_neighbour.setDet ( calo ); + SmartDataPtr<Clusters> clusters( eventSvc() , m_inputData ); + if( !clusters ) { + return Error("Could not load input data ='"+m_inputData+"'"); + } + + /// loop over all clusters + for( LHCb::CaloCluster* cluster : *clusters ) { + if( !cluster ) { continue ; } + + double Energy=0; + double PosX=0; + double PosY=0; + /// Find Cluster Seed + const auto iSeed = + clusterLocateDigit( cluster->entries().begin() , + cluster->entries().end () , + LHCb::CaloDigitStatus::SeedCell ); + const LHCb::CaloDigit* seed = iSeed->digit() ; + if( !seed) { continue ; } + const LHCb::CaloCellID& seedID = seed->cellID() ; + // Loop over 3x3 digits + for(const auto& entry : cluster->entries()) { + const LHCb::CaloDigit* cell = entry.digit(); + const LHCb::CaloCellID& cellID = cell->cellID() ; + if( 0 != m_cell3x3( seedID , cellID) && m_neighbour(seedID,cellID) ){ + Energy += cell->e() * entry.fraction(); + PosX += detector->cellX(cellID) * cell->e() * entry.fraction(); + PosY += detector->cellY(cellID) * cell->e() * entry.fraction(); + } + } + PosX=PosX/Energy; + PosY=PosY/Energy; + LHCb::CaloPosition pos = cluster->position(); + LHCb::CaloPosition::Parameters params; + + params(LHCb::CaloPosition::Index::X)=PosX; + params(LHCb::CaloPosition::Index::Y)=PosY; + params(LHCb::CaloPosition::Index::E)=Energy; + pos.setParameters( params ); + cluster->setPosition( pos ); + } + return StatusCode::SUCCESS; +} + +// ============================================================================ +// The End +// ============================================================================ diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureClusterCorrect3x3Position.h b/CaloFuture/CaloFutureReco/src/CaloFutureClusterCorrect3x3Position.h new file mode 100644 index 0000000000000000000000000000000000000000..ace541f3ef80c11e3a609a02c9b3b4eee7ea11c1 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureClusterCorrect3x3Position.h @@ -0,0 +1,59 @@ +#ifndef CALOFUTURERECO_CaloFutureClusterCorrect3x3Position_H +#define CALOFUTURERECO_CaloFutureClusterCorrect3x3Position_H 1 +// Include files +// from STL +#include <string> +#include <vector> +// +#include "GaudiAlg/GaudiAlgorithm.h" +//CaloFutureUtils +#include "CaloFutureUtils/CellMatrix3x3.h" +#include "CaloFutureUtils/CellNeighbour.h" +// forward declarations +class CaloCluster ; +struct ICaloFutureHypoTool ; + +/** @class CaloFutureClusterCorrect3x3Position CaloFutureClusterCorrect3x3Position.h + * + * Merged pi0 reconstruction with Iterativ Method + * + * @author Olivier Deschamps + * @date 05/10/2002 + */ + +class CaloFutureClusterCorrect3x3Position : public GaudiAlgorithm +{ +public: + /** Standard constructor + * @param name algorithm name + * @param svcloc pointer to service locator + */ + CaloFutureClusterCorrect3x3Position( const std::string& name , + ISvcLocator* svcloc ); + + /** standard algorithm execution + * @return status code + */ + StatusCode execute () override; + +protected: + + /** helper function to calculate number of digits + * in the cluster with given status + * @param cluster pointet to the cluster object + * @param status digit statsu to be checked + * @return number of digits with given status. + * In the case of errors it returns -1 + */ + long numberOfDigits ( const LHCb::CaloCluster* cluster , + const LHCb::CaloDigitStatus::Status& status ) const ; + + private: + CellMatrix3x3 m_cell3x3 ; + CellNeighbour m_neighbour; + Gaudi::Property<std::string> m_inputData {this, "InputData", LHCb::CaloClusterLocation::Ecal}; + Gaudi::Property<std::string> m_detData {this, "Detector", DeCalorimeterLocation::Ecal}; +}; + +// ============================================================================ +#endif // CaloFutureClusterCorrect3x3Position_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureClusterCovarianceAlg.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureClusterCovarianceAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..041833808e4e6cd06045b04947bd32646a56b49a --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureClusterCovarianceAlg.cpp @@ -0,0 +1,154 @@ +// =========================================================================== +#define CALOFUTURERECO_CALOFUTURECLUSTERCOVARIANCEALG_CPP 1 +/// =========================================================================== +// Include files +#include "Event/CaloCluster.h" +#include "CaloFutureInterfaces/ICaloFutureClusterTool.h" +#include "FutureSubClusterSelectorTool.h" +#include "CaloFutureUtils/CovarianceEstimator.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "CaloFutureClusterCovarianceAlg.h" + +// =========================================================================== +/** @file + * + * Implementation file for class CaloFutureClusterCovarianceAlg + * + * @see CaloFutureClusterCovarinanceAlg + * @see ICaloFutureClusterTool + * @see ICaloFutureSubClusterTag + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 04/07/2001 +s */ +// =========================================================================== + +DECLARE_COMPONENT( CaloFutureClusterCovarianceAlg ) + +// ============================================================================ +/** Standard constructor + * @param name algorithm name + * @param pSVcLocator pointer to Service Locator +*/ +// ============================================================================ +CaloFutureClusterCovarianceAlg::CaloFutureClusterCovarianceAlg +( const std::string& name, + ISvcLocator* pSvcLocator) + : GaudiAlgorithm ( name , pSvcLocator ) +{ + // following properties might be inherited by the covariance tool + declareProperty( "CovarianceParameters" , m_covParams ) ; // KEEP IT UNSET ! INITIAL VALUE WOULD BYPASS DB ACCESS + + // set default data as a function of detector + m_inputData = LHCb::CaloFutureAlgUtils::CaloFutureClusterLocation( name , context() ); + + std::string caloName = LHCb::CaloFutureAlgUtils::CaloFutureNameFromAlg( name ); + m_covName = caloName + "CovarTool" ; + m_spreadName = caloName + "SpreadTool"; + m_tagName = caloName + "ClusterTag"; +} + +// =========================================================================== +/** standard initialization method + * @see GaudiAlgorithm + * @see Algorithm + * @see IAlgorithm + * @return status code + */ +// =========================================================================== +StatusCode CaloFutureClusterCovarianceAlg::initialize(){ + // try to initialize base class + StatusCode sc = GaudiAlgorithm::initialize(); + if( sc.isFailure() ) + { return Error("Could not initialize the base class GaudiAlgorithm"); } + + // locate the tagger (inherit from relevant properties) + m_tagger = tool<FutureSubClusterSelectorTool>( "FutureSubClusterSelectorTool" , m_tagName , this ); + + // locate the tool for covariance matrix calculations + m_cov = m_covName.empty() ? + tool<ICaloFutureClusterTool>( m_covType , this ) : + tool<ICaloFutureClusterTool>( m_covType , m_covName , this ) ; + + // locate the tool for cluster spread(2nd moments) estimation + m_spread = m_spreadName.empty() ? + tool<ICaloFutureClusterTool>( m_spreadType , this ) : + tool<ICaloFutureClusterTool>( m_spreadType , m_spreadName , this ) ; + + // copy flag + m_copy = (!m_outputData.empty()) && (m_outputData.value() != m_inputData.value()); + + counterStat = tool<IFutureCounterLevel>("FutureCounterLevel"); + return StatusCode::SUCCESS; +} + + + +// =========================================================================== +StatusCode CaloFutureClusterCovarianceAlg::finalize(){ + // finalize the base class + return GaudiAlgorithm::finalize(); +} + +// =========================================================================== +StatusCode CaloFutureClusterCovarianceAlg::execute(){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "==> Execute" << endmsg; + + // useful typedefs + typedef LHCb::CaloClusters Clusters ; + + // locate input data + Clusters* clusters = get<Clusters> ( m_inputData ); + if( 0 == clusters ) { return StatusCode::FAILURE ; } + // + + // define the output data + Clusters* output = 0; + if( m_copy ){ + // make a copy of container + output = new Clusters(); + put( output , m_outputData ); + // make a copy + for( const LHCb::CaloCluster* i: *clusters ) { + if ( i ) output->insert( new LHCb::CaloCluster(*i) ) ; + } + } + else { output = clusters; } // update existing sequence + + // + for( Clusters::iterator cluster = output->begin() ; output->end() != cluster ; ++cluster ){ + + // skip nulls + if( 0 == *cluster ) { continue ; } + + + // == APPLY TAGGER + StatusCode sc = m_tagger -> tag ( *cluster ); + if( sc.isFailure() ){ + Error("Error from tagger, skip cluster ", sc ).ignore() ; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << *cluster << endmsg ; + continue ; + } + + // == APPLY COVARIANCE ESTIMATOR + sc = cov() -> process( *cluster ) ; + if( sc.isFailure() ){ + Error("Error from cov, skip cluster ", sc, 0 ).ignore() ; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << *cluster << endmsg ; + continue ; + } + + // == APPLY SPREAD ESTIMATOR + sc = spread() -> process( *cluster ) ; + if( sc.isFailure() ){ + Error("Error from spread, skip cluster ", sc, 0 ).ignore() ; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << *cluster << endmsg ; + continue ; + } + } + + // == FUTURECOUNTER + if(counterStat->isQuiet())counter ( "#Clusters from '" + m_inputData + "'") += clusters->size() ; + return StatusCode::SUCCESS ; +} + diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureClusterCovarianceAlg.h b/CaloFuture/CaloFutureReco/src/CaloFutureClusterCovarianceAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..321b15737848579024ec2daef4d9ed43c4c34ad3 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureClusterCovarianceAlg.h @@ -0,0 +1,112 @@ +// =========================================================================== +#ifndef CALOFUTURERECO_CALOFUTURECLUSTERCOVARIANCEALG_H +#define CALOFUTURERECO_CALOFUTURECLUSTERCOVARIANCEALG_H 1 +/// =========================================================================== +// Include files +// from STL +#include <string> +#include "GaudiAlg/GaudiAlgorithm.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" + +struct ICaloFutureClusterTool ; +class FutureSubClusterSelectorTool ; + +/** @class CaloFutureClusterCovarianceAlg CaloFutureClusterCovarianceAlg.h + * + * Simple algorithm for evaluation of covariance matrix + * for CaloFutureCluster object + * + * @author Vanya BElyaev Ivan Belyaev + * @date 04/07/2001 + */ + +class CaloFutureClusterCovarianceAlg : public GaudiAlgorithm +{ +public: + + /** Standard constructor + * @param name algorith name + * @param pSvcLocator pointer to Service Locator + */ + CaloFutureClusterCovarianceAlg + ( const std::string& name , + ISvcLocator* pSvcLocator ); + + /** standard initialization method + * @see GaudiAlgorithm + * @see Algorithm + * @see IAlgorithm + * @return status code + */ + StatusCode initialize() override; + + /** standard execution method + * @see GaudiAlgorithm + * @see Algorithm + * @see IAlgorithm + * @return status code + */ + StatusCode execute() override; + + /** standard finalization method + * @see GaudiAlgorithm + * @see Algorithm + * @see IAlgorithm + * @return status code + */ + StatusCode finalize() override; + +protected: + + inline ICaloFutureClusterTool* cov () const { return m_cov ; } + inline ICaloFutureClusterTool* spread () const { return m_spread ; } + inline FutureSubClusterSelectorTool* tagger () const { return m_tagger ; } + + +private: + + /// default constructor is private + CaloFutureClusterCovarianceAlg(); + + /** copy constructor is private + * @param copy object to be copied + */ + CaloFutureClusterCovarianceAlg + ( const CaloFutureClusterCovarianceAlg& copy ); + + /** assignement operator is private + * @param copy object to be copied + */ + CaloFutureClusterCovarianceAlg& operator= + ( const CaloFutureClusterCovarianceAlg& copy ); + +private: + + bool m_copy = false ; /// copy flag + + // tool used for covariance matrix calculation + Gaudi::Property<std::string> m_covType {this, "CovarianceType", "FutureClusterCovarianceMatrixTool"}; + Gaudi::Property<std::string> m_covName {this, "CovarianceName"}; + ICaloFutureClusterTool* m_cov = nullptr ; ///< tool + FutureSubClusterSelectorTool* m_tagger = nullptr ; + + // tool used for cluster spread estimation + Gaudi::Property<std::string> m_spreadType {this, "SpreadType", "FutureClusterSpreadTool"}; + Gaudi::Property<std::string> m_spreadName {this, "SpreadName"}; + ICaloFutureClusterTool* m_spread = nullptr ; ///< tool + + Gaudi::Property<std::string> m_outputData {this, "OutputData"}; + Gaudi::Property<std::string> m_inputData {this, "InputData"}; + Gaudi::Property<std::string> m_tagName {this, "TaggerName"}; + + // following properties are inherited by the selector tool when defined: + Gaudi::Property<std::vector<std::string>> m_taggerE {this, "EnergyTags"}; + Gaudi::Property<std::vector<std::string>> m_taggerP {this, "PositionTags"}; + + // collection of known cluster shapes + std::map<std::string , std::string> m_clusterShapes; + std::map<std::string,std::vector<double> > m_covParams; + IFutureCounterLevel* counterStat = nullptr; + }; + +#endif // CALOFUTURERECO_CALOFUTURECLUSTERCOVARIANCEALG_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureClusterizationTool.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureClusterizationTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ce32f5a33595933f0f9ff8fdac294dacb875fa7d --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureClusterizationTool.cpp @@ -0,0 +1,388 @@ +// Include files + +// from Gaudi +#include "GaudiKernel/SystemOfUnits.h" +// ============================================================================ +#include "DetDesc/IGeometryInfo.h" +// ============================================================================ +#include "Event/CaloDigit.h" +#include "Event/CaloCluster.h" +#include "CaloFutureUtils/CaloFutureDataFunctor.h" +#include "Event/CellID.h" +// ============================================================================ +#include "CaloFutureUtils/ClusterFunctors.h" +#include "CaloFutureUtils/CaloFutureNeighbours.h" +// local +#include "CaloFutureClusterizationTool.h" +#include "TaggedCellFunctor.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : CaloFutureClusterizationTool +// +// 2008-04-04 : Victor Egorychev +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( CaloFutureClusterizationTool ) + +// ============================================================================ +inline bool CaloFutureClusterizationTool::isLocMax +( const LHCb::CaloDigit* digit , + const CaloFutureClusterizationTool::DirVector& hits , + const DeCalorimeter* det ) const +{ + + const CaloNeighbors& ns = det->neighborCells( digit -> cellID() ) ; + double e = digit -> e() ; + + LHCb::CaloDataFunctor::EnergyTransverse<const DeCalorimeter*> et ( det ) ; + + double eT = ( m_withET ? et(digit) : 0. ); + + for ( const auto& iN : ns ) { + const CelAutoTaggedCell* cell = hits[iN]; + if ( !cell ) { continue ; } + const LHCb::CaloDigit* nd = cell->digit() ; + if ( !nd ) { continue ; } + + if ( nd->e() > e ) { return false ; } + + if ( m_withET ) { eT += et ( nd ) ; } + } + + if ( m_withET && eT < m_ETcut ) { return false ; } + + return true ; +} +// ============================================================================ +/* Application of rules of tagging on one cell + * - No action if no clustered neighbor + * - Clustered if only one clustered neighbor + * - Edge if more then one clustered neighbor + */ +// ============================================================================ +inline void +CaloFutureClusterizationTool::appliRulesTagger +( CelAutoTaggedCell* cell , + CaloFutureClusterizationTool::DirVector& hits , + const DeCalorimeter* det , + const bool releaseBool) const +{ + + // Find in the neighbors cells tagged before, the clustered neighbors cells + const LHCb::CaloCellID& cellID = cell->cellID() ; + const CaloNeighbors& ns = det->neighborCells ( cellID ) ; + bool hasEdgeNeighbor = false; + bool hasClusteredNeighbor = false; + for ( CaloNeighbors::const_iterator iN = ns.begin() ; ns.end() != iN ; ++iN ){ + const CelAutoTaggedCell* nei = hits[ *iN ] ; + if ( 0 == nei ) { continue ; } + // + if( nei->isEdge() && releaseBool ){ + hasEdgeNeighbor = true; + for( std::vector<LHCb::CaloCellID>::const_iterator id = nei->seeds().begin();id != nei->seeds().end();id++){ + if( !cell->isWithSeed( *id ) )cell->addSeed( *id ); + } + } + // + if ( !nei->isClustered() ) { continue ; } + hasClusteredNeighbor = true; + const LHCb::CaloCellID& seed = nei->seedForClustered() ; + if ( cell->isWithSeed( seed ) ) { continue ; } + cell->addSeed ( seed ) ; + } + + + // Tag or or not the cell + + switch ( cell -> numberSeeds() ) { + case 0: + if( !releaseBool)break; + if( hasEdgeNeighbor && !hasClusteredNeighbor)cell->setEdge(); // + break; + case 1: + cell->setClustered(); + break; + default: + cell->setEdge(); + break; + } +} + +// ============================================================================ +inline StatusCode CaloFutureClusterizationTool::setEXYCluster( LHCb::CaloCluster& cluster, const DeCalorimeter* detector ) const +{ + /// + double E, X, Y; + /// + StatusCode sc = LHCb::ClusterFunctors::calculateEXY + ( cluster.entries().begin() , + cluster.entries().end () , + detector , E , X , Y ); + /// + m_clusterEnergy += E; + if( sc.isSuccess() ){ + cluster.position().parameters()( LHCb::CaloPosition::Index::E ) = E ; + cluster.position().parameters()( LHCb::CaloPosition::Index::X ) = X ; + cluster.position().parameters()( LHCb::CaloPosition::Index::Y ) = Y ; + } + else + { Error( " E,X and Y of cluster could not be evaluated!",sc).ignore(); } + /// + return sc; +} + +unsigned int CaloFutureClusterizationTool::clusterize( std::vector<LHCb::CaloCluster*>& clusters , + const LHCb::CaloDigits& hits, + const DeCalorimeter* m_detector , + const std::vector<LHCb::CaloCellID>& _cell_list , + const unsigned int m_neig_level ) const +{ + + // + + // cmb: this needs to be done every time in order + // to allow different detectors in the same algorithm + // --> to be revisited in a future round + CellSelector cellSelectorE; + CellSelector cellSelectorP; + cellSelectorE.setSelector(m_usedE); + cellSelectorP.setSelector(m_usedP); + cellSelectorE.setDet(m_detector); + cellSelectorP.setDet(m_detector); + bool releaseBool = false; + bool useData = false; + // + LHCb::CaloCellID::Set out_cells; + + + /* + + _cell_list.empty() && level > 0 -> All local maxima + neighborhood(level) + _cell_list.empty() && level = 0 -> All data (default) + !_cell_list.empty() && level > 0 -> seed lis + neighborhood(level) + !_cell_list.empty() && level = 0 -> seed list + */ + + + // fill with data if level >0 and no predefined seed list + std::vector<LHCb::CaloCellID> cell_list; + if( _cell_list.empty() && m_neig_level>0){ + useData = true; + + cell_list.reserve(hits.size()); + for(const auto& i : hits ) { + const CaloNeighbors& neighbors = m_detector->neighborCells( i -> cellID() ) ; + if ( std::none_of( neighbors.begin(), neighbors.end(), + [&,e = i->e()](const auto& n) { + if ( !m_detector->valid( n )) return false; + const LHCb::CaloDigit* dig = hits( n ); + return dig && dig->e() > e; + } ) ) { + cell_list.push_back( i->cellID() ); + } + } + } + else{ + cell_list.assign( _cell_list.begin(), _cell_list.end() ); + } + + + // info() << "Cell list " << _cell_list << " level = " << m_neig_level << endmsg; + + // if list of "seed" is not empty + if( !cell_list.empty() ){ + out_cells.insert( cell_list.begin(), cell_list.end() ); + + /** find all neighbours for the given set of cells for the givel level + * @param cells (UPDATE) list of cells + * @param level (INPUT) level + * @param detector (INPUT) the detector + * @return true if neighbours are added + */ + LHCb::CaloFutureFunctors::neighbours(out_cells, m_neig_level, m_detector); + } + + // z-position of cluster + LHCb::ClusterFunctors::ZPosition zPosition( m_detector ); + + // Create access direct and sequential on the tagged cells + DirVector taggedCellsDirect( (CelAutoTaggedCell*) 0 ) ; + /// container to tagged cells with sequential access + std::vector<CelAutoTaggedCell*> taggedCellsSeq; + + size_t local_size = cell_list.empty() ? hits.size() : out_cells.size(); + const CelAutoTaggedCell cell0_ = CelAutoTaggedCell () ; + std::vector<CelAutoTaggedCell> local_cells ( local_size , cell0_ ) ; + + if( cell_list.empty() ){ + taggedCellsDirect.reserve ( hits.size() ) ; + taggedCellsDirect.setSize ( 14000 ) ; + taggedCellsSeq.reserve ( hits.size() ) ; + } + else{ + taggedCellsDirect.reserve ( out_cells.size() ) ; + taggedCellsDirect.setSize ( 14000 ) ; + taggedCellsSeq.reserve ( out_cells.size() ) ; + } + + if( cell_list.empty() ){ + // fill with the data + size_t index = 0 ; + + for( auto ihit =hits.begin() ; hits.end() != ihit ; ++ihit , ++index ){ + const LHCb::CaloDigit* digit = *ihit ; + if ( !digit ) { continue ; } // CONTINUE !!! + CelAutoTaggedCell& taggedCell = *(local_cells.begin() + index ) ; + taggedCell = digit ; + + taggedCellsDirect.addEntry ( &taggedCell , digit->cellID() ) ; + taggedCellsSeq.push_back ( &taggedCell ) ; + + } + }else{//fill for HLT + size_t index = 0 ; + + for(std::set<LHCb::CaloCellID>::const_iterator icell = out_cells.begin(); + out_cells.end() != icell; ++icell , ++index){ + + const LHCb::CaloDigit* digit = hits(*icell); + if ( 0 == digit ) { continue ; } // CONTINUE !!! + + CelAutoTaggedCell& taggedCell = *(local_cells.begin() + index ) ; + taggedCell = digit ; + + taggedCellsDirect.addEntry ( &taggedCell , digit->cellID() ) ; + taggedCellsSeq.push_back ( &taggedCell ) ; + } + + } + + + // Find and mark the seeds (local maxima) + if(useData){ + for(std::vector<LHCb::CaloCellID>::iterator seed = cell_list.begin();seed!=cell_list.end();seed++){ + taggedCellsDirect[*seed]->setIsSeed(); + } + } + else{ + for( auto itTag = taggedCellsSeq.begin(); taggedCellsSeq.end() != itTag ; ++itTag ){ + if ( isLocMax ( (*itTag)->digit() ,taggedCellsDirect ,m_detector) ) { + (*itTag)->setIsSeed(); + } + } + } + + /// Tag the cells which are not seeds + auto itTagLastSeed = std::stable_partition( taggedCellsSeq.begin () , + taggedCellsSeq.end () , + TaggedCellFunctor::isClustered() ); + + auto itTagLastClustered = itTagLastSeed ; + auto itTagFirst = itTagLastClustered ; + unsigned int nPass = 0; + while ( itTagLastClustered != taggedCellsSeq.end() ) { + + // Apply rules tagger for all not tagged cells + for ( auto itTag = itTagLastClustered ; taggedCellsSeq.end() != itTag ; ++itTag ){ + appliRulesTagger( (*itTag), taggedCellsDirect , m_detector, releaseBool ); + } + + // Valid result + std::for_each ( itTagFirst, taggedCellsSeq.end(), TaggedCellFunctor::setStatus() ); + + itTagLastClustered = std::stable_partition( itTagFirst, + taggedCellsSeq.end(), + TaggedCellFunctor::isClusteredOrEdge() ); + + // Test if cells are tagged in this pass + if ( itTagLastClustered == itTagFirst && releaseBool ){ + const long number = taggedCellsSeq.end() - itTagLastClustered ; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " TAGGING NOT FULL - Remain " + << std::to_string ( number ) + << " not clustered cells" << endmsg ; + itTagLastClustered = taggedCellsSeq.end(); + } + if( itTagLastClustered == itTagFirst )releaseBool = true; // try additional passes releasing appliRulesTagger criteria + nPass++; + itTagFirst = itTagLastClustered; + if( m_passMax > 0 && nPass >= m_passMax)break; + } + + + + LHCb::CaloDigitStatus::Status usedForE = LHCb::CaloDigitStatus::UseForEnergy | LHCb::CaloDigitStatus::UseForCovariance ; + LHCb::CaloDigitStatus::Status usedForP = LHCb::CaloDigitStatus::UseForPosition | LHCb::CaloDigitStatus::UseForCovariance ; + LHCb::CaloDigitStatus::Status seed = LHCb::CaloDigitStatus::SeedCell |LHCb::CaloDigitStatus::LocalMaximum | usedForP | usedForE; + + + itTagLastClustered = std::stable_partition( itTagLastSeed , + taggedCellsSeq.end() , + TaggedCellFunctor::isClustered() ) ; + auto itTagSeed = taggedCellsSeq.begin(); + auto itTagClustered1 = itTagLastSeed; + while ( itTagSeed != itTagLastSeed ){ + const LHCb::CaloDigit* digit = (*itTagSeed)->digit() ; + + if( digit->e() <= 0 ) { + itTagSeed++; + m_negativeSeed += digit->e(); + continue; // does not keep cluster with seed.energy <= 0 + } + + LHCb::CaloCellID seedID = (*itTagSeed)->cellID(); + // Do partitions first + auto itTagClustered2 = std::stable_partition( itTagClustered1 , + itTagLastClustered , + TaggedCellFunctor::isWithSeed(seedID) ) ; + auto itTagFirstEdge = itTagLastClustered ; + auto itTagLastEdge = std::stable_partition( itTagLastClustered , + taggedCellsSeq.end() , + TaggedCellFunctor::isWithSeed (seedID) ) ; + + // Create cluster, reserve, fill + auto cluster = std::make_unique<LHCb::CaloCluster>(); + cluster->entries().reserve(1 + (itTagClustered2 - itTagClustered1) + (itTagLastEdge - itTagFirstEdge) ); + + // set seed + cluster->entries().emplace_back( digit , seed ); + cluster->setSeed( digit->cellID() ); + + // Owned cells + for ( ; itTagClustered1 != itTagClustered2 ; ++itTagClustered1 ){ + LHCb::CaloCellID cellID = (*itTagClustered1)->cellID(); + const LHCb::CaloDigit* digit = (*itTagClustered1)->digit() ; + LHCb::CaloDigitStatus::Status owned = LHCb::CaloDigitStatus::OwnedCell ; + if( cellSelectorE( seedID, cellID) > 0.)owned |= usedForE; + if( cellSelectorP( seedID, cellID) > 0.)owned |= usedForP; + cluster->entries().emplace_back( digit , owned ); + } + // Shared cells + for( ; itTagFirstEdge != itTagLastEdge ; ++itTagFirstEdge ){ + const LHCb::CaloDigit* digit = (*itTagFirstEdge)->digit() ; + LHCb::CaloCellID cellID = (*itTagFirstEdge)->cellID(); + LHCb::CaloDigitStatus::Status shared = LHCb::CaloDigitStatus::SharedCell; + if( cellSelectorE( seedID, cellID) > 0.)shared |= usedForE; + if( cellSelectorP( seedID, cellID) > 0.)shared |= usedForP; + cluster->entries().emplace_back( digit , shared ); + }; + + if( setEXYCluster ( *cluster, m_detector ).isSuccess() ){ + cluster->setType( LHCb::CaloCluster::Type::CellularAutomaton ) ; + cluster->position().setZ( zPosition( cluster.get() ) ); + // put cluster to the output + clusters.push_back( cluster.release() ); + m_clusterEnergy += clusters.back()->entries().size(); + } + itTagClustered1 = itTagClustered2; + itTagSeed++; + } + + // clear local storages + taggedCellsSeq .clear () ; + taggedCellsDirect .clear () ; + local_cells .clear () ; + + return nPass; +} diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureClusterizationTool.h b/CaloFuture/CaloFutureReco/src/CaloFutureClusterizationTool.h new file mode 100644 index 0000000000000000000000000000000000000000..3ea629544a225e64080f9273e930f83f8f7ee4b0 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureClusterizationTool.h @@ -0,0 +1,60 @@ +#ifndef CALOFUTURECLUSTERIZATIONTOOL_H +#define CALOFUTURECLUSRERIZATIONTOOL_H 1 +// ============================================================================ +#include <string> +#include "GaudiAlg/GaudiTool.h" +#include "CaloKernel/CaloVector.h" +#include "CaloFutureInterfaces/ICaloFutureClusterization.h" +#include "GaudiKernel/Counters.h" +#include "CaloDet/DeCalorimeter.h" +#include "CelAutoTaggedCell.h" +#include "CaloFutureUtils/CellSelector.h" + +/** @class CaloFutureClusterizationTool CaloFutureClusterizationTool.h + * + * + * @author Victor Egorychev + * @date 2008-04-03 + */ +class CaloFutureClusterizationTool : public extends<GaudiTool,ICaloFutureClusterization> { + +public: + /// container to tagged cells with direct (by CaloCellID key) access + typedef CaloVector<CelAutoTaggedCell*> DirVector ; + + /// Extend ICaloFutureClusterization + using extends<GaudiTool,ICaloFutureClusterization>::extends; + + unsigned int clusterize + ( std::vector<LHCb::CaloCluster*>& clusters , + const LHCb::CaloDigits& hits , + const DeCalorimeter* detector , + const std::vector<LHCb::CaloCellID>& seeds , + const unsigned int level ) const override; + +private: + + inline bool isLocMax + ( const LHCb::CaloDigit* digit , + const DirVector& hits , + const DeCalorimeter* det ) const ; + + inline void appliRulesTagger + ( CelAutoTaggedCell* taggedCell, + DirVector& taggedCellsDirect, + const DeCalorimeter* detector, + const bool releaseBool) const ; + + inline StatusCode setEXYCluster( LHCb::CaloCluster& cluster,const DeCalorimeter* detector ) const ; + + Gaudi::Property<bool> m_withET{this, "withET", false}; + Gaudi::Property<double> m_ETcut{this, "ETcut", -10. * Gaudi::Units::GeV}; + Gaudi::Property<std::string> m_usedE{this, "CellSelectorForEnergy", "3x3"}; + Gaudi::Property<std::string> m_usedP{this, "CellSelectorForPosition", "3x3"}; + Gaudi::Property<unsigned int> m_passMax{this, "MaxIteration", 10}; + + mutable Gaudi::Accumulators::StatCounter<> m_clusterEnergy{this, "Cluster energy"}; + mutable Gaudi::Accumulators::StatCounter<> m_negativeSeed{this, "Negative seed energy"}; + mutable Gaudi::Accumulators::StatCounter<> m_clusterSize{this, "Cluster size"}; + }; +#endif // CALOFUTURECLUSTERIZATIONTOOL_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..32862abb41665726b83baf4cb7d88754c8b79656 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.cpp @@ -0,0 +1,557 @@ +// Include files + +#include "Event/ProtoParticle.h" +#include "CaloFutureCorrectionBase.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : CaloFutureCorrectionBase +// +// 2010-05-07 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( CaloFutureCorrectionBase ) + + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +CaloFutureCorrectionBase::CaloFutureCorrectionBase( const std::string& type , + const std::string& name , + const IInterface* parent ) + : GaudiTool ( type, name , parent ) +{ + declareInterface<CaloFutureCorrectionBase>(this); + m_cmLoc = LHCb::CaloFutureAlgUtils::CaloFutureIdLocation("ClusterMatch", context()); +} + +//============================================================================= +// Initialization +//============================================================================= +StatusCode CaloFutureCorrectionBase::initialize() { + StatusCode sc = GaudiTool::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; // error printed already by GaudiTool + + if ( UNLIKELY (msgLevel(MSG::DEBUG) ) ) debug() << "==> Initialize" << endmsg; + + // register to incident service + IIncidentSvc* inc = incSvc() ; + if ( inc ) inc -> addListener( this , IncidentType::EndEvent ) ; + + // check the setting + + // transform vector of accepted hypos + m_hypos.clear () ; + for( const auto& hypo : m_hypos_ ) { + if( hypo <= (int) LHCb::CaloHypo::Hypothesis::Undefined || + hypo >= (int) LHCb::CaloHypo::Hypothesis::Other ) + { return Error("Invalid/Unknown Calorimeter hypothesis object!" ) ; } + m_hypos.push_back( LHCb::CaloHypo::Hypothesis( hypo )); + } + + // locate and set and configure the Detector + m_det = getDet<DeCalorimeter>( m_detData ) ; + if( !m_det ) { return StatusCode::FAILURE ; } + m_calo.setCaloFuture( m_detData); + // + if( m_hypos.empty() )return Error("Empty vector of allowed Calorimeter Hypotheses!" ) ; + + // debug printout of all allowed hypos + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) { + debug() << " List of allowed hypotheses : " << endmsg; + for( const auto& h : m_hypos ) { + debug () << " -->" << h << endmsg ; + } + for( const auto& c : m_corrections ) { + debug() << "Accepted corrections : '" << c <<"'" << endmsg; + } + } + + // get external tools + m_caloElectron = tool<ICaloFutureElectron>("CaloFutureElectron", this); + m_pileup = tool<ICaloFutureDigitFilterTool>("CaloFutureDigitFilterTool","FilterTool"); + m_tables = tool<ICaloFutureRelationsGetter>("CaloFutureRelationsGetter","CaloFutureRelationsGetter",this); + counterStat = tool<IFutureCounterLevel>("FutureCounterLevel"); + return setConditionParams(m_conditionName); +} + + +//============================================================================= +// Finalize +//============================================================================= +StatusCode CaloFutureCorrectionBase::finalize() +{ + if ( UNLIKELY(msgLevel(MSG::DEBUG)) ) debug() << "==> Finalize" << endmsg; + + if( m_corrections.size() > 1 || *(m_corrections.begin()) != "All" ){ + for( const auto& c : m_corrections ) { + info() << "Accepted corrections : '" << c <<"'" << endmsg; + } + } + if( m_corrections.empty())warning() << "All corrections have been disabled for " << name() << endmsg; + + if( m_cond == nullptr ) + warning() << " Applied corrections configured via options for " << name() <<endmsg; + else if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " Applied corrections configured via condDB ('" << m_conditionName << "') for " + << name() << endmsg; + + for ( const auto& param : m_params ) + { + if ( !param.active ) continue; + const auto & type = param.type; + const auto & vec = param.data; + if ( !vec.empty() ) + { + int func = vec[0]; + int dim = vec[1]; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " o '" << type <<"' correction as a '" << CaloFutureCorrection::funcName[ func ] + << "' function of " << dim << " parameters" << endmsg; + } + else + { + warning() << " o '" << type << "' correction HAS NOT BEEN APPLIED (badly configured)" << endmsg; + } + } + + return GaudiTool::finalize(); // must be called after all other actions +} + +//=============================================================================Â©Â©ï¬ +StatusCode CaloFutureCorrectionBase::setDBParams(){ + if(m_update)return StatusCode::SUCCESS; // don't update twice before next incident + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Get params from CondDB condition = " << m_conditionName << endmsg; + m_params = Params::Vector(CaloFutureCorrection::nT); + registerCondition(m_conditionName, m_cond, &CaloFutureCorrectionBase::updParams); + return runUpdate(); +} +// ============================================================================ +StatusCode CaloFutureCorrectionBase::setOptParams(){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) )debug() << "Get params from options " << endmsg; + if( m_optParams.empty() && m_conditionName != "none" ){ + info()<< "No default options parameters defined"<<endmsg; + return StatusCode::SUCCESS; + } + m_params = Params::Vector(CaloFutureCorrection::nT); + for ( const auto& p : m_optParams ) + { + const std::string& name = p.first; + if ( accept( name ) ) + { + m_params[stringToCorrectionType(name)] = Params( name, p.second ); + } + } + checkParams(); + return StatusCode::SUCCESS; +} +// ============================================================================ +StatusCode CaloFutureCorrectionBase::updParams(){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "updParams() called" << endmsg; + if ( !m_cond ) return Error("Condition points to NULL", StatusCode::FAILURE); + + // toDo + for( const auto& paramName : m_cond->paramNames() ) { + if( m_cond -> exists( paramName ) ){ + const auto & params = m_cond->paramAsDoubleVect( paramName ); + if ( accept( paramName ) ) + { + m_params[ stringToCorrectionType(paramName) ] = Params( paramName, params ); + } + } + } + m_update = true; + checkParams(); + + return StatusCode::SUCCESS; +} + + +CaloFutureCorrection::Parameters +CaloFutureCorrectionBase::getParams(const CaloFutureCorrection::Type type, const LHCb::CaloCellID id) const +{ + const auto & params = m_params[type]; + if ( !params.active ) return { CaloFutureCorrection::Unknown, CaloFutureCorrection::ParamVector{} }; + + // get parameters + const auto & pars = params.data; + if ( pars.size() < 2 ) return { CaloFutureCorrection::Unknown, CaloFutureCorrection::ParamVector{} }; + + // consistency of pars checked elsewhere - straight parsing here + const auto& func = pars[0]; + const auto& dim = pars[1]; + const int narea = ( func != CaloFutureCorrection::GlobalParamList ) ? 3 : 1; + const int shift = ( func != CaloFutureCorrection::GlobalParamList ) ? id.area() : 0; + int pos = 2 + shift; + + CaloFutureCorrection::ParamVector v; v.reserve(dim); + for ( int i = 0 ; i < dim ; ++i ) + { + v.push_back( pars[pos] ); + pos += narea; + } + return { (CaloFutureCorrection::Function) func , std::move(v) }; +} + + +double CaloFutureCorrectionBase::getCorrection(const CaloFutureCorrection::Type type, + const LHCb::CaloCellID id, + double var, double def) const +{ + + const auto pars = getParams(type,id); + + if ( UNLIKELY(msgLevel( MSG::DEBUG) ) ) + { + const auto& name = CaloFutureCorrection::typeName[ type ]; + debug() << "Correction type " << name << " to be applied on cluster (seed = " << id << ") is a '" + << CaloFutureCorrection::funcName[ pars.first ] << "' function with params = " << pars.second + << endmsg; + } + + // compute correction + if( pars.first == CaloFutureCorrection::Unknown || pars.second.empty() ) return def; + + // list accessor - not correction : + if( pars.first == CaloFutureCorrection::ParamList || pars.first == CaloFutureCorrection::GlobalParamList) + { + warning() << " Param accessor is a fake function - no correction to be applied - return default value" << endmsg; + return def; + } + + double cor = def; + // polynomial correction + const auto & temp = pars.second; + + // polynomial functions + if (pars.first == CaloFutureCorrection::Polynomial || + pars.first == CaloFutureCorrection::InversPolynomial || + pars.first == CaloFutureCorrection::ExpPolynomial || + pars.first == CaloFutureCorrection::ReciprocalPolynomial ){ + double v = 1.; + cor = 0.; + for( auto i = temp.begin() ; i != temp.end() ; ++ i){ + cor += (*i) * v; + if( pars.first == CaloFutureCorrection::ReciprocalPolynomial ) + v = (var == 0) ? 0. : v/var ; + else + v *= var; +#if defined(__clang__) +#warning "Activating workaround for FPE with clang" + // Without this, clang optimiser does something with this loop that causes FPE... + if ( UNLIKELY(msgLevel(MSG::VERBOSE)) ) verbose() << "cor = " << cor << endmsg; +#endif + } + if( pars.first == CaloFutureCorrection::InversPolynomial) cor = ( cor == 0 ) ? def : 1./cor; + if( pars.first == CaloFutureCorrection::ExpPolynomial) cor = ( cor == 0 ) ? def : myexp(cor); + } + + // sigmoid function + else if( pars.first == CaloFutureCorrection::Sigmoid ){ + if( temp.size() == 4){ + const auto& a = temp[0]; + const auto& b = temp[1]; + const auto& c = temp[2]; + const auto& d = temp[3]; + cor = a + b*mytanh(c*(var+d)); + } + else{ + Warning("The power sigmoid function must have 4 parameters").ignore(); + } + } + + // Sshape function + else if( pars.first == CaloFutureCorrection::Sshape || pars.first == CaloFutureCorrection::SshapeMod ){ + if( temp.size() == 1){ + const auto& b = temp[0]; + constexpr double delta = 0.5; + if( b > 0 ) { + double arg = var/delta ; + if ( pars.first == CaloFutureCorrection::SshapeMod ) { arg *= mysinh(delta/b); } + else if ( pars.first == CaloFutureCorrection::Sshape ) { arg *= mycosh(delta/b); } + cor = b * mylog( arg + std::sqrt( arg*arg + 1.0 ) ); + } + } + else{ + Warning("The Sshape function must have 1 parameter").ignore(); + } + } + + // Shower profile function + else if( pars.first == CaloFutureCorrection::ShowerProfile ){ + if( temp.size() == 10){ + if( var > 0.5 ) { + cor = temp[0] * myexp( -temp[1]*var); + cor += temp[2] * myexp( -temp[3]*var); + cor += temp[4] * myexp( -temp[5]*var); + }else{ + cor = 2.; + cor -= temp[6] * myexp( -temp[7]*var); + cor -= temp[8] * myexp( -temp[9]*var); + } + }else{ + Warning("The ShowerProfile function must have 10 parameters").ignore(); + } + } + + // Sinusoidal function + else if( pars.first == CaloFutureCorrection::Sinusoidal ){ + if( temp.size() == 1){ + const double& A = temp[0]; + cor = A*mysin(2*M_PI*var); + } + else{ + Warning("The Sinusoidal function must have 1 parameter").ignore(); + } + } + + if(counterStat->isVerbose())kounter(type,id.areaName()) += cor; + + return cor; +} + + +void CaloFutureCorrectionBase::checkParams(){ + if ( m_params.size() != CaloFutureCorrection::nT ){ + warning() << "Corrections vector size != " << CaloFutureCorrection::nT << endmsg; + } + for( auto& param : m_params ){ + if ( !param.active ) continue; + const auto & type = param.type; + // is the type registered + bool ok = false; + for( unsigned int i = 0 ; i != CaloFutureCorrection::lastType ; ++i ){ + if( type == CaloFutureCorrection::typeName[i]){ + ok = true; + break; + } + } + if( !ok ){ + warning() << " o Type " << type << " is not registered" << endmsg; + param.clear(); + continue; + } + + const auto & vec = param.data; + int func = CaloFutureCorrection::Unknown; + int dim = 0; + if( vec.size() < 3 ) ok = false; + else{ + func = vec[0]; + dim = vec[1]; + if( func >= CaloFutureCorrection::Unknown )ok = false; + int narea = ( func != CaloFutureCorrection::GlobalParamList ) ? 3 : 1; + if( narea*dim+2 != (int) vec.size())ok=false; + if( dim <= 0 ) ok = false; + } + if( !ok ){ + warning() << " o Parameters for correction '"<< type << "' are badly defined : [ " << vec << " ]"<< endmsg; + param.clear(); + }else{ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " o Will apply correction '" << type <<"' as a '" << CaloFutureCorrection::funcName[ func ] + << "' function of " << dim << " parameters" << endmsg; + } + } +} + + + +double CaloFutureCorrectionBase::incidence(const LHCb::CaloHypo* hypo, bool straight)const +{ + const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo(hypo,true) ; + double incidence = 0; + if ( LHCb::CaloHypo::Hypothesis::EmCharged == hypo->hypothesis() && !straight ) + { + // for electron hypothesis : get the matching track + if ( exist<LHCb::CaloFuture2Track::IClusTrTable>(m_cmLoc) ) + { + auto * ctable = m_tables->getClusTrTable( m_cmLoc ); + const auto range = ctable -> relations(cluster); + if ( !range.empty() ) + { + const LHCb::Track * ctrack = range.front(); + // temporary protoParticle + auto * proto = new LHCb::ProtoParticle(); + proto->setTrack( ctrack ); + proto->addToCalo( hypo ); + if ( m_caloElectron->set(proto) ) { incidence = m_caloElectron->caloState().momentum().Theta() ; } + delete proto; + } + } + } + else + { + // for neutrals : + auto cMomentum = LHCb::CaloMomentum( hypo ); + incidence = cMomentum.momentum().Theta(); + } + return incidence; +} + +double CaloFutureCorrectionBase::getCorrectionDerivative(const CaloFutureCorrection::Type type, + const LHCb::CaloCellID id , + double var, double def) const +{ + const auto pars = getParams( type , id ); + + if ( msgLevel( MSG::DEBUG) ) + { + const auto name = CaloFutureCorrection::typeName[ type ]; + debug() << "Derivative for Correction type " << name + << " to be calculated for cluster (seed = " << id + << ") is a '" + << CaloFutureCorrection::funcName[ pars.first ] + << "' function with params = " << pars.second << endmsg; + } + + // compute correction + double cor = def; + if( pars.first == CaloFutureCorrection::Unknown || pars.second.empty() ) return cor; + + // polynomial correction + const auto & temp = pars.second; + + // polynomial functions + double ds = 0.; + if ( pars.first == CaloFutureCorrection::Polynomial ) + { + ds = 0.; + double v = 1.; + int cnt = 0; + auto i = temp.begin(); + for( ++ i, cnt ++ ; i != temp.end() ; ++ i, cnt ++){ + ds += (*i) * cnt * v; + v *= var; + } + } + + else if (pars.first == CaloFutureCorrection::InversPolynomial ) + { + double v = 1.; + cor = 0.; + for( auto i = temp.begin() ; i != temp.end() ; ++ i){ + cor += (*i) * v; + v *= var; + } + cor = ( cor == 0 ) ? def : 1./cor; + + v = 1.; + ds = 0.; + int cnt = 0; + auto i = temp.begin(); + for( ++ i, cnt ++ ; i != temp.end() ; ++ i, cnt ++){ + ds += (*i) * cnt * v; + v *= var; + } + ds *= -cor*cor; + } + + else if (pars.first == CaloFutureCorrection::ExpPolynomial ) + { + double v = 1.; + cor = 0.; + for( auto i = temp.begin() ; i != temp.end() ; ++ i){ + cor += (*i) * v; + v *= var; + } + cor = ( cor == 0 ) ? def : myexp(cor); + + ds = 0.; + v = 1.; + int cnt = 0; + auto i = temp.begin(); + for( ++ i, cnt ++ ; i != temp.end() ; ++ i, cnt ++){ + ds += (*i) * cnt * v; + v *= var; + } + + ds *= cor; + } + + else if (pars.first == CaloFutureCorrection::ReciprocalPolynomial ) + { + ds = 0.; + if ( var != 0 ){ + auto v = 1./(var*var); + int cnt = 0; + auto i = temp.begin(); + for( ++ i, cnt ++ ; i != temp.end() ; ++ i, cnt ++){ + ds -= (*i) * cnt * v; + v /= var; + } + } + } + + // sigmoid function + else if( pars.first == CaloFutureCorrection::Sigmoid ) + { + ds = 0.; + if( temp.size() == 4){ + // double a = temp[0]; + const auto & b = temp[1]; + const auto & c = temp[2]; + const auto & d = temp[3]; + ds = b*c*(1.- std::pow( mytanh(c*(var+d)),2) ); + } + else{ + Warning("The power sigmoid function must have 4 parameters").ignore(); + } + } + + + // Sshape function + else if( pars.first == CaloFutureCorrection::Sshape || pars.first == CaloFutureCorrection::SshapeMod ){ + ds = 0.; + if( temp.size() == 1){ + const auto& b = temp[0]; + double delta = 0.5; + if( b > 0 ) { + double csh = 1.; + if ( pars.first == CaloFutureCorrection::SshapeMod ) { csh = mysinh(delta/b); } + else if ( pars.first == CaloFutureCorrection::Sshape ) { csh = mycosh(delta/b); } + const auto arg = var/delta * csh; + ds = b / delta * csh / std::sqrt( arg*arg + 1. ); + } + } + else{ + Warning("The Sshape function must have 1 parameter").ignore(); + } + } + + // Shower profile function + else if( pars.first == CaloFutureCorrection::ShowerProfile ){ + ds = 0.; + if( temp.size() == 10){ + if( var > 0.5 ) { + ds = -temp[0]*temp[1]*myexp( -temp[1]*var); + ds+= -temp[2]*temp[3]*myexp( -temp[3]*var); + ds+= -temp[4]*temp[5]*myexp( -temp[5]*var); + }else{ + ds = temp[6]*temp[7]*myexp( -temp[7]*var); + ds+= temp[8]*temp[9]*myexp( -temp[9]*var); + } + }else{ + Warning("The ShowerProfile function must have 10 parameters").ignore(); + } + } + + // Sinusoidal function + else if( pars.first == CaloFutureCorrection::Sinusoidal ){ + ds = 0.; + if( temp.size() == 1){ + const auto& A = temp[0]; + constexpr double twopi=2.*M_PI; + ds = A*twopi*mycos(twopi*var); + } + else{ + Warning("The Sinusoidal function must have 1 parameter").ignore(); + } + + } + + return ds; +} + diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h new file mode 100644 index 0000000000000000000000000000000000000000..486d7dde151d80df04e1b66f7e6b141b1ea8e685 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureCorrectionBase.h @@ -0,0 +1,400 @@ +#ifndef CALOFUTURECORRECTIONBASE_H +#define CALOFUTURECORRECTIONBASE_H 1 + +// Include files +#include "GaudiAlg/GaudiTool.h" +#include "DetDesc/Condition.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "Kernel/CaloCellID.h" +#include "CaloFutureUtils/ClusterFunctors.h" +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureDAQ/ICaloFutureDigitFilterTool.h" +#include "Event/CaloHypo.h" +#include "Event/CaloDigit.h" +#include "GaudiKernel/Point3DTypes.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "CaloFutureUtils/CaloMomentum.h" +#include "CaloFutureUtils/ICaloFutureElectron.h" +#include "CaloFutureUtils/CaloFuture2Track.h" +#include "Relations/IRelationWeighted2D.h" +#include "Event/Track.h" +#include "CaloFutureInterfaces/ICaloFutureRelationsGetter.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" +#include "GaudiKernel/IIncidentListener.h" +#include "GaudiKernel/IIncidentSvc.h" + +// VDT +#include "vdt/vdtMath.h" + +static const InterfaceID IID_CaloFutureCorrectionBase ( "CaloFutureCorrectionBase", 1, 0 ); + +/** @class CaloFutureCorrectionBase CaloFutureCorrectionBase.h + * + * + * @author Olivier Deschamps + * @date 2010-05-07 + */ + + +namespace CaloFutureCorrectionUtils{ + class DigitFromCaloFuture { + public: + explicit DigitFromCaloFuture( const int calo ): m_calo( calo ) {} ; + explicit DigitFromCaloFuture( const std::string& calo ): DigitFromCaloFuture( CaloCellCode::CaloNumFromName( calo ) ) {} ; + inline bool operator() ( const LHCb::CaloDigit* digit ) const{ + return digit && ( ( (int) digit->cellID().calo() ) == m_calo ) ; + }; + DigitFromCaloFuture() = delete; + private: + int m_calo{0} ; + }; +} +// DO NOT CHANGE THE FUNCTION ORDER FOR BACKWARD COMPATIBILITY WITH EXISTING CONDITIONS DB +namespace CaloFutureCorrection +{ + enum Function + { + InversPolynomial =0, + Polynomial =1, + ExpPolynomial =2, + ReciprocalPolynomial=3, + Sigmoid =4, + Sshape =5, + ShowerProfile =6, + SshapeMod =7, + Sinusoidal =8, + ParamList =9, // simple parameter access (by area) + GlobalParamList =10, // simple parameter access (ind. of area) + Unknown // MUST be the last item + }; + using ParamVector = std::vector<double>; + using Parameters = std::pair< CaloFutureCorrection::Function , ParamVector >; + enum Type + { + // E-Correction parameters + alphaG, // global alpha factor + alphaE, // alpha(E) + alphaB, // alpha(Bary) + alphaX, // alpha(Dx) + alphaY, // alpha(Dy) + alphaP, // alpha(ePrs) + beta, // Prs correction (with possible eEcal dependency) + betaP, // Prs correction (with possible ePrs dependency) + betaPR, // Prs correction (with possible ePrs/eEcal dependency) + betaC, // Prs correction for converted photons (use beta if not defined) + betaCP, // "" + betaCPR, // "" + globalC, // global factor for converted photons + globalT, // global(DeltaTheta) function of incidence angle + offsetT, // offset(DeltaTheta) function of incidence angle + offset, // offset( sinTheta ) energy (or ET ) offset + offsetC, // offset( sinTheta ) energy (or ET ) offset for converted photons + // + ClusterCovariance, // parameters for cluster covariance estimation + // L-Correction parameters + gamma0, + delta0, + gammaP, + deltaP, + // S-correction parameters + shapeX, + shapeY, + residual, + residualX, + residualY, + asymP, + asymM, + angularX, + angularY, + // ShowerShape profile + profile, + profileC, // for converted photons + // Cluster masking + EnergyMask, + PositionMask, + lastType // MUST BE THE LAST LINE + }; + static const int nT = lastType+1; + static const int nF = Unknown+1; + static const std::string typeName[nT] = + { "alphaG", "alphaE","alphaB","alphaX","alphaY","alphaP","beta","betaP","betaPR","betaC","betaCP","betaCPR" // E-corrections + ,"globalC","globalT" ,"offsetT","offset","offsetC","ClusterCovariance" + ,"gamma0","delta0","gammaP","deltaP" // L-Corrections + ,"shapeX","shapeY","residual","residualX","residualY","asymP","asymM","angularX","angularY" // S-Corrections + ,"profile","profileC" // Profile shape + ,"EnergyMask","PositionMask" + ,"Unknown"}; + + static const std::string funcName[nF] = + { "InversPolynomial", "Polynomial","ExpPolynomial","ReciprocalPolynomial","Sigmoid" + ,"Sshape","ShowerProfile","SshapeMod","Sinusoidal","ParamList","GlobalParamList","Unknown" }; +} + +class CaloFutureCorrectionBase : public GaudiTool, virtual public IIncidentListener +{ + +public: + + // Return the interface ID + static const InterfaceID& interfaceID() { return IID_CaloFutureCorrectionBase; } + + /// Standard constructor + CaloFutureCorrectionBase( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; ///< Algorithm initialization + StatusCode finalize() override; ///< Algorithm finalization + + void setOrigin(Gaudi::XYZPoint origin){m_origin = origin;} + StatusCode updParams(); + + StatusCode setConditionParams(const std::string & cond,bool force=false) + { // force = true : forcing access via condDB only + if(cond != m_conditionName)m_conditionName = cond; + + // get parameters from options : + if( !m_useCondDB && !force )return setOptParams(); + + // get from DB if exists : + if( !existDet<DataObject>( m_conditionName) ){ + if(force){ + if ( m_conditionName != "none" ) info() << "Condition '"<< m_conditionName.value() << "' has not been found " << endmsg; + return StatusCode::SUCCESS; + }else{ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << " Condition '" << m_conditionName.value() << "' has not found -- try options parameters !" << endmsg; + return setOptParams(); + } + } + return setDBParams(); + } + + + // accessors + CaloFutureCorrection::Parameters getParams(const CaloFutureCorrection::Type type, + const LHCb::CaloCellID id=LHCb::CaloCellID()) const; + inline CaloFutureCorrection::ParamVector getParamVector(const CaloFutureCorrection::Type type, + const LHCb::CaloCellID id=LHCb::CaloCellID()) const + { + return getParams(type,id).second; + } + double getParameter(CaloFutureCorrection::Type type, unsigned int i, + const LHCb::CaloCellID id=LHCb::CaloCellID(),double def=0.) const + { + const auto params = getParams(type,id); + const auto& data = params.second; + return (i < data.size()) ? data[i] : def; + } + /// return value of analytic derivative for a given function type in cell id at a given point var with default value def + double getCorrectionDerivative(const CaloFutureCorrection::Type type, const LHCb::CaloCellID id , double var = 0.,double def = 0.) const; + //// propagate cov.m. cov0 according to Jacobian jac: cov1 = (jac * cov * jac^T), see comments in CaloFutureECorrection.cpp and CaloFutureSCorrection.cpp + // void recalculate_cov(const TMatrixD &jac, const TMatrixDSym &cov0, TMatrixDSym &cov1) const; + + + double getCorrection(const CaloFutureCorrection::Type type, const LHCb::CaloCellID id , double var = 0.,double def = 1.) const; + double incidence(const LHCb::CaloHypo* hypo,bool straight=false) const; + + void getPrsSpd(const LHCb::CaloHypo* hypo,double& ePrs,double& eSpd) const + { + typedef const LHCb::CaloHypo::Digits Digits; + const auto & digits = hypo->digits(); + for( Digits::const_iterator d = digits.begin() ; digits.end() != d ; ++d ) + { + if ( *d == 0 ) { continue ; } + else if( m_prs( *d ) ) { ePrs += (*d)->e() ; } + else if( m_spd( *d ) ) { eSpd += (*d)->e() ; } + } + } + + ICaloFutureDigitFilterTool* pileup() const noexcept { return m_pileup;} + + bool hasConditionChanged() const noexcept {return m_update;} + void handle(const Incident& ) override { m_update = false; }// reset update flag + +protected: + + Gaudi::Property<std::string> m_conditionName {this, "ConditionName", "none"}; + Gaudi::Property<std::vector<std::string>> m_corrections {this, "Corrections", {"All"}}; + // + typedef std::vector<LHCb::CaloHypo::Hypothesis> Hypotheses ; + typedef std::vector<int> Hypotheses_ ; + Hypotheses m_hypos; + Gaudi::Property<Hypotheses_> m_hypos_ {this, "Hypotheses", { + (int) LHCb::CaloHypo::Hypothesis::Photon, + (int) LHCb::CaloHypo::Hypothesis::PhotonFromMergedPi0, + (int) LHCb::CaloHypo::Hypothesis::EmCharged, + }, "acceptable hypotheses"}; + + LHCb::ClusterFunctors::ClusterArea m_area; + LHCb::ClusterFunctors::ClusterFromCaloFuture m_calo{DeCalorimeterLocation::Ecal}; + CaloFutureCorrectionUtils::DigitFromCaloFuture m_spd{DeCalorimeterLocation::Spd}; + CaloFutureCorrectionUtils::DigitFromCaloFuture m_prs{DeCalorimeterLocation::Prs}; + std::string m_detData{DeCalorimeterLocation::Ecal}; + const DeCalorimeter* m_det = nullptr; + Gaudi::XYZPoint m_origin; + ICaloFutureDigitFilterTool* m_pileup = nullptr; + Gaudi::Property<bool> m_correctCovariance {this, "CorrectCovariance", true}; + + template< typename TYPE > + inline TYPE myexp( const TYPE x ) const + { + //info() << "In myexp " << x << endmsg; + //return std::exp(x); + return vdt::fast_exp(x); + } + + template< typename TYPE > + inline TYPE mylog( const TYPE x ) const + { + //info() << "In mylog " << x << endmsg; + //return std::log(x); + return vdt::fast_log(x); + } + + template< typename TYPE > + inline TYPE myatan( const TYPE x ) const + { + //info() << "In myatan " << x << endmsg; + //return std::atan(x); + return vdt::fast_atan(x); + } + + template< typename TYPE > + inline TYPE myatan2( const TYPE x, const TYPE y ) const + { + //info() << "In myatan2 " << x << " " << y << endmsg; + //return std::atan2(x,y); + return vdt::fast_atan2(x,y); + } + + template< typename TYPE > + inline TYPE mycos( const TYPE x ) const + { + //info() << "In mycos " << x << endmsg; + //return std::cos(x); + return vdt::fast_cos(x); + } + + template< typename TYPE > + inline TYPE mysin( const TYPE x ) const + { + //info() << "In mysin " << x << endmsg; + //return std::sin(x); + return vdt::fast_sin(x); + } + + template< typename TYPE > + inline TYPE mytanh( const TYPE x ) const + { + //info() << "In mytanh " << x << endmsg; + //return std::tanh(x); + const auto y = myexp(-2.0*x); + return ( 1.0 - y ) / ( 1.0 + y ); + } + + template< typename TYPE > + inline TYPE mysinh( const TYPE x ) const + { + //info() << "In mysinh " << x << endmsg; + //return std::sinh(x); + const auto y = myexp(-x); + return 0.5 * ( (1.0/y) - y ); + } + + template< typename TYPE > + inline TYPE mycosh( const TYPE x ) const + { + //info() << "In mycosh " << x << endmsg; + //return std::cosh(x); + const auto y = myexp(-x); + return 0.5 * ( (1.0/y) + y ); + } + +private: + + inline CaloFutureCorrection::Type stringToCorrectionType ( const std::string & type ) + { + for ( int i = 0; i < CaloFutureCorrection::nT; ++i ) + { + if ( CaloFutureCorrection::typeName[i] == type ) return static_cast<CaloFutureCorrection::Type>(i); + } + return static_cast<CaloFutureCorrection::Type>(CaloFutureCorrection::lastType); + } + + ICaloFutureElectron * m_caloElectron = nullptr; + + bool accept(const std::string& name){ + for( auto it = m_corrections.begin() ; m_corrections.end() != it ; ++it){ + if( name == *it || *it == "All")return true; + } + return false; + } + + StatusCode setOptParams(); + StatusCode setDBParams(); + void checkParams(); + + class Params + { + public: + Params() = default; + Params( const std::string & t, + const CaloFutureCorrection::ParamVector & v ) + : active(true), type(t), data(v) { } + public: + void clear() { active = false; data.clear(); } + public: + bool active{false}; + std::string type; + CaloFutureCorrection::ParamVector data; + public: + typedef std::vector<Params> Vector; + }; + + /// Cache counters, as looking them up as + /// counter( CaloFutureCorrection::typeName[ type ] + " correction processing (" + areaName + ")" ) + /// requires the creation of a temporary string every time, which in turn + /// involves (eventually) a call to 'new' and 'delete' -- and the above was the source of 10% (!) + /// of the # of calls to 'new' and 'delete' in the HLT!!!! (FYI: there are, on average, 1K calls + /// per event to this method!!!) + /// + /// On top of that, this also speeds up the actual search for the correct counter, + /// by making it a two-step process, and the first step is a direct lookup + /// instead of a 'find'. + /// + /// in the end, this change alone speeds up the total HLT by about 1%... + inline StatEntity& kounter(const CaloFutureCorrection::Type type, const std::string& areaName) const + { + assert( type < CaloFutureCorrection::lastType+1 ); + auto a = m_counters[type].find(areaName); + if ( UNLIKELY( a == std::end(m_counters[type]) ) ) + { + const auto name = CaloFutureCorrection::typeName[type] + " correction processing (" + areaName + ")"; + auto r = m_counters[type].insert( areaName, &counter(name) ); + assert(r.second); + a = r.first; + } + assert(a->second); + return *(a->second); + } + +private: + + Params::Vector m_params{ CaloFutureCorrection::nT }; + + Gaudi::Property<std::map< std::string, std::vector<double> >> m_optParams + {this, "Parameters"}; + + mutable std::array< GaudiUtils::VectorMap<std::string, StatEntity* >, CaloFutureCorrection::lastType+1 > m_counters; + Condition* m_cond = nullptr; + Gaudi::Property<std::string> m_cmLoc {this, "ClusterMatchLocation"}; + ICaloFutureRelationsGetter* m_tables = nullptr; + Gaudi::Property<bool> m_useCondDB {this, "UseCondDB", true}; + bool m_update{false}; + +protected: + + IFutureCounterLevel* counterStat = nullptr; + +}; +#endif // CALOFUTURECORRECTIONBASE_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureDigitsFilterAlg.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureDigitsFilterAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d320c83c5f3f0f551124328931ed3a0c5f50fabe --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureDigitsFilterAlg.cpp @@ -0,0 +1,157 @@ +// ============================================================================ +// Include files +// Event +#include "Event/CaloDigit.h" +#include "Event/CaloCluster.h" +#include "Event/CaloHypo.h" +// local +#include "CaloFutureDigitsFilterAlg.h" + +// ============================================================================ +/** @file CaloFutureDigitsFilterAlg.cpp + * + * Template implementation file for class : CaloFutureDigitsFilterAlg + * @see CaloFutureDigitsFilterAlg + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 02/11/2001 + */ +// ============================================================================ + +DECLARE_COMPONENT( CaloFutureDigitsFilterAlg ) + +// ============================================================================ +/** standard algorithm finalization + * @see GaudiAlgorithm + * @see Algorithm + * @see IAlgorithm + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureDigitsFilterAlg::finalize() +{ + /// clear container + m_hypos.clear(); + /// finalize the base class + return GaudiAlgorithm::finalize(); +} +// ============================================================================ + +// ============================================================================ +/** standard algorithm execution + * @see GaudiAlgorithm + * @see Algorithm + * @see IAlgorithm + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureDigitsFilterAlg::execute() +{ + /// avoid long names and types + typedef LHCb::CaloHypos Hypos ; + typedef LHCb::CaloHypo::Digits Digs ; + typedef LHCb::CaloDigits Digits ; + typedef LHCb::CaloClusters Clusters ; + typedef LHCb::CaloCluster::Entries Entries ; + typedef LHCb::CaloDigitStatus::Status Status ; + + // get digits + Digits* digits = get<Digits>( m_inputData ); + if( 0 == digits ) { return StatusCode::FAILURE ; } + + // create new digits + Digits filter; + + // auxillary container of "used" IDs + typedef std::vector<LHCb::CaloDigit*> Tmp; + Tmp used; + + // loop over containers of hypos + for( Addresses::const_iterator address = m_hypos.begin() ; + m_hypos.end() != address ; ++address ) + { + Hypos* hypos = get<Hypos> ( *address ) ; + if( 0 == hypos ) { return StatusCode::FAILURE ; } + // loop over all hypos + for( Hypos::iterator hypo = hypos->begin() ; + hypos->end() != hypo ; ++hypo) + { + if( 0 == *hypo ) { continue ; } + // loop over all "extra" digits + Digs& digs = (*hypo)->digits(); + for( Digs::iterator digit = digs.begin() ; + digs.end() != digit ; ++digit ) + { + LHCb::CaloDigit* dig = *digit ; + if( 0 == dig ) { continue ; } + if( dig->parent() == digits ) { used.push_back( dig ); } + } // end of loop over all "extra" digits + } // end loop over all hypos + } // end of loop over all containers of hypos + + + if( !m_statuses.empty() ) + { + // loop over containers clusters + for( Addresses::const_iterator address = m_clusters.begin() ; + m_clusters.end() != address ; ++address ) + { + Clusters* clusters = get<Clusters>( *address ); + if( 0 == clusters ) { return StatusCode::FAILURE ; } + // loop over clusters + for( Clusters::iterator cluster = clusters->begin() ; + clusters->end() != cluster ; ++cluster ) + { + LHCb::CaloCluster* cl = *cluster ; + if( 0 == cl ) { continue ; } + Entries& entries = cl->entries() ; + for( Entries::iterator entry = entries.begin() ; + entries.end() != entry ; ++entry ) + { + LHCb::CaloDigit* digit = entry->digit(); + if( 0 == digit ) { continue ; } + // correct parent ? + if( digits != digit->parent() ) { continue ; } + bool keep = false ; + for( Statuses::const_iterator st = m_statuses.begin() ; + m_statuses.end() != st ; ++st ) + { + if( entry->status() & (Status) *st ) + { keep = true ; break; } + } + if( keep ) { used.push_back ( digit ) ; } + else { entry->setDigit ( (LHCb::CaloDigit*) 0 ) ; } + } + } + } + } + + { // eliminate duplicates + std::stable_sort( used.begin() , used.end() ); + Tmp::iterator it = std::unique( used.begin() , used.end() ); + used.erase( it , used.end() ); + while( !used.empty() ) { filter.insert( used.back() ) ; used.pop_back();} + } + + const unsigned int all = digits -> size() ; + + { // clear digits + digits -> clear(); + // copy filter to digits + for( Digits::iterator dig = filter.begin() ; filter.end() != dig ; ++dig ) + { digits->insert( *dig ); } + // clear filter + filter.clear(); + } + + const unsigned int kept = digits->size() ; + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug () << "'" << m_inputData << "' : " + << " Kept " << kept << " digits from " + << all << endmsg ; + + return StatusCode::SUCCESS ; +} +// ============================================================================ + diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureDigitsFilterAlg.h b/CaloFuture/CaloFutureReco/src/CaloFutureDigitsFilterAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..4606afbdaeb5c358fb6be64504fdbf6c7b638f19 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureDigitsFilterAlg.h @@ -0,0 +1,59 @@ +#ifndef CALOFUTURERECO_CALOFUTUREDIGITSFILTERALG_H +#define CALOFUTURERECO_CALOFUTUREDIGITSFILTERALG_H 1 +// Include files +// from STL +#include <string> +#include <vector> + +// from GaudiAlg +#include "GaudiAlg/GaudiAlgorithm.h" + + +/** @class CaloFutureDigitsFilterAlg CaloFutureDigitsFilterAlg.h + * + * Simple algorithm to perform filtering of CaloDigits + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 2002-06-11 + */ +class CaloFutureDigitsFilterAlg : + public GaudiAlgorithm +{ +public: + + /** standard algorithm execution + * @see GaudiAlgorithm + * @see Algorithm + * @see IAlgorithm + * @return status code + */ + StatusCode execute() override; + + /** standard algorithm finalization + * @see GaudiAlgorithm + * @see Algorithm + * @see IAlgorithm + * @return status code + */ + StatusCode finalize() override; + + /// Standard constructor + using GaudiAlgorithm::GaudiAlgorithm; + +private: + + typedef std::vector<std::string> Addresses ; + typedef std::vector<int> Statuses ; + + Gaudi::Property<std::string> m_inputData {this, "InputData"}; + Gaudi::Property<Addresses> m_hypos {this, "Hypotheses"}; + Gaudi::Property<Addresses> m_clusters {this, "Clusters"}; + Gaudi::Property<Statuses> m_statuses {this, "Statuses", { + LHCb::CaloDigitStatus::SeedCell, + LHCb::CaloDigitStatus::LocalMaximum, + LHCb::CaloDigitStatus::CentralCell, + }}; + +}; +// ============================================================================ +#endif // CALOFUTURERECO_CALOFUTUREDIGITSFILTERALG_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureECorrection.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureECorrection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..928b4aee0c4518806405f75a7405f0c790f330c2 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureECorrection.cpp @@ -0,0 +1,638 @@ +// ============================================================================ +// Include files +#include "GaudiKernel/SystemOfUnits.h" +#include "Event/CaloHypo.h" +#include "CaloFutureECorrection.h" + +/** @file + * Implementation file for class : CaloFutureECorrection + * + * @date 2003-03-10 + * @author Deschamps Olivier + */ + +DECLARE_COMPONENT( CaloFutureECorrection ) + +// ============================================================================ +/* Standard constructor + * @see GaudiTool + * @see AlgTool + * @param type tool type (?) + * @param name tool name + * @param parent tool parent + */ +// ============================================================================ +CaloFutureECorrection::CaloFutureECorrection( const std::string& type , + const std::string& name , + const IInterface* parent ) + : CaloFutureCorrectionBase( type , name , parent ) +{ + + // define conditionName + const std::string uName ( LHCb::CaloFutureAlgUtils::toUpper( name ) ) ; + if ( uName.find( "ELECTRON" ) != std::string::npos ) { + m_conditionName = "Conditions/Reco/Calo/ElectronECorrection"; + } else if ( uName.find( "MERGED" ) != std::string::npos || uName.find( "SPLITPHOTON" ) != std::string::npos ) { + m_conditionName = "Conditions/Reco/Calo/SplitPhotonECorrection"; + } else if ( uName.find( "PHOTON" ) ) { + m_conditionName = "Conditions/Reco/Calo/PhotonECorrection"; + } + + declareInterface<ICaloFutureHypoTool> ( this ) ; + + std::vector<std::string> caloAreas = {"Outer" , "Middle" , "Inner" , "PinArea"}; + m_countersAlpha.reserve(k_numOfCaloFutureAreas); + m_countersBetaTimesEprs.reserve(k_numOfCaloFutureAreas); + for (auto i = 0; i < k_numOfCaloFutureAreas; i++) { + m_countersAlpha.emplace_back(this, "<alpha> " + caloAreas[i]); + m_countersBetaTimesEprs.emplace_back(this, "<beta*ePrs> " + caloAreas[i]); + } +} +// ============================================================================ +// destructor +// ============================================================================ +StatusCode CaloFutureECorrection::finalize () +{ + m_hypos.clear(); + return CaloFutureCorrectionBase::finalize () ; +} +// ============================================================================ +StatusCode CaloFutureECorrection::initialize () +{ + // first initialize the base class + StatusCode sc = CaloFutureCorrectionBase::initialize(); + if ( sc.isFailure() )return Error ( "Unable initialize the base class CaloFutureCorrectionBase!" , sc ) ; + + if ( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Condition name : " << m_conditionName << endmsg; + + //info() << " =========== Condition name : " << m_conditionName << endmsg; + + + + + return StatusCode::SUCCESS ; +} + +// ============================================================================ +StatusCode CaloFutureECorrection::operator() ( LHCb::CaloHypo* hypo ) const +{ + return process( hypo ); +} + +// ============================================================================ +StatusCode CaloFutureECorrection::process ( LHCb::CaloHypo* hypo ) const +{ + + // check arguments + if ( 0 == hypo )return Warning( " CaloHypo* points to NULL!", StatusCode::SUCCESS ) ; + + // check the Hypo + Hypotheses::const_iterator h = std::find( m_hypos.begin() , m_hypos.end() , hypo->hypothesis() ) ; + if ( m_hypos.end() == h )return Error ( "Invalid hypothesis -> no correction applied" , StatusCode::SUCCESS) ; + + // No correction for negative energy : + if ( hypo->e() < 0.) { + ++m_counterSkippedNegativeEnergyCorrection; + return StatusCode::SUCCESS; + } + + // Somewhat inelegant way of data sharing between this const method process() and calcECorrection(). Use of private fields + // of this CaloFutureECorrection class for the same purpose would break the constness of the process() interface. + struct ECorrInputParams _params; // input parameters calculated once in process() and used in all the calcECorrection() calls + ECorrOutputParams _results; // Jacobian elements plus many various intermediate parameters, used e.g. for debug printout + + // input variables passed from process() to calcECorrection() + LHCb::CaloCellID& cellID = _params.cellID; + Gaudi::XYZPoint& seedPos = _params.seedPos; + double& eSpd = _params.eSpd; + double& dtheta = _params.dtheta; + unsigned int& area = _params.area; + + + // get Prs/Spd + double ePrs = 0 ; + eSpd = 0 ; + getPrsSpd(hypo, ePrs, eSpd); + + if ( eSpd == 0 && (m_sFilt & 0x1) == 0)return StatusCode::SUCCESS; + if ( eSpd > 0 && (m_sFilt & 0x2) == 0)return StatusCode::SUCCESS; + if ( ePrs == 0 && (m_pFilt & 0x1) == 0)return StatusCode::SUCCESS; + if ( ePrs > 0 && (m_pFilt & 0x2) == 0)return StatusCode::SUCCESS; + if ( UNLIKELY(msgLevel( MSG::DEBUG) )) + debug() << " Accepted spd/prs : " << (int) (eSpd > 0 ) << " / " << (int) (ePrs > 0) << endmsg; + + // get cluster (special case for SplitPhotons) + const LHCb::CaloCluster* GlobalCluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo(hypo, false); + const LHCb::CaloCluster* MainCluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo(hypo, true) ; + + + /* + Position information (e/x/y ) + */ + if ( 0 == MainCluster )return Warning ( "CaloCluster* points to NULL -> no correction applied" , StatusCode::SUCCESS) ; + + // For Split Photon - share the Prs energy + if ( LHCb::CaloHypo::Hypothesis::PhotonFromMergedPi0 == hypo->hypothesis() ) { + ePrs *= MainCluster->position().e() / GlobalCluster->position().e() ; + } + + // Get position + const LHCb::CaloPosition& position = MainCluster->position(); + double eEcal = position. e () ; + const double xBar = position. x () ; + const double yBar = position. y () ; + + // seed ID & position + const LHCb::CaloCluster::Entries& entries = MainCluster->entries(); + LHCb::CaloCluster::Entries::const_iterator iseed = + LHCb::ClusterFunctors::locateDigit ( entries.begin () , entries.end() , LHCb::CaloDigitStatus::SeedCell ); + if ( entries.end() == iseed )return Warning( "The seed cell is not found -> no correction applied", StatusCode::SUCCESS ) ; + + // get the "area" of the cluster (where seed is) + area = m_area( MainCluster ); + const LHCb::CaloDigit* seed = iseed->digit(); + if ( 0 == seed )return Warning ( "Seed digit points to NULL -> no correction applied", StatusCode::SUCCESS ) ; + // Cell ID for seed digit + cellID = seed->cellID() ; + seedPos = m_det->cellCenter( cellID ); + + // incidence angle + dtheta = incidence( hypo ) - incidence(hypo, true); + // info() << "------> " << incidence( hypo ) << " " << incidence(hypo, true) << " " << dtheta << endmsg; + + // Pileup subtraction at the cluster level + if ( m_pileup->method("Ecal") >= 10 ) { + bool spd = (eSpd > 0) ? true : false; + double offset = m_pileup->offset( cellID, spd ); + if (offset < eEcal) { + const double eee = eEcal; + eEcal -= offset; + m_counterPileupOffset += offset; + m_counterPileupSubstractedRatio += eEcal / eee; + m_counterPileupScale += m_pileup->getScale(); + } + } + + + /** here all information is available + * + * (1) Ecal energy in 3x3 : eEcal + * (2) Prs and Spd energies : ePrs, eSpd + * (3) weighted barycenter : xBar, yBar + * (4) Zone/Area in Ecal : area + * (5) SEED digit : seed (NO for split!) + * (6) CellID of seed digit : cellID (OK for split!) + * (7) Position of seed cell : seedPos (OK for split!) + * + */ + + + ///////////////////////////////////////////////////////// + + + /* Calculate corrected energy in a separate function call. Necessary for debugging the Jacobian by calculating + * numeric derivatives w.r.t. (X, Y, E, [and possibly ePrs]) in case of any changes in the correction code. + * + * Input positions and energies are passed as parameters for ease of numeric derivative calculation, + * all the other paramers and results of intermediate calculations are shared between the two methods + * using local struct ECorrInputParams _params, and [zero-initialized] ECorrOutputParams _results. + */ + double eCor = calcECorrection(xBar, yBar, eEcal, ePrs, _params, &_results); + + // results of semi-analytic derivative calculation + const double& dEcor_dXcl = _results.dEcor_dXcl; + const double& dEcor_dYcl = _results.dEcor_dYcl; + const double& dEcor_dEcl = _results.dEcor_dEcl; + + // protection against unphysical d(Ehypo)/d(Ecluster) == 0 + if ( fabs( dEcor_dEcl ) < 1e-10 ) { + if ( UNLIKELY(msgLevel( MSG::DEBUG) ))debug() << "unphysical d(Ehypo)/d(Ecluster) = " << dEcor_dEcl << " reset to 1 as if Ehypo = Ecluster" << endmsg; + ++m_counterUnphysical; + const_cast<double&>(dEcor_dEcl) = 1.; + } + + // debugging necessary in case if any new corrections are added or their sequence is changed! + if ( UNLIKELY( msgLevel(MSG::DEBUG) && m_correctCovariance ) ) { + const double dx_rel(1e-5), dy_rel(1e-5), de_rel(1e-3); // dx,dy ~ few*0.1*mm, de ~ few MeV + + // calculate numeric derivatives to be compared with analytic ones + debug() << "\n ------------------------ ECorrection(x+dx, y, e) calculation follows ------------------- " << endmsg; + double eCor_x = calcECorrection(xBar * (1 + dx_rel), yBar, eEcal, ePrs, _params, NULL); + + debug() << "\n ------------------------ ECorrection(x, y+dy, e) calculation follows ------------------- " << endmsg; + double eCor_y = calcECorrection(xBar, yBar * (1 + dy_rel), eEcal, ePrs, _params, NULL); + + debug() << "\n ------------------------ ECorrection(e, y, e+de) calculation follows ------------------- " << endmsg; + double eCor_e = calcECorrection(xBar, yBar, eEcal * (1 + de_rel), ePrs, _params, NULL); + + + double dn_eCor_dx = (eCor_x - eCor) / xBar / dx_rel; + double dn_eCor_dy = (eCor_y - eCor) / yBar / dy_rel; + double dn_eCor_de = (eCor_e - eCor) / eEcal / de_rel; + + // avoid division in comparison for possible dE/dX == 0 or dE/dY == 0 + if ( fabs(dEcor_dXcl - dn_eCor_dx) > fabs(dEcor_dXcl) * 0.1 + || fabs(dEcor_dYcl - dn_eCor_dy) > fabs(dEcor_dYcl) * 0.1 + || fabs(dEcor_dEcl - dn_eCor_de) > fabs(dEcor_dEcl) * 0.1 ) { + debug() << " some CaloFutureECorrection analytically-calculated Jacobian elements differ (by > 10%) from numerically-calculated ones! " << endmsg; + } + + debug() << "**********" << " betaC_flag = " << _results.betaC_flag << " ******* Jacobian elements J(2,*) =" << endmsg; + debug() << " semi-analytic dEcor_dXcl = " << dEcor_dXcl << " numeric dn_eCor_dx = " << dn_eCor_dx << endmsg; + debug() << " semi-analytic dEcor_dYcl = " << dEcor_dYcl << " numeric dn_eCor_dy = " << dn_eCor_dy << endmsg; + debug() << " semi-analytic dEcor_dEcl = " << dEcor_dEcl << " numeric dn_eCor_de = " << dn_eCor_de << endmsg; + } + + + + // revoir le debug + if ( UNLIKELY(msgLevel( MSG::DEBUG) )) { + debug() << "CaloFuture hypothesis : " << hypo->hypothesis() << endmsg; + debug() << "cellID : " << cellID << endmsg; + debug() << "eSpd : " << eSpd << " " << "ePrs : " << ePrs << endmsg; + debug() << "asx : " << _results.Asx << " " << "asy : " << _results.Asy << endmsg; + debug() << "alpha " << _results.alpha << " = " << _results.aG << " x " << _results.aE << " x " << _results.aB << " x " << _results.aX << " x " << _results.aY << endmsg; + debug() << "beta " << _results.beta << endmsg; + debug() << "Global Factor " << _results.gC << endmsg; + debug() << "Global theta correction " << _results.gT << endmsg; + debug() << "eEcal " << eEcal << " --> " << "eCor " << eCor << endmsg; + } + + /// assert(cellID.area()>=0 &&cellID.area()<4); + m_countersAlpha.at(cellID.area()) += _results.alpha; + m_countersBetaTimesEprs.at(cellID.area()) += _results.beta * ePrs; + + // update position + LHCb::CaloPosition::Parameters& parameters = hypo ->position() ->parameters () ; + parameters ( LHCb::CaloPosition::Index::E ) = eCor ; + m_counterCorrectedEnergy += eCor; + m_counterDeltaEnergy += eCor - eEcal; + + + // ----------------------------------------- apply semi-analytic cov.m. propagation due to the (X,Y,E) corrections + if ( m_correctCovariance ) { + LHCb::CaloPosition::Covariance& covariance = hypo ->position() ->covariance () ; + + if ( UNLIKELY(msgLevel( MSG::DEBUG)) ) { + debug() << "before E-corr. cov.m. = \n" << covariance << endmsg; + } + + // index numbering just follows ROOT::Math::SMatrix<double,3,3>::Array() for row/column indices (X:0, Y:1, E:2) + double c0[6], c1[6]; + /* + * Indexing following ROOT::Math::SMatrix<double,3,3,ROOT::Math::MatRepSym<double,3> >::Array() : + * + * The iterators access the matrix element in the order how they are + * stored in memory. The C (row-major) convention is used, and in the + * case of symmetric matrices the iterator spans only the lower diagonal + * block. For example for a symmetric 3x3 matrices the order of the 6 + * elements \f${a_0,...a_5}\f$ is: + * \f[ + * M = \left( \begin{array}{ccc} + * a_0 & a_1 & a_3 \\ + * a_1 & a_2 & a_4 \\ + * a_3 & a_4 & a_5 \end{array} \right) + * \f] + */ + c0[0] = covariance(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::X); // arr[0] not relying on LHCb::CaloFuturePosition::Index::X == 0 + c0[2] = covariance(LHCb::CaloPosition::Index::Y, LHCb::CaloPosition::Index::Y); // arr[2] not relying on LHCb::CaloFuturePosition::Index::Y == 1 + c0[5] = covariance(LHCb::CaloPosition::Index::E, LHCb::CaloPosition::Index::E); // arr[5] not relying on LHCb::CaloFuturePosition::Index::E == 2 + c0[1] = covariance(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::Y); // arr[1] + c0[3] = covariance(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::E); // arr[3] + c0[4] = covariance(LHCb::CaloPosition::Index::Y, LHCb::CaloPosition::Index::E); // arr[4] + + // cov1 = (J * cov0 * J^T) for the special case of Jacobian for (X,Y,E) -> (X1=X, Y1=Y, E1=E(X,Y,E)) + c1[0] = c0[0]; + c1[1] = c0[1]; + c1[2] = c0[2]; + c1[3] = c0[0] * dEcor_dXcl + c0[1] * dEcor_dYcl + c0[3] * dEcor_dEcl; + c1[4] = c0[1] * dEcor_dXcl + c0[2] * dEcor_dYcl + c0[4] * dEcor_dEcl; + double tmp = c0[3] * dEcor_dXcl + c0[4] * dEcor_dYcl + c0[5] * dEcor_dEcl; + c1[5] = c1[3] * dEcor_dXcl + c1[4] * dEcor_dYcl + tmp * dEcor_dEcl; + + // additional protection against cov.m.(E,E) <= 0 due to numerical effects + if ( c1[5] < 1.e-10 ) { + if ( UNLIKELY(msgLevel( MSG::DEBUG) ))debug() << "unphysical variance(Ehypo) = " << c1[5] << " reset cov.m.(Ehypo,*) = cov.m.(Ecluster,*) as if Ehypo = Ecluster" << endmsg; + ++m_counterUnphysicalVariance; + c1[5] = c0[5]; + c1[3] = c0[3]; + c1[4] = c0[4]; + } + + // --------------------------------------------------------------------------- alternative calculation for a general-form Jacobian + // /* typedef ROOT::Math::SMatrix<double, 3, 3, ROOT::Math::MatRepSym<double,3> > Gaudi::SymMatrix3x3; + // * typedef Gaudi::SymMatrix3x3 LHCb::CaloPosition::Covariance; + // * + // * calculations done with TMatrixDSym (for which TMatrixD.Mult() is defined) for simplicity instead of ROOT::Math::SMatrix<...> + // * cov1 = J * cov0 * J^T + // */ + // + // // Jacobian for (X,Y,E) -> (X1=X, Y1=Y, E1=E(X,Y,E)) + // TMatrixD jac(3, 3); + // jac(0,0) = 1.; + // jac(1,1) = 1.; + // jac(2,0) = dEcor_dXcl; + // jac(2,1) = dEcor_dYcl; + // jac(2,2) = dEcor_dEcl; + // // std::cout << "jacobian = " << std::endl; jac.Print(); + // + // TMatrixDSym cov0( 3 ); // cov.m. is 3x3 + // + // // use of SMatrix<>::Array() would have required less to type but assumes a particular storage sequence of the (X,Y,E) elements + // cov0(0,0) = covariance(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::X); // c0[0] nomatter if LHCb::CaloPosition::Index::X == 0 + // cov0(1,1) = covariance(LHCb::CaloPosition::Index::Y, LHCb::CaloPosition::Index::Y); // c0[2] nomatter if LHCb::CaloPosition::Index::Y == 1 + // cov0(2,2) = covariance(LHCb::CaloPosition::Index::E, LHCb::CaloPosition::Index::E); // c0[5] nomatter if LHCb::CaloPosition::Index::E == 2 + // cov0(1,0) = cov0(0,1) = covariance(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::Y); // c0[1] + // cov0(2,0) = cov0(0,2) = covariance(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::E); // c0[3] + // cov0(2,1) = cov0(1,2) = covariance(LHCb::CaloPosition::Index::Y, LHCb::CaloPosition::Index::E); // c0[4] + // + // // cov1 = J * cov *J^T using TMatrixD.Mult() and TMatrixDSym for a general-form Jacobian J + // TMatrixDSym cov1( cov0 ); + // recalculate_cov(jac, cov0, cov1); + // + // // std::cout << "cov0 = " << std::endl; cov0.Print(); + // // std::cout << "cov1 = " << std::endl; cov1.Print(); + // ------------------------------------------------------------------------------------------------------------------------------- + + // finally update CaloHypo::position()->covariance() + covariance(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::X) = c1[0]; // cov1(0,0); + covariance(LHCb::CaloPosition::Index::Y, LHCb::CaloPosition::Index::Y) = c1[2]; // cov1(1,1); + covariance(LHCb::CaloPosition::Index::E, LHCb::CaloPosition::Index::E) = c1[5]; // cov1(2,2); + covariance(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::Y) = c1[1]; // cov1(0,1); + covariance(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::E) = c1[3]; // cov1(0,2); + covariance(LHCb::CaloPosition::Index::Y, LHCb::CaloPosition::Index::E) = c1[4]; // cov1(1,2); + + // // paranoic test (should be always ok since Covariance is SMatrix<3,3,double> with internal representation as double array[5]) + // assert( covariance(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::Y) == covariance(LHCb::CaloPosition::Index::Y, LHCb::CaloPosition::Index::X)); + // assert( covariance(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::E) == covariance(LHCb::CaloPosition::Index::E, LHCb::CaloPosition::Index::X)); + // assert( covariance(LHCb::CaloPosition::Index::Y, LHCb::CaloPosition::Index::E) == covariance(LHCb::CaloPosition::Index::E, LHCb::CaloPosition::Index::Y)); + + if ( UNLIKELY(msgLevel( MSG::DEBUG)) ) { + debug() << "after E-corr. cov.m. = \n" << covariance << endmsg; + } + } + + return StatusCode::SUCCESS ; +} + + +double CaloFutureECorrection::calcECorrection( double xBar, double yBar, double eEcal, double ePrs, + const struct CaloFutureECorrection::ECorrInputParams& _params, + CaloFutureECorrection::ECorrOutputParams* _results ) const +{ + // local aliases for the input variables passed from process() to calcECorrection() + const LHCb::CaloCellID& cellID = _params.cellID; + const Gaudi::XYZPoint& seedPos = _params.seedPos; + const double& eSpd = _params.eSpd; + const double& dtheta = _params.dtheta; + const unsigned int& area = _params.area; + + const int ShiftCol[3] = { 0 , 0 , 8 }; + const int ShiftRow[3] = { 6 , 12 , 14 }; + + double CellSize = m_det->cellSize( cellID ); + double Asx = ( xBar - seedPos.x() ) / CellSize ; // Asx0 + double Asy = ( yBar - seedPos.y() ) / CellSize ; // Asy0 + + const double Asx0 = Asx; + const double Asy0 = Asy; + + unsigned int Col = cellID.col() - ShiftCol[area] + 1; + unsigned int Row = cellID.row() - ShiftRow[area] + 1; + + + double bDist = sqrt( Asx * Asx + Asy * Asy) * sqrt ( 2. ) ; + + // leakage induced by Ecal module frame + double signX = 0; + if ( 1 == Col % (area + 1) ) { + signX = +1.; + } + if ( 0 == Col % (area + 1) ) { + signX = -1.; + } + double signY = 0; + if ( 1 == Row % (area + 1) ) { + signY = +1.; + } + if ( 0 == Row % (area + 1) ) { + signY = -1.; + } + Asx *= signX; // Asx1 + Asy *= signY; // Asy1 + + + // analytic derivatives of the correction functions + double DaE(0), DaB(0), DaX(0), DaY(0), Dbeta(0), DbetaPR(0), DbetaC(0), DbetaCPR(0); + + // + // apply corrections + // NB: numeric derivative calculation calls and printouts which are commented-out below + // are useful for debugging in case of changes in the correction function code + // + //// aG = const(X,Y,E), no need to calculate derivatives + double aG = getCorrection(CaloFutureCorrection::alphaG , cellID ); // global Ecal factor + + //// aE = alphaE(eEcal) + double aE = getCorrection(CaloFutureCorrection::alphaE , cellID , eEcal ); // longitudinal leakage + if ( m_correctCovariance ) { + if ( _results ) DaE = getCorrectionDerivative(CaloFutureCorrection::alphaE , cellID , eEcal ); + // double dn_aE = (getCorrection(CaloFutureCorrection::alphaE , cellID , eEcal*1.02 )-aE)/eEcal/2.e-2; + // std::cout << " alphaE: eEcal = " << eEcal << " aE = " << aE << " DaE = " << DaE + // << " numeric d(aE)/d(eEcal) = dn_aE = " << dn_aE << std::endl; + } + + //// aB = alphaB(bDist) + double aB = getCorrection(CaloFutureCorrection::alphaB , cellID , bDist ); // lateral leakage + if ( m_correctCovariance ) { + if ( _results ) DaB = getCorrectionDerivative(CaloFutureCorrection::alphaB , cellID , bDist ); + // double tmpd = ( bDist > 1e-5 ) ? bDist*2.e-2 : 2.e-7; + // double dn_aB = (getCorrection(CaloFutureCorrection::alphaB , cellID , bDist + tmpd )-aB)/tmpd; + // std::cout << "\t alphaB: bDist = " << bDist << " aB = " << aB << " DaB = " << DaB + // << " numeric d(aB)/d(bDist) = dn_aB = " << dn_aB << std::endl; + } + + //// aX = alphaX(Asx1) + double aX = getCorrection(CaloFutureCorrection::alphaX , cellID , Asx ); // module frame dead material X-direction + if ( m_correctCovariance ) { + if ( _results ) DaX = getCorrectionDerivative(CaloFutureCorrection::alphaX , cellID , Asx ); + // double tmpd = ( fabs(Asx) > 1e-5 ) ? Asx*2.e-2 : 2.e-7; + // double dn_aX = (getCorrection(CaloFutureCorrection::alphaX , cellID , Asx + tmpd ) -aX)/ tmpd; + // std::cout << "\t alphaX Asx = " << Asx << " aX = " << aX << " DaX = " << DaX + // << " numeric d(aX)/d(Asx1) = dn_aX = " << dn_aX << std::endl; + } + + //// aY = alphaY(Asy1) + double aY = getCorrection(CaloFutureCorrection::alphaY , cellID , Asy ); // module frame dead material Y-direction + if ( m_correctCovariance ) { + if ( _results ) DaY = getCorrectionDerivative(CaloFutureCorrection::alphaY , cellID , Asy ); + // double tmpd = ( fabs(Asy) > 1e-5 ) ? Asy*2.e-2 : 2.e-7; + // double dn_aY = (getCorrection(CaloFutureCorrection::alphaY , cellID , Asy + tmpd ) -aY)/ tmpd; + // std::cout << "\t alphaY: Asy = " << Asy << " aY = " << aY << " DaY = " << DaY + // << " numeric d(aY)/d(Asy1) = dn_aY = " << dn_aY << std::endl; + } + + //// alphaP(ePrs) = const(X,Y,E), no need to calculate derivatives + //// unless a full 4D cov.m.(X,Y,E,ePrs) is used including sigma(ePrs) and ePrs correlations with X,Y,E + double aP = getCorrection(CaloFutureCorrection::alphaP , cellID , ePrs ); // Prs deposit dependency + + + // Prs correction + double ratio = (eEcal > 0 ) ? ePrs / eEcal : 0. ; + //// beta0 = beta(eEcal) + double beta = getCorrection(CaloFutureCorrection::beta , cellID , eEcal , 0. ); // eEcal dependency if any + if ( m_correctCovariance ) { + if ( _results ) Dbeta = getCorrectionDerivative(CaloFutureCorrection::beta , cellID , eEcal , 0 ); + // double dn_beta = (getCorrection(CaloFutureCorrection::beta , cellID , eEcal*1.02 , 0. )-beta)/eEcal/2.e-2; + // std::cout << "\t beta: eEcal = " << eEcal << " beta = " << beta << " Dbeta = " << Dbeta + // << " numeric d(beta)/d(eEcal) = dn_beta = " << dn_beta << std::endl; + } + + double betaP = getCorrection(CaloFutureCorrection::betaP , cellID , ePrs , 0. ); // add Eprs dependency if any + beta += betaP; // beta1 + //// betaPR(ratio = ePrs/eEcal) + double betaPR = getCorrection(CaloFutureCorrection::betaPR , cellID , ratio , 0. ); // add ePrs/eEcal dependency if any + if ( m_correctCovariance ) { + if ( _results ) DbetaPR = getCorrectionDerivative(CaloFutureCorrection::betaPR , cellID , ratio , 0. ); + } + beta += betaPR; // beta2 + + + // angular correction + // assume dtheta to be independent of X,Y,E, although it may still be implicitly a bit dependent on X,Y + double gT = getCorrection(CaloFutureCorrection::globalT , cellID , dtheta ); // incidence angle (delta) + double dT = getCorrection(CaloFutureCorrection::offsetT , cellID , dtheta , 0. ); // incidence angle (delta) + + + // Energy offset + double sinT = m_det->cellSine( cellID ); + double offset = ( eSpd == 0) ? + getCorrection(CaloFutureCorrection::offset, cellID , sinT , 0.) : + getCorrection(CaloFutureCorrection::offsetC, cellID , sinT , 0.) ; + + // - dedicate correction for 'converted photon' + double gC = 1.; + bool betaC_flag = false; + if ( eSpd > 0) { + gC = getCorrection(CaloFutureCorrection::globalC , cellID ); // global correction factor for converted photons + //// betaC0 = betaC(eEcal) + double betaC = getCorrection(CaloFutureCorrection::betaC , cellID , eEcal , 0. ); + if ( m_correctCovariance ) { + if ( _results ) DbetaC = getCorrectionDerivative(CaloFutureCorrection::betaC , cellID , eEcal , 0. ); + } + + //// betaCP = betaCP(ePrs) = const(X,Y,E) => no need to calculate derivaties unless 4D cov.m.(X,Y,E,ePrs) is used + double betaCP = getCorrection(CaloFutureCorrection::betaCP , cellID , ePrs , 0. ); + betaC += betaCP; // betaC1 + + //// betaCPR(ratio = ePrs/eEcal) + double betaCPR = getCorrection(CaloFutureCorrection::betaCPR , cellID , ratio , 0. ); + if ( m_correctCovariance ) { + if ( _results ) DbetaCPR = getCorrectionDerivative(CaloFutureCorrection::betaCPR , cellID , ratio , 0. ); + } + betaC += betaCPR; // betaC2 + + if ( betaC != 0.) { + beta = betaC; + betaC_flag = true; + } + } + + + + // Apply Ecal leakage corrections + double alpha = aG * aE * aB * aX * aY * aP; + double eCor = ( alpha * eEcal + beta * ePrs ) * gC * gT + dT + offset; + + + + /* DG,20140714: derivative calculation + * + * Asx0 = (Xcluster-seedPos.x)/CellSize + * bDist = sqrt(2)*sqrt(Asx0**2+Asy0**2) + * signX = signX(cellID); // const(X,Y,Ecluster) + * Asx1 = signX*Asx0 + * eEcal = Ecluster - pileup_offset(cellID, eSpd); // => d(eEcal)/d(Ecluster) = 1 + * aG = alphaG(cellID); // const(X,Y, Ecluster) + * aE = alphaE(eEcal) + * aB = alphaB(bDist) + * aX = alphaX(Asx1) + * aY = alphaY(Asy1) + * aP = alphaP(ePrs); // const(X,Y, Ecluster) + * ratio = ePrs/eEcal; // if eEcal > 0, otherwise = 0 + * beta0 = beta(eEcal) + * beta1 = beta0 + betaP(ePrs) + * beta2 = beta1 + betaPR(ratio) + * gT = globalT(dtheta); // const(X,Y,Ecluster) although dtheta may indirectly depend on (X,Y) + * dT = offsetT(dtheta); // const(X,Y,Ecluster) + * sinT = cellSince(cellID); // const(X,Y,Ecluster) + * offset= eSpd > 0 ? offsetC(cellID, sinT) : offset(cellID, sinT) + * gC = eSpd > 0 ? globalC(cellID) : 1; // const(X,Y,Ecluster) + * betaC0= betaC(eEcal) + * betaC1= betaC0_betaCP(ePrs) + * betaC2= betaC1+betaCPR(ratio) + * + * betaQ2= betaC_flag ? betaC2 : beta2 + * + * d(Asx0)/dX = +1/CellSize + * d(Asx1)/d(Asx0) = signX + * d(bDist)/d(Asx0) = sqrt(2)*2*Asx0/2/sqrt(Asx0**2+Asy0**2) = 2*Asx0/bDist; // if bDist != 0, otherwise 0 + * if bDist=0 <=> (Asx=0,Asy=0), but for any Asy!=0 (if Asx=0 => d(bDist)/d(Asx) = 0) + * => for continuity similarly define the same for Asy=0, i.e. if bDist=0 => d(bDist)/d(Asx) = 0 + * + * d(aB)/dX = d(aB)/d(bDist)*d(bDist)/d(Asx0)*d(Asx0)/dX = DalphpaB*(2*Asx0/bDist)*(1/CellSize) + * d(aX)/dX = d(aX)/d(Asx1)*d(Asx1)/d(Asx0)*d(Asx0)/dX = DalphaX*signX*(1/CellSize) + * d(eEcal)/d(Ecluster) = 1 + * d(ratio)/d(eEcal) = - ePrs/eEcal**2 = - ratio / eEcal; // if eEcal > 0, otherwise = 0 + * + * betaQ = betaC_flag ? betaC : beta + * d(betaQ2)/dE = d( betaQ(eEcal) + betaQP(ePrs) + betaQPR(ratio) )/d(eEcal) = DbetaQ + 0 + DbetaQ*d(ratio)/dE = + * = DbetaQ - DbetaQPR*ePrs/eEcal**2 = DbetaQ - DbetaQPR*ratio/eEcal + * + * alpha = aG * aE(eEcal) * aB(bDist) * aX(Asx1) * aY(Asy1) * aP(ePrs); + * Ehypo = eCor = ( alpha(eEcal, bDist, Asx1, Asy1) * eEcal + beta2(eEcal, ratio, ePrs) * ePrs ) * gC * gT + dT + offset; + * + * d(alpha)/d(eEcal) = (aG*aB*aX*aY*aP) * d(aE)/d(eEcal) = (alpha/aE) * DalphaE; // if aE!=0, otherwise aG*aB*aX*aY*aP*DalphaE + * + * + * d(Ehypo)/d(Ecluster) = gC*gT*(eEcal*d(alpha)/d(eEcal) + alpha + ePrs*d(beta2)/d(eEcal)) + * = gC * gT * ( ePrs * DbetaQ2 + alpha * (1. + DaE / aE * eEcal) ) + * d(Ehypo)/d(Xcluster) = gC*gT*eEcal*d(alpha)/dX = gC*gT*eEcal*aG*aE*aY*aP*(d(aB)/dX*aX+d(aX)/dX*aB) + * = gC * gT * eEcal * aG * aE * aY * aP * (DaB*2.*Asx0/bDist*aX + signX*aB*DaX)/CellSize + * d(Ehypo)/d(Ycluster) = [ same as for d(Ehypo)/d(Xcluster) with ( X <-> Y ) ] + * = gC * gT * eEcal * aG * aE * aX * aP * (DaB*2.*Asy0/bDist*aY + signY*aB*DaY)/CellSize + */ + + if ( _results != NULL ) { + if ( m_correctCovariance ) { + double DbetaQ2 = betaC_flag ? ( DbetaC - (eEcal > 0 ? DbetaCPR * ratio / eEcal : 0) ) + : ( Dbeta - (eEcal > 0 ? DbetaPR * ratio / eEcal : 0) ); + double d_alpha_dE = (aE != 0) ? DaE * alpha / aE : DaE * aG * aB * aX * aY * aP; // though in principle, aE should never be 0 + + _results->dEcor_dEcl = gC * gT * ( ePrs * DbetaQ2 + alpha + d_alpha_dE * eEcal ); + _results->dEcor_dXcl = gC * gT * eEcal * aG * aE * aY * aP * ((bDist == 0 ? 0. : DaB * 2.*Asx0 / bDist * aX) + signX * aB * DaX) / CellSize; + _results->dEcor_dYcl = gC * gT * eEcal * aG * aE * aX * aP * ((bDist == 0 ? 0. : DaB * 2.*Asy0 / bDist * aY) + signY * aB * DaY) / CellSize; + + _results->betaC_flag = betaC_flag; + } + + _results->beta = beta; // betaQ2 + _results->alpha = alpha; + + // intermediate variables calculated by calcECorrection() needed for debug printout inside process() + if ( UNLIKELY(msgLevel( MSG::DEBUG)) ) { + _results->Asx = Asx; // Asx1 + _results->Asy = Asy; // Asy1 + _results->aG = aG; + _results->aE = aE; + _results->aB = aB; + _results->aX = aX; + _results->aY = aY; + _results->gC = gC; + _results->gT = gT; + } + } + + return eCor; +} diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureECorrection.h b/CaloFuture/CaloFutureReco/src/CaloFutureECorrection.h new file mode 100644 index 0000000000000000000000000000000000000000..e2cd400744e30e10beed27747468b4c95c036e38 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureECorrection.h @@ -0,0 +1,106 @@ +#ifndef CALOFUTURERECO_CALOFUTUREECORRECTION_H +#define CALOFUTURERECO_CALOFUTUREECORRECTION_H 1 +// Include files +#include <string> +#include <map> +#include "CaloFutureInterfaces/ICaloFutureHypoTool.h" +#include "CaloFutureCorrectionBase.h" +#include "GaudiKernel/Counters.h" + +/** @namespace CaloFutureECorrection_Local + */ + + +/** @class CaloFutureECorrection CaloFutureECorrection.h + * + * + * @author Deschamps Olivier + + * @date 2003-03-10 + */ +class CaloFutureECorrection : + public virtual ICaloFutureHypoTool, + public CaloFutureCorrectionBase +{ + +public: + + StatusCode process ( LHCb::CaloHypo* hypo ) const override; + StatusCode operator() ( LHCb::CaloHypo* hypo ) const override; + +public: + + StatusCode initialize() override; + StatusCode finalize() override; + + CaloFutureECorrection ( const std::string& type , + const std::string& name , + const IInterface* parent ) ; + +private: + Gaudi::Property<int> m_pFilt {this, "PrsFilter", 0x3, "1 : noPrs ; 2 : Prs ; 3: both"}; + Gaudi::Property<int> m_sFilt {this, "SpdFilter", 0x3, "1 : noSpd ; 2 : Spd ; 3: both"}; + + /// input variables calculated once in process() and passed to all calcECorrection() calls + struct ECorrInputParams { + LHCb::CaloCellID cellID; + Gaudi::XYZPoint seedPos; + double eSpd; + double dtheta; + unsigned int area; + }; + + /// Jacobian elements and intermediate variables sometimes returned from calcECorrection() to process() + class ECorrOutputParams + { + public: + ECorrOutputParams() : dEcor_dXcl(0), dEcor_dYcl(0), dEcor_dEcl(0), + alpha(0), beta(0), Asx(0), Asy(0), aG(0), aE(0), aB(0), aX(0), aY(0), gC(0), gT(0), betaC_flag(false) {} + + // output Jacobian elements returned from calcECorrection() to process() + double dEcor_dXcl; + double dEcor_dYcl; + double dEcor_dEcl; + + // intermediate variables calculated by calcECorrection() needed for debug printout inside process() + double alpha; + double beta; + double Asx; + double Asy; + double aG; + double aE; + double aB; + double aX; + double aY; + double gC; + double gT; + + bool betaC_flag; + }; + + /// calculate corrected CaloHypo energy depending on CaloCluster position, energy, and Prs energy + double calcECorrection( double xBar, double yBar, double eEcal, double ePrs, + const struct CaloFutureECorrection::ECorrInputParams& _params, + CaloFutureECorrection::ECorrOutputParams* _results ) const; + + using IncCounter = Gaudi::Accumulators::Counter<>; + using SCounter = Gaudi::Accumulators::StatCounter<float>; + + mutable IncCounter m_counterSkippedNegativeEnergyCorrection{this, "Skip negative energy correction"}; + + mutable SCounter m_counterPileupOffset{this, "Pileup offset"}; + mutable SCounter m_counterPileupSubstractedRatio{this, "Pileup subtracted ratio"}; + mutable SCounter m_counterPileupScale{this, "Pileup scale"}; + + mutable IncCounter m_counterUnphysical{this, "Unphysical d(Ehypo)/d(Ecluster)"}; + + mutable SCounter m_counterCorrectedEnergy{this, "Corrected energy"}; + mutable SCounter m_counterDeltaEnergy{this, "Delta(E)"}; + + mutable IncCounter m_counterUnphysicalVariance{this, "Unphysical variance(Ehypo)"}; + + static constexpr int k_numOfCaloFutureAreas{4}; + mutable std::vector<SCounter> m_countersAlpha; + mutable std::vector<SCounter> m_countersBetaTimesEprs; +}; +#endif // CALOFUTURERECO_CALOFUTUREECORRECTION_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureElectronAlg.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureElectronAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..02ac04f8f8467d9e42a3c29523f44ec50fd0ca9e --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureElectronAlg.cpp @@ -0,0 +1,174 @@ +// ============================================================================ +// Include files +// ============================================================================ +// STD & STL +// ============================================================================ +#include <algorithm> +// ============================================================================ +#include "CaloFutureUtils/CaloFutureDataFunctor.h" +#include "Event/CellID.h" +#include "Event/CaloCluster.h" +#include "Event/CaloHypo.h" +#include "CaloFutureInterfaces/ICaloFutureClusterSelector.h" +#include "CaloFutureInterfaces/ICaloFutureHypoTool.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "CaloFutureUtils/CaloMomentum.h" +#include "CaloFutureElectronAlg.h" +// ============================================================================ +/** @file + * + * Implementation file for class : CaloFutureElectronAlg + * The implementation is based on F.Machefert's codes. + * @see CaloFutureElectronAlg + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 31/03/2002 + */ +// ============================================================================ +namespace { + template <typename Container, typename Arg, typename Parent> + bool apply(const Container& c, Arg& arg, const char* errmsg, const Parent& parent) { + bool r = std::all_of( std::begin(c), std::end(c), + [&](typename Container::const_reference elem) + { return (*elem)(&arg).isSuccess(); } ); + if (UNLIKELY(!r)) parent.Error( errmsg, StatusCode::FAILURE ).ignore(); + return r; + } +} +DECLARE_COMPONENT( CaloFutureElectronAlg ) +// ============================================================================ +/* Standard constructor + * @param name algorithm name + * @param pSvc service locator + */ +// ============================================================================ +CaloFutureElectronAlg::CaloFutureElectronAlg +( const std::string& name , + ISvcLocator* pSvcLocator ) + : ScalarTransformer( name, pSvcLocator, + KeyValue("InputData",{}), // note: context can not be used here -- only _after_ the baseclass is initialized! + KeyValue("OutputData",{}) ) + +{ + updateHandleLocation( *this, "InputData", LHCb::CaloFutureAlgUtils::CaloFutureClusterLocation("Ecal", context() )); + updateHandleLocation( *this, "OutputData", LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation("Electrons", context() )); + + + setProperty ( "PropertiesPrint" , true ) ; +} +// ============================================================================ +/* standard Algorithm initialization + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureElectronAlg::initialize() +{ + // initialize the base class + StatusCode sc = ScalarTransformer::initialize(); + if( sc.isFailure() ){ return Error("Could not initialize the base class GaudiAlgorithm!",sc);} + + // check the geometry information + m_det = getDet<DeCalorimeter>( m_detData ) ; + if( !m_det ) { return Error("Detector information is not available!");} + + m_eT = LHCb::CaloDataFunctor::EnergyTransverse<const DeCalorimeter*>{ m_det } ; // TODO: can we combine this into Over_Et_Threshold and make it a property?? + + // locate selector tools + std::transform(m_selectorsTypeNames.begin(), m_selectorsTypeNames.end(), + std::back_inserter( m_selectors ), + [&](const std::string& name) + { return this->tool<ICaloFutureClusterSelector>( name , this ); } ); + if ( m_selectors.empty() )info()<< "No Cluster Selection tools are specified!" <<endmsg ; + // locate correction tools + std::transform( m_correctionsTypeNames.begin(), m_correctionsTypeNames.end(), + std::back_inserter(m_corrections), + [&](const std::string& name) + { return this->tool<ICaloFutureHypoTool>( name , this ); } ); + if ( m_corrections.empty() )info() << "No Hypo Correction(1) tools are specified!" << endmsg ; + // locate other hypo tools + std::transform( m_hypotoolsTypeNames.begin(), m_hypotoolsTypeNames.end(), + std::back_inserter(m_hypotools), + [&](const std::string& name) + { return this->tool<ICaloFutureHypoTool>( name , this ); } ); + if ( m_hypotools.empty() )info() << "No Hypo Processing(1) tools are specified!" << endmsg ; + // locate correction tools + std::transform( m_correctionsTypeNames2.begin(), m_correctionsTypeNames2.end() , + std::back_inserter(m_corrections2), + [&](const std::string& name) + { return this->tool<ICaloFutureHypoTool>( name , this ); } ); + if ( m_corrections2.empty() ) info() << "No Hypo Correction(2) tools are specified!" << endmsg ; + // locate other hypo tools + std::transform( m_hypotoolsTypeNames2.begin(), m_hypotoolsTypeNames2.end(), + std::back_inserter(m_hypotools2), + [&](const std::string& name) + { return this->tool<ICaloFutureHypoTool>( name , this ); } ); + if ( m_hypotools2.empty() )info() << "No Hypo Processing(2) tools are specified!" << endmsg ; + /// + counterStat = tool<IFutureCounterLevel>("FutureCounterLevel"); + return StatusCode::SUCCESS; +} +// ============================================================================ +/* standard Algorithm finalization + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureElectronAlg::finalize() +{ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug()<<"Finalize"<<endmsg; + + // clear containers + m_selectors .clear () ; + m_corrections .clear () ; + m_hypotools .clear () ; + m_corrections2 .clear () ; + m_hypotools2 .clear () ; + m_selectorsTypeNames .clear () ; + m_correctionsTypeNames .clear () ; + m_hypotoolsTypeNames .clear () ; + m_correctionsTypeNames2 .clear () ; + m_hypotoolsTypeNames2 .clear () ; + // finalize the base class + return ScalarTransformer::finalize() ; +} +// ============================================================================ +/* standard Algorithm execution + * @return status code + */ +// ============================================================================ +boost::optional<LHCb::CaloHypo> +CaloFutureElectronAlg::operator()(const LHCb::CaloCluster& cluster) const{ + + // loop over all selectors + bool select = ( m_eT(&cluster) >= m_eTcut && + std::all_of( m_selectors.begin(), m_selectors.end(), + [&](Selectors::const_reference sel) + { return (*sel)(&cluster); } ) ); + if ( !select ) return boost::none; + + // create "Hypo"/"Electron" object + LHCb::CaloHypo hypo; + hypo.setHypothesis( LHCb::CaloHypo::Hypothesis::EmCharged ); + hypo.addToClusters( &cluster ); + hypo.setPosition( std::make_unique<LHCb::CaloPosition>(cluster.position()) ); + + // return boost::none; + return boost::make_optional( + apply( m_corrections, hypo,"Error from Correction Tool, skip the cluster " , *this ) // loop over all corrections and apply corrections + && apply( m_hypotools, hypo, "Error from Other Hypo Tool, skip the cluster " , *this) // loop over other hypo tools (e.g. add extra digits) + && apply( m_corrections2, hypo, "Error from Correction Tool 2 , skip the cluster " , *this) // loop over all corrections and apply corrections + && apply( m_hypotools2, hypo, "Error from Other Hypo Tool 2 , skip the cluster ", *this) // loop over other hypo tools (e.g. add extra digits) + && LHCb::CaloMomentum(&hypo).pt() >= m_eTcut, + hypo); + +} + +void +CaloFutureElectronAlg::postprocess(const LHCb::CaloHypos& hypos) const +{ + if(msgLevel(MSG::DEBUG))debug() << " # of created Electron Hypos is " << hypos.size() << endmsg; // << "/" << clusters->size()<< endmsg ; + if(counterStat->isQuiet()){ + std::string inputData; getProperty("InputData",inputData).ignore(); + counter ( inputData + "=>" + outputLocation() ) += hypos.size() ; + } +} + diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureElectronAlg.h b/CaloFuture/CaloFutureReco/src/CaloFutureElectronAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..82f0a172e96be579ed0b43c8f6690ac7468b8d17 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureElectronAlg.h @@ -0,0 +1,96 @@ +#ifndef CALOFUTURERECO_CALOFUTUREElectronALG_H +#define CALOFUTURERECO_CALOFUTUREElectronALG_H 1 +// Include files +// from STL +#include <string> +// from GaudiAlg +#include "GaudiAlg/ScalarTransformer.h" +#include "CaloDet/DeCalorimeter.h" +#include "Event/CaloHypo.h" +#include "Event/CaloCluster.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" + +// forward delcarations +struct ICaloFutureClusterSelector ; +struct ICaloFutureHypoTool ; + +/** @class CaloFutureElectronAlg CaloFutureElectronAlg.h + * + * The simplest algorithm of reconstruction of + * electrons in electromagnetic calorimeter. + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 31/03/2002 + */ +class CaloFutureElectronAlg +: public Gaudi::Functional::ScalarTransformer<CaloFutureElectronAlg,LHCb::CaloHypos(const LHCb::CaloClusters&)> +{ + public: + + CaloFutureElectronAlg(const std::string& name, ISvcLocator* pSvcLocator ); + + + + StatusCode initialize() override; + StatusCode finalize() override; + + using ScalarTransformer::operator(); + boost::optional<LHCb::CaloHypo> operator()(const LHCb::CaloCluster& ) const; + void postprocess(const LHCb::CaloHypos&) const; +private: + + /// container of names + typedef std::vector<std::string> Names ; + /// container of selector tools + typedef std::vector<ICaloFutureClusterSelector*> Selectors ; + /// containers of hypo tools + typedef std::vector<ICaloFutureHypoTool*> HypoTools ; + /// container of correction tools (S-,L-,...) + typedef HypoTools Corrections ; + + + // cluster selectors + Selectors m_selectors; + Gaudi::Property<Names> m_selectorsTypeNames {this, "SelectionTools", { + "CaloFutureSelectCluster/ElectronCluster", + "CaloFutureSelectChargedClusterWithSpd/ChargedWithSpd", + "CaloFutureSelectClusterWithPrs/ClusterWithPrs", + "CaloFutureSelectorNOT/ChargedWithTracks" + }, "List of Cluster selector tools"}; + + // corrections + Corrections m_corrections; + Gaudi::Property<Names> m_correctionsTypeNames + {this, "CorrectionTools", {}, "List of primary correction tools"}; + + // other hypo tools + HypoTools m_hypotools; + Gaudi::Property<Names> m_hypotoolsTypeNames + {this, "HypoTools", {"CaloFutureExraDigits/SpdPrsExtraE"}, + "List of generic Hypo-tools to apply for newly created hypos"}; + + // corrections + Corrections m_corrections2; + Gaudi::Property<Names> m_correctionsTypeNames2 {this, "CorrectionTools2", { + "CaloECorrection/ECorrection" , + "CaloSCorrection/SCorrection" , + "CaloLCorrection/LCorrection" + }, "List of tools for 'fine-corrections"}; + + // other hypo tools + HypoTools m_hypotools2; + Gaudi::Property<Names> m_hypotoolsTypeNames2 + {this, "HypoTools2", {}, + "List of generi Hypo-tools to apply for corrected hypos"}; + + Gaudi::Property<std::string> m_detData {this, "Detector", LHCb::CaloFutureAlgUtils::DeCaloFutureLocation("Ecal") }; + const DeCalorimeter* m_det = nullptr; + Gaudi::Property<float> m_eTcut {this, "EtCut", 0, "Threshold on cluster & hypo ET"}; + IFutureCounterLevel* counterStat = nullptr; + + LHCb::CaloDataFunctor::EnergyTransverse<const DeCalorimeter*> m_eT { nullptr } ; // TODO: can we combine this into Over_Et_Threshold and make it a property?? + +}; + +// ============================================================================ +#endif // CALOFUTUREElectronALG_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureExtraDigits.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureExtraDigits.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4df502fc8d8d70ea0f244031bcb39c849b2fda6e --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureExtraDigits.cpp @@ -0,0 +1,94 @@ +// ============================================================================ +// Include files +// ============================================================================ +// STL +// ============================================================================ +#include <cmath> +#include <algorithm> +// ============================================================================ +// from Gaudi +// ============================================================================ +#include "GaudiKernel/SmartRef.h" +// ============================================================================ +// local +// ============================================================================ +#include "CaloFutureExtraDigits.h" +// ============================================================================ +/** @file CaloFutureExtraDigits.cpp + * + * Implementation file for class : CaloFutureExtraDigits + * @see CaloFutureExtraDigits + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 01/04/2002 + */ +// ============================================================================ +DECLARE_COMPONENT( CaloFutureExtraDigits ) +// ============================================================================ +CaloFutureExtraDigits::CaloFutureExtraDigits +( const std::string& type , + const std::string& name , + const IInterface* parent ) + : GaudiTool ( type, name , parent ) +{ + // + declareInterface<ICaloFutureHypoTool> (this); + // + if ( std::string::npos != name.find ( "Prs" ) ) + { m_toDet.value().push_back ( "Prs" ) ; } + if ( std::string::npos != name.find ( "Spd" ) ) + { m_toDet.value().push_back ( "Spd" ) ; } + if ( std::string::npos != name.find ( "Hcal" ) ) + { m_toDet.value().push_back ( "Hcal" ) ; } + if ( std::string::npos != name.find ( "Ecal" ) ) + { m_toDet.value().push_back ( "Ecal" ) ; } +} +// ============================================================================ +StatusCode CaloFutureExtraDigits::initialize () +{ + // initilaize the base class + StatusCode sc = GaudiTool::initialize (); + if( sc.isFailure() ) + { return Error ( "Could not initialize the base class GaudiTool!", sc ) ; } + // + if ( m_toDet.empty() ) + { return Error ( "List of 'ExtraDigitsFrom' is empty!" ) ; } + // + for ( std::vector<std::string>::iterator idet = m_toDet.begin(); + idet!=m_toDet.end();idet++) + { + m_toCaloFuture[*idet]=tool<ICaloFutureHypo2CaloFuture>("CaloFutureHypo2CaloFuture", "CaloFutureHypo2" + *idet , this ); + m_toCaloFuture[*idet]->setCalos(m_det,*idet); + } + // + counterStat = tool<IFutureCounterLevel>("FutureCounterLevel"); + return StatusCode::SUCCESS ; +} +// ============================================================================ +StatusCode CaloFutureExtraDigits::process ( LHCb::CaloHypo* hypo ) const +{ return (*this) ( hypo ); } +// ============================================================================ +StatusCode CaloFutureExtraDigits::operator() ( LHCb::CaloHypo* hypo ) const +{ + if ( 0 == hypo ) { return Error("CaloHypo* points to NULL!" , StatusCode{200} ) ; } + // + for ( std::map<std::string,ICaloFutureHypo2CaloFuture*>::const_iterator + idet = m_toCaloFuture.begin(); idet!=m_toCaloFuture.end();idet++) + { + ICaloFutureHypo2CaloFuture* tool = idet->second ; + const std::string& toCaloFuture = idet->first ; + unsigned int count = 0 ; + const std::vector<LHCb::CaloDigit*>& digits = tool->digits ( *hypo, toCaloFuture ); + for ( std::vector<LHCb::CaloDigit*>::const_iterator id = digits.begin() ; + id != digits.end(); id++) + { + hypo->addToDigits( *id ); + ++count; + } + // + if (UNLIKELY( msgLevel(MSG::DEBUG) ) )debug() << "Adding " << count << " digits from "<< *idet << endmsg; + // + if(counterStat->isVerbose() )counter ( toCaloFuture ) += count ; + } + return StatusCode::SUCCESS ; +} diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureExtraDigits.h b/CaloFuture/CaloFutureReco/src/CaloFutureExtraDigits.h new file mode 100644 index 0000000000000000000000000000000000000000..1f125b169a354e667a3270680e4ed093e82e28cf --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureExtraDigits.h @@ -0,0 +1,39 @@ +#ifndef CALOFUTURERECO_CALOFUTUREEXTRADIGITS_H +#define CALOFUTURERECO_CALOFUTUREEXTRADIGITS_H 1 +// Include files +// from STL +#include <string> +// Kernel +#include "GaudiAlg/GaudiTool.h" +#include "CaloFutureInterfaces/ICaloFutureHypoTool.h" +#include "CaloFutureInterfaces/ICaloFutureHypo2CaloFuture.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" + +/** @class CaloFutureExtraDigits CaloFutureExtraDigits.h + * + * + * @author Vanya Belyaev Ivan Belyaev + * @date 31/03/2002 + */ +class CaloFutureExtraDigits : + public virtual ICaloFutureHypoTool , + public GaudiTool +{ +public: + + StatusCode initialize() override; + StatusCode process ( LHCb::CaloHypo* hypo ) const override; + StatusCode operator() ( LHCb::CaloHypo* hypo ) const override; + + CaloFutureExtraDigits( const std::string& type, + const std::string& name, + const IInterface* parent); + +private: + + Gaudi::Property<std::vector<std::string>> m_toDet {this, "ExtraDigitFrom"}; + std::map<std::string,ICaloFutureHypo2CaloFuture*> m_toCaloFuture; + Gaudi::Property<std::string> m_det {this, "Detector", "Ecal"}; + IFutureCounterLevel* counterStat = nullptr; +}; +#endif // CALOFUTUREEXTRADIGITS_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureGetterInit.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureGetterInit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b90bc72fe43d663f6579697b557115505e559578 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureGetterInit.cpp @@ -0,0 +1,52 @@ +// Include files + +// local +#include "CaloFutureGetterInit.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : CaloFutureGetterInit +// +// 2009-04-17 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( CaloFutureGetterInit ) + +//============================================================================= +// Initialization +//============================================================================= +StatusCode CaloFutureGetterInit::initialize() { + StatusCode sc = GaudiAlgorithm::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; // error printed already by GaudiAlgorithm + + if ( UNLIKELY(msgLevel(MSG::DEBUG) ) ) debug() << "==> Initialize" << endmsg; + + + m_getter = tool<ICaloFutureGetterTool>("CaloFutureGetterTool", m_name ); + + return StatusCode::SUCCESS; +} + +//============================================================================= +// Main execution +//============================================================================= +StatusCode CaloFutureGetterInit::execute() { + + if ( UNLIKELY(msgLevel(MSG::DEBUG) ) ) debug() << "==> Execute" << endmsg; + + m_getter->update(); + + return StatusCode::SUCCESS; +} + +//============================================================================= +// Finalize +//============================================================================= +StatusCode CaloFutureGetterInit::finalize() { + + if ( UNLIKELY(msgLevel(MSG::DEBUG) ) ) debug() << "==> Finalize" << endmsg; + + return GaudiAlgorithm::finalize(); // must be called after all other actions +} + +//============================================================================= diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureGetterInit.h b/CaloFuture/CaloFutureReco/src/CaloFutureGetterInit.h new file mode 100644 index 0000000000000000000000000000000000000000..17ab66493e1abd08f2790e1be72645b0a0f35c57 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureGetterInit.h @@ -0,0 +1,30 @@ +// $Id: CaloFutureGetterInit.h,v 1.1 2009-04-17 11:44:53 odescham Exp $ +#ifndef CALOFUTUREGETTERINIT_H +#define CALOFUTUREGETTERINIT_H 1 + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiAlgorithm.h" +//from LHCb +#include "CaloFutureInterfaces/ICaloFutureGetterTool.h" + +/** @class CaloFutureGetterInit CaloFutureGetterInit.h + * + * + * @author Olivier Deschamps + * @date 2009-04-17 + */ +class CaloFutureGetterInit : public GaudiAlgorithm { +public: + /// Standard constructor + using GaudiAlgorithm::GaudiAlgorithm; + + StatusCode initialize() override; ///< Algorithm initialization + StatusCode execute() override; ///< Algorithm execution + StatusCode finalize() override; ///< Algorithm finalization + +private: + ICaloFutureGetterTool* m_getter = nullptr; + Gaudi::Property<std::string> m_name {this, "ToolName", "CaloFutureGetter"}; +}; +#endif // CALOFUTUREGETTERINIT_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureHypoAlg.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureHypoAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d38328cd979de45aaf8947ad5d531a9d9e15a134 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureHypoAlg.cpp @@ -0,0 +1,126 @@ +// ============================================================================ +// Include files +// ============================================================================ +// STD & STL +// ============================================================================ +#include <algorithm> +// ============================================================================ +// CaloFutureInterfaces +// ============================================================================ +#include "CaloFutureInterfaces/ICaloFutureHypoTool.h" +// ============================================================================ +// CaloFutureEvent/Event +// ============================================================================ +#include "Event/CaloHypo.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +// ============================================================================ +// local +// ============================================================================ +#include "CaloFutureHypoAlg.h" +// ============================================================================ +/** @file CaloFutureHypoAlg.cpp + * + * Template implementation file for class : CaloFutureHypoAlg + * @see CaloFutureHypoAlg + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 02/09/2002 + */ +// ============================================================================ +DECLARE_COMPONENT( CaloFutureHypoAlg ) +// ============================================================================ +/* Standard constructor + * @param name algorithm name + * @param svcloc pointer to service locator + */ +// ============================================================================ +CaloFutureHypoAlg::CaloFutureHypoAlg +( const std::string& name , + ISvcLocator* svcloc ) + : GaudiAlgorithm ( name , svcloc ) +{ + setProperty ( "PropertiesPrint" , true ) ; +} +// ============================================================================ +/* standard algorithm initialization + * @see CaloFutureAlgorithm + * @see Algorithm + * @see IAlgorithm + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureHypoAlg::initialize() +{ + StatusCode sc = GaudiAlgorithm::initialize(); + if( sc.isFailure() ) + { return Error("Could not initialize the base class CaloFutureAlgorithm",sc);} + + // apply default context-dependent TES location (if not defined) + if( m_inputData.empty() && !m_type.empty() )m_inputData = LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation( m_type , context() ); + + + if ( m_inputData.empty() ) + { return Error ( "Empty 'InptuData'" ) ; } + // + for( Names::const_iterator it = m_names.begin() ; + m_names.end() != it ; ++it ) + { + ICaloFutureHypoTool* t = tool<ICaloFutureHypoTool>( *it , this ) ; + if( 0 == t ) { return Error("Could not locate the tool!"); } + m_tools.push_back( t ); + } + // + if ( m_tools.empty() ) { Warning ( "Empty list of tools").ignore() ; } + // + counterStat = tool<IFutureCounterLevel>("FutureCounterLevel"); + return StatusCode::SUCCESS; +} +// ============================================================================ +/* standard algorithm finalization + * @see CaloFutureAlgorithm + * @see Algorithm + * @see IAlgorithm + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureHypoAlg::finalize() +{ + // clear the container + m_tools.clear(); + /// finalize the base class + return GaudiAlgorithm::finalize(); +} +// ============================================================================ +/* standard algorithm execution + * @see CaloFutureAlgorithm + * @see Algorithm + * @see IAlgorithm + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureHypoAlg::execute() +{ + // avoid long name and types + typedef LHCb::CaloHypos Hypos; + + Hypos* hypos = get<Hypos>( m_inputData ) ; + if( 0 == hypos ) { return StatusCode::FAILURE ; } + + for( Hypos::const_iterator hypo = hypos->begin() ; + hypos->end() != hypo ; ++hypo ) + { + // skip NUULS + if( 0 == *hypo ) { continue ; } + // loop over all tools + StatusCode sc = StatusCode::SUCCESS ; + for( Tools::const_iterator itool = m_tools.begin() ; + m_tools.end() != itool && sc.isSuccess() ; ++itool ) + { sc = (**itool)( *hypo ); } + if( sc.isFailure() ) + { Error("Error from the Tool! skip hypo!",sc).ignore() ; continue ; } + } + + if(counterStat->isQuiet())counter ( "#Hypos from '" + m_inputData +"'") += hypos->size() ; + // + return StatusCode::SUCCESS ; +} diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureHypoAlg.h b/CaloFuture/CaloFutureReco/src/CaloFutureHypoAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..961af08c759fdba46a5092ba97b309ccf4998f2a --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureHypoAlg.h @@ -0,0 +1,79 @@ +#ifndef CaloFutureReco_CaloFutureHypoAlg_H +#define CaloFutureReco_CaloFutureHypoAlg_H 1 +// Include files +// from STL +#include <string> +#include <vector> + +#include "CaloFutureInterfaces/IFutureCounterLevel.h" +#include "GaudiAlg/GaudiAlgorithm.h" +// forward declaration +struct ICaloFutureHypoTool ; + +/** @class CaloFutureHypoAlg CaloFutureHypoAlg.h + * + * Generic CaloFutureHypo Algorithm. + * It is just applies a set of ICaloFutureHypoTools + * to a container of CaloFutureHypo objects + * @see ICaloFutureHypoTool + * @see CaloFutureHypo + * @see CaloFutureAlgorithm + * @see Algorithm + * @see IAlgorithm + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 02/09/2002 + */ + +class CaloFutureHypoAlg : public GaudiAlgorithm +{ +public: + + /** standard algorithm initialization + * @see CaloFutureAlgorithm + * @see Algorithm + * @see IAlgorithm + * @return status code + */ + StatusCode initialize() override; + + /** standard algorithm execution + * @see CaloFutureAlgorithm + * @see Algorithm + * @see IAlgorithm + * @return status code + */ + StatusCode execute() override; + + /** standard algorithm finalization + * @see CaloFutureAlgorithm + * @see Algorithm + * @see IAlgorithm + * @return status code + */ + StatusCode finalize() override; + + /** Standard constructor + * @param name algorithm name + * @param svcloc pointer to service locator + */ + CaloFutureHypoAlg( const std::string& name , + ISvcLocator* svcloc ); + +private: + + typedef std::vector<std::string> Names ; + typedef std::vector<ICaloFutureHypoTool*> Tools ; + + /// list of tool type/names + Gaudi::Property<Names> m_names + {this, "Tools", {}, "The list of generic Hypo-tools to be applied"}; + + /// list of tools + Tools m_tools ; + Gaudi::Property<std::string> m_inputData {this, "InputData"}; + Gaudi::Property<std::string> m_type {this, "HypoType"}; + IFutureCounterLevel* counterStat = nullptr; +}; +// ============================================================================ +#endif // CaloFutureHypoAlg_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureLCorrection.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureLCorrection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d8086176dc0aca5da5571778506e4975291abc1a --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureLCorrection.cpp @@ -0,0 +1,232 @@ +// ============================================================================ +// Include files +#include "CaloFutureLCorrection.h" + +/** @file + * Implementation file for class : CaloFutureLCorrection + * + * @date 2003-03-10 + * @author Xxxx XXXXX xxx@xxx.com + */ + +DECLARE_COMPONENT( CaloFutureLCorrection ) + +// ============================================================================ +/** Standard constructor + * @see GaudiTool + * @see AlgTool + * @param type tool type (?) + * @param name tool name + * @param parent tool parent + */ +// ============================================================================ +CaloFutureLCorrection::CaloFutureLCorrection +( const std::string& type , + const std::string& name , + const IInterface* parent ) + : CaloFutureCorrectionBase( type , name , parent ) +{ + + // define conditionName + const std::string uName ( LHCb::CaloFutureAlgUtils::toUpper( name ) ) ; + if ( uName.find( "ELECTRON" ) != std::string::npos ) { + m_conditionName = "Conditions/Reco/Calo/ElectronLCorrection"; + } else if ( uName.find( "MERGED" ) != std::string::npos || uName.find( "SPLITPHOTON" ) != std::string::npos ) { + m_conditionName = "Conditions/Reco/Calo/SplitPhotonLCorrection"; + } else if ( uName.find( "PHOTON" ) ) { + m_conditionName = "Conditions/Reco/Calo/PhotonLCorrection"; + } + + /// interafces + declareInterface<ICaloFutureHypoTool> ( this ) ; + + m_counterPerCaloFutureAreaDeltaZ.reserve(k_numOfCaloFutureAreas); + m_counterPerCaloFutureAreaGamma.reserve(k_numOfCaloFutureAreas); + m_counterPerCaloFutureAreaDelta.reserve(k_numOfCaloFutureAreas); + std::vector<std::string> caloAreas = {"Outer" , "Middle" , "Inner" , "PinArea"}; + for (auto i = 0; i < k_numOfCaloFutureAreas; i++) { + m_counterPerCaloFutureAreaDeltaZ.emplace_back(this, "Delta(Z) " + caloAreas[i]); + m_counterPerCaloFutureAreaGamma.emplace_back(this, "<gamma> " + caloAreas[i]); + m_counterPerCaloFutureAreaDelta.emplace_back(this, "<delta> " + caloAreas[i]); + } +} + +// ============================================================================ +StatusCode CaloFutureLCorrection::finalize () +{ + m_hypos.clear(); + return CaloFutureCorrectionBase::finalize () ; +} +// ============================================================================ +StatusCode CaloFutureLCorrection::initialize () +{ + /// first initialize the base class + StatusCode sc = CaloFutureCorrectionBase::initialize(); + if ( sc.isFailure() ) { + return Error ( "Unable initialize the base class CaloFutureCorrectionBase !" , sc ) ; + } + + if ( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Condition name : " << m_conditionName << endmsg; + + return StatusCode::SUCCESS ; +} + +// ============================================================================ +StatusCode CaloFutureLCorrection::operator() ( LHCb::CaloHypo* hypo ) const +{ + return process( hypo ); +} + +// ============================================================================ +StatusCode CaloFutureLCorrection::process ( LHCb::CaloHypo* hypo ) const +{ + + // check arguments + if ( !hypo ) { + return Warning ( " CaloHypo* points to NULL!" , StatusCode::SUCCESS) ; + } + + // check the Hypo + const auto h = std::find( m_hypos.begin() , m_hypos.end() , hypo->hypothesis() ) ; + if ( m_hypos.end() == h )return Error ( "Invalid hypothesis -> no correction applied", StatusCode::SUCCESS ) ; + + // No correction for negative energy : + if ( hypo->e() < 0.) { + ++m_counterSkipNegativeEnergyCorrection; + return StatusCode::SUCCESS; + } + + + // get Prs/Spd + double ePrs = 0 ; + double eSpd = 0 ; + getPrsSpd(hypo, ePrs, eSpd); + + + // get cluster energy (special case for SplitPhotons) + const LHCb::CaloCluster* GlobalCluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo(hypo, false); + const LHCb::CaloCluster* MainCluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo(hypo, true) ; + + /* + Cluster information (e/x/y and Prs/Spd digit) + */ + if ( !MainCluster ) { + return Error ( "CaloCLuster* points to NULL!" ) ; + } + + // For Split Photon - share the Prs energy + if ( LHCb::CaloHypo::Hypothesis::PhotonFromMergedPi0 == hypo->hypothesis() ) { + ePrs *= MainCluster->position().e() / GlobalCluster->position().e() ; + } + + + const double energy = hypo->e () ; + + const auto& entries = MainCluster->entries(); + const auto iseed = + LHCb::ClusterFunctors::locateDigit ( entries.begin () , entries.end () , LHCb::CaloDigitStatus::SeedCell ); + if ( entries.end() == iseed ) { + return Error ( "The seed cell is not found !" ) ; + } + + // get the "area" of the cluster (where seed is) + const LHCb::CaloDigit* seed = iseed->digit(); + if ( !seed ) { + return Error ( "Seed digit points to NULL!" ) ; + } + + // Cell ID for seed digit + const auto cellID = seed->cellID() ; + + + /** here all information is available + * + * (1) Ecal energy in 3x3 : energy + * (2) Prs and Spd energies : ePrs, eSpd + * (3) weighted barycenter : xBar, yBar + * (4) Zone/Area in Ecal : area + * (5) SEED digit : seed + * (6) CellID of seed digit : cellID + * (7) Position of seed cell : seedPos + */ + + + // Account for the tilt + const auto plane = m_det->plane(CaloPlane::Front); // Ecal Front-Plane + const LHCb::CaloPosition* pos = hypo->position() ; + + const auto xg = pos->x() - m_origin.X(); + const auto yg = pos->y() - m_origin.Y(); + const auto normal = plane.Normal(); + const auto Hesse = plane.HesseDistance(); + const auto z0 = (-Hesse - normal.X() * pos->x() - normal.Y() * pos->y()) / normal.Z(); + auto zg = z0 - m_origin.Z(); + + // hardcoded inner offset (+7.5 mm) + if ( cellID.area() == 2 ) { + zg += 7.5; + } + + // Uncorrected angle + const auto aaa = std::pow(xg, 2) + std::pow(yg, 2); + const auto tth = std::sqrt(aaa) / zg ; + //double cth = mycos ( myatan2( std::sqrt(aaa) , zg ) ) ; + auto cth = zg / std::sqrt( aaa + std::pow(zg, 2) ); + + // Corrected angle + + const auto gamma0 = getCorrection(CaloFutureCorrection::gamma0, cellID); + const auto delta0 = getCorrection(CaloFutureCorrection::delta0, cellID); + const auto gammaP = getCorrection(CaloFutureCorrection::gammaP, cellID, ePrs); + const auto deltaP = getCorrection(CaloFutureCorrection::deltaP, cellID, ePrs); + const auto g = gamma0 - gammaP; + const auto d = delta0 + deltaP; + + //double alpha = Par_Al1[zon] - myexp( Par_Al2[zon] - Par_Al3[zon] * ePrs/Gaudi::Units::MeV ); + //double beta = Par_Be1[zon] + myexp( Par_Be2[zon] - Par_Be3[zon] * ePrs/Gaudi::Units::MeV ); + + /// assert(cellID.area()>=0 &&cellID.area()<4); + m_counterPerCaloFutureAreaGamma.at(cellID.area()) += g; + m_counterPerCaloFutureAreaDelta.at(cellID.area()) += d; + + const auto tgfps = ( energy > 0.0 ? g * mylog(energy / Gaudi::Units::GeV) + d : 0.0 ); + + const auto bbb = ( 1. + tgfps * cth / zg ); + //cth = mycos( myatan2( tth , bbb ) ) ; + cth = bbb / std::sqrt( std::pow(tth, 2) + std::pow(bbb, 2) ); + + const auto dzfps = cth * tgfps ; + /// assert(cellID.area()>=0 &&cellID.area()<4); + m_counterPerCaloFutureAreaDeltaZ.at(cellID.area()) += dzfps; + m_counterDeltaZ += dzfps; + + /* + info() << " ======= Z0 FRONT-PLANE = " << z0 << " " << zg << endmsg; + ROOT::Math::Plane3D planeSM = m_det->plane(CaloPlane::ShowerMax); // Ecal Front-Plane + info() << " ======= Z0 SHOWERMAX = " << -planeSM.HesseDistance() <<endmsg; + ROOT::Math::Plane3D planeM = m_det->plane(CaloPlane::Middle); // Ecal Middle + info() << " ======= Z0 MIDDLE = " << -planeM.HesseDistance() <<endmsg; + */ + + + // Recompute Z position and fill CaloFuturePosition + const auto zCor = z0 + dzfps; + + if ( UNLIKELY( msgLevel(MSG::DEBUG) ) ) { + debug() << "Hypothesis :" << hypo->hypothesis() << endmsg; + debug() << " ENE " << hypo->position ()->e() << " " + << "xg " << xg << " " << "yg " << yg << endmsg; + debug() << "zg " << pos->z() << " " + << "z0 " << z0 << " " + << "DeltaZ " << dzfps << " " + << "zCor " << zCor + << endmsg ; + } + + hypo -> position() -> setZ( zCor ) ; + + return StatusCode::SUCCESS ; +} + +// ============================================================================ diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureLCorrection.h b/CaloFuture/CaloFutureReco/src/CaloFutureLCorrection.h new file mode 100644 index 0000000000000000000000000000000000000000..942a2f1b5245fdf8fb70e6ecf9788321c1c35eba --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureLCorrection.h @@ -0,0 +1,64 @@ +#ifndef CALOFUTURERECO_CALOFUTURELCORRECTION_H +#define CALOFUTURERECO_CALOFUTURELCORRECTION_H 1 + +// from STL +#include <string> +#include <cmath> + +// CaloFuture +#include "CaloFutureInterfaces/ICaloFutureHypoTool.h" +#include "CaloFutureCorrectionBase.h" +#include "CaloDet/DeCalorimeter.h" +#include "GaudiKernel/Counters.h" + +// Gaudi +#include "GaudiKernel/SystemOfUnits.h" + +// Event +#include "Event/CaloHypo.h" + +/** @class CaloFutureLCorrection CaloFutureLCorrection.h + * + * + * @author Deschamps Olivier + * @date 2003-03-10 + * revised 2010 + */ + +class CaloFutureLCorrection : + public virtual ICaloFutureHypoTool, + public CaloFutureCorrectionBase +{ +public: + + + StatusCode process ( LHCb::CaloHypo* hypo ) const override; + StatusCode operator() ( LHCb::CaloHypo* hypo ) const override; + + StatusCode initialize() override; + StatusCode finalize() override; + + /** Standard constructor + * @see GaudiTool + * @see AlgTool + * @param type tool type (?) + * @param name tool name + * @param parent tool parent + */ + CaloFutureLCorrection ( const std::string& type, + const std::string& name, + const IInterface* parent); +private: + using IncCounter = Gaudi::Accumulators::Counter<>; + using SCounter = Gaudi::Accumulators::StatCounter<float>; + + mutable IncCounter m_counterSkipNegativeEnergyCorrection{this, "Skip negative energy correction"}; + mutable SCounter m_counterDeltaZ{this, "Delta(Z)"}; + + static constexpr int k_numOfCaloFutureAreas{4}; + mutable std::vector<SCounter> m_counterPerCaloFutureAreaDeltaZ; + mutable std::vector<SCounter> m_counterPerCaloFutureAreaGamma; + mutable std::vector<SCounter> m_counterPerCaloFutureAreaDelta; +}; +// ============================================================================ +#endif // CALOFUTURERECO_CALOFUTURELCORRECTION_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureMergedPi0.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureMergedPi0.cpp new file mode 100644 index 0000000000000000000000000000000000000000..add1bd586b798f96f35319619f0ea0cc6eea6adb --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureMergedPi0.cpp @@ -0,0 +1,338 @@ +// ============================================================================ +// ============================================================================ +#include <numeric> +#include <algorithm> +#include <cmath> +#include "Event/CaloDataFunctor.h" +#include "CaloDet/DeCalorimeter.h" +#include "Event/CellID.h" +#include "Event/CaloHypo.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "Kernel/CaloCellID.h" +#include "GaudiKernel/SystemOfUnits.h" +#include "CaloFutureMergedPi0.h" +#include "CaloFutureUtils/CaloMomentum.h" +// ============================================================================ +/** @file CaloFutureMergedPi0.cpp + * + * Implementation file for class : CaloFutureMergedPi0 + * + * @author Olivier Deschamps + * @date 05/05/2014 + * + * New implementation of CaloFutureMergedPi0 algorithm + * + */ +// ============================================================================ + +DECLARE_COMPONENT( CaloFutureMergedPi0 ) + + CaloFutureMergedPi0::CaloFutureMergedPi0( const std::string& name , + ISvcLocator* svcloc ): GaudiAlgorithm ( name , svcloc ) +{ + // following properties are be inherited by the covariance tool + declareProperty( "CovarianceParameters" , m_covParams ) ; // KEEP IT UNSET ! INITIAL VALUE WOULD BYPASS DB ACCESS + + // default context-dependent locations + m_clusters = LHCb::CaloFutureAlgUtils::CaloFutureClusterLocation ( "Ecal" , context() ); // input : neutral CaloFutureCluster's + m_mergedPi0s = LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation ("MergedPi0s" , context() ); // output : mergedPi0 CaloFutureHypo's + m_splitPhotons = LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation("SplitPhotons", context() ); // output : splitPhoton CaloFutureHypo's + m_splitClusters = LHCb::CaloFutureAlgUtils::CaloFutureSplitClusterLocation(context() ); // output : splitCluster CaloFutureClusters +} + +bool CaloFutureMergedPi0::isNeighbor(LHCb::CaloCellID id0 , LHCb::CaloCellID id1){ + if( id0 == LHCb::CaloCellID() || id1 == LHCb::CaloCellID() )return false; + if( abs(int(id0.row()) - int(id1.row()) ) > 1 )return false; + if( abs(int(id0.col()) - int(id1.col()) ) > 1 )return false; + return true; +} + +// ============================================================================ + +StatusCode CaloFutureMergedPi0::initialize(){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug()<< "==> Initialise" << endmsg; + StatusCode sc = GaudiAlgorithm::initialize(); + if( sc.isFailure() )return Error("Could not initialize the base class!",sc); + + // Always skip negative-energy clusters : + if(m_minET<0.)m_minET=0.; + + if(m_createClusterOnly)info() << "Producing SplitClusters only" << endmsg; + + // get detectorElement + m_detector = getDet<DeCalorimeter>( m_det ) ; + if( !m_detector ){ return Error("could not locate calorimeter '"+m_det+"'");} + + //==== get tools + + // - main tool : + m_oTool=tool<ICaloFutureShowerOverlapTool>("CaloFutureShowerOverlapTool","SplitPhotonShowerOverlap",this); + + // - cluster tools + m_cov = tool<ICaloFutureClusterTool> ( "FutureClusterCovarianceMatrixTool" , "EcalCovariance" , this ) ; + m_spread = tool<ICaloFutureClusterTool> ( "FutureClusterSpreadTool" , "EcalSpread" , this ) ; + m_tagger = tool<FutureSubClusterSelectorTool>( "FutureSubClusterSelectorTool" , "EcalClusterTag" , this ); + + // - hypo tools + for ( std::vector<std::string>::const_iterator it = m_photonTools.begin() ;m_photonTools.end() != it ; ++it ){ + ICaloFutureHypoTool* t = tool<ICaloFutureHypoTool>( *it , this ); + if( 0 == t ) { return StatusCode::FAILURE ; } + m_gTools.push_back( t ) ; + } + + for ( std::vector<std::string>::const_iterator it = m_pi0Tools.begin() ;m_pi0Tools.end() != it ; ++it ){ + ICaloFutureHypoTool* t = tool<ICaloFutureHypoTool>( *it , this ); + if( 0 == t ) { return StatusCode::FAILURE ; } + m_pTools.push_back( t ) ; + } + counterStat = tool<IFutureCounterLevel>("FutureCounterLevel"); + return sc; +} + +StatusCode CaloFutureMergedPi0::finalize(){ + m_pTools.clear() ; + m_gTools.clear() ; + return GaudiAlgorithm::finalize(); +} + +StatusCode CaloFutureMergedPi0::execute(){ + + using namespace LHCb::CaloDataFunctor; + typedef LHCb::CaloClusters Clusters; + typedef Clusters::iterator Iterator; + + //======== load input : + Clusters* clusters = getIfExists<Clusters>( m_clusters ); + if( NULL == clusters )return Warning("No cluster input container : no merged Pi0 !", StatusCode::SUCCESS); + + + //======== create cluster output : + //- split clusters (check it does not exist first) + + + LHCb::CaloClusters* splitclusters = new LHCb::CaloClusters(); + int level = msgLevel(); // store outputLevel + try{ + setProperty("OutputLevel", MSG::ALWAYS ).ignore();// suppress FATAL message + put(splitclusters, m_splitClusters ); + } catch(GaudiException &exc ) { + setProperty("OutputLevel", level ).ignore(); // reset outputLevel before issuing a warning... + Warning("Existing SplitCluster container at "+ m_splitClusters + " found -> will replace",StatusCode::SUCCESS,1).ignore(); + delete splitclusters; + splitclusters=get<LHCb::CaloClusters>( m_splitClusters ); + splitclusters->clear(); + } + setProperty("OutputLevel", level ).ignore(); + + + //- pi0s & SPlitPhotons + LHCb::CaloHypos* pi0s = new LHCb::CaloHypos(); + LHCb::CaloHypos* phots = new LHCb::CaloHypos(); + + // put on TES when requested + if(!m_createClusterOnly){ + put( pi0s , m_mergedPi0s ); + put( phots , m_splitPhotons); + } + + + //- load SPD container : + LHCb::CaloDigits* spds = getIfExists<LHCb::CaloDigits>( LHCb::CaloDigitLocation::Spd ); + + // - setup the estimator of cluster transverse energy + LHCb::CaloDataFunctor::EnergyTransverse<const DeCalorimeter*> eT ( m_detector ) ; + + // define entry status' + + LHCb::CaloDigitStatus::Status used = + LHCb::CaloDigitStatus::UseForEnergy | + LHCb::CaloDigitStatus::UseForPosition | + LHCb::CaloDigitStatus::UseForCovariance ; + LHCb::CaloDigitStatus::Status seed = LHCb::CaloDigitStatus::SeedCell | + LHCb::CaloDigitStatus::LocalMaximum | used ; + + // ============ loop over all clusters ============== + for( Iterator icluster = clusters->begin() ; clusters->end() != icluster ; ++icluster ){ + LHCb::CaloCluster* cluster = *icluster ; + if( 0 == cluster ) { continue ; } + if ( 0 < m_etCut && m_etCut > eT( cluster ) ) { continue ; } + + // -- remove small clusters : + if( 1 >= cluster->entries().size() )continue; + + // -- locate cluster Seed + const LHCb::CaloCluster::Digits::iterator iSeed = + clusterLocateDigit( cluster->entries().begin() , cluster->entries().end () , LHCb::CaloDigitStatus::SeedCell ); + LHCb::CaloDigit* dig1 = iSeed->digit() ; + if( 0 == dig1) continue ; + LHCb::CaloCellID seed1 = dig1->cellID() ; + + double seede = dig1->e(); + + // -- get spd hit in front of seed1 + int spd1 = 0 ; + const LHCb::CaloDigit* spddigit1 = (spds == NULL) ? NULL : spds->object( dig1->key() ); + if( NULL != spddigit1 )spd1 = (spddigit1->e() > 0.) ? 1 : 0 ; + + // -- locate seed2 + double sube = 0. ; // 2nd seed should must have a positive energy ! + LHCb::CaloDigit* dig2 = nullptr; + for( LHCb::CaloCluster::Digits::iterator it =cluster->entries().begin() ; cluster->entries().end() != it ; ++it ){ + LHCb::CaloDigit* dig = it->digit() ; + if( !dig ) { continue ; } + LHCb::CaloCellID seed = dig->cellID() ; + double ecel = dig->e()*it->fraction(); + if (ecel > sube && ecel < seede && isNeighbor( seed1, seed) && !(seed==seed1)){ + //if (ecel > sube && ecel < seede && isNeighbor( seed1, seed) ){ + sube=ecel; + dig2=dig; + } + } + + if ( !dig2 ){ + if(counterStat->isQuiet())counter("Cluster without 2nd seed found") += 1; + continue ; + } + + LHCb::CaloCellID seed2 = dig2->cellID() ; + // -- get spd hit in front of seed2 + const LHCb::CaloDigit* spddigit2 = ( spds ? spds->object( dig2->key() ) : nullptr ); + int spd2 = 0 ; + if( spddigit2 ) { spd2 = (spddigit2->e() > 0.) ? 1 : 0 ; } + + + // -- create and fill sub-cluster + auto cl1 = std::make_unique<LHCb::CaloCluster>(); + cl1->setSeed( seed1 ); + cl1->setType( LHCb::CaloCluster::Type::Area3x3 ); + auto cl2 = std::make_unique<LHCb::CaloCluster>(); + cl2->setSeed( seed2 ); + cl2->setType( LHCb::CaloCluster::Type::Area3x3 ); + + for( const auto& it2 : cluster->entries() ) { + const LHCb::CaloDigit* dig = it2.digit() ; + if( !dig ) continue ; + const LHCb::CaloCellID id = dig->cellID() ; + double fraction = it2.fraction(); + + // -- tag 3x3 area for energy and position + if ( isNeighbor( seed1, id ) ){ + LHCb::CaloDigitStatus::Status status = ( seed1 == id ) ? seed : used; + // set initial weights + double weight1 = fraction; + if( seed2 == id )weight1=0.; + else if( seed1 == id )weight1=fraction; + else if (isNeighbor(seed2,id)) weight1=dig1->e() / (dig1->e() + dig2->e())*fraction; + cl1->entries().emplace_back( dig , status, weight1 ); + } + if ( isNeighbor( seed2, id ) ){ + LHCb::CaloDigitStatus::Status status = ( seed2 == id ) ? seed : used; + //set initial weights + double weight2 = fraction; + if( seed1 == id )weight2=0.; + else if(seed2 == id)weight2=fraction; + else if (isNeighbor(seed1,id))weight2=dig2->e() / (dig1->e() + dig2->e())*fraction; + cl2->entries().emplace_back( dig , status,weight2 ); + } + } + + + // -- apply position tagger (possibly replacing the 3x3 already set) + // -- needed to apply hypo S/L-corrections with correct parameters internally + // -- keep the 3x3 energy tag for the time being (to be applied after the overlap subtraction) + StatusCode sc; + sc = m_tagger->tagPosition( cl1.get() ) ; + sc = m_tagger->tagPosition( cl2.get() ) ; + if( sc.isFailure() )Warning("SplitCluster tagging failed - keep the initial 3x3 tagging").ignore(); + + // == apply the mergedPi0 tool : subtract shower overlap + m_oTool->process(cl1.get(),cl2.get(), spd1*10+spd2, m_iter,true); // 'true' means the initial entries weight is propagated + if( LHCb::CaloMomentum(cl1.get()).pt() <= m_minET || LHCb::CaloMomentum(cl2.get()).pt() <= m_minET ){ // skip negative energy "clusters" + continue; + } + + // == prepare outputs : + + // apply loose mass window : (TODO ??) + + // == APPLY CLUSTER TOOLS : Energy tagger, covariance & spread (position tagger already applied): + if (m_tagger -> tagEnergy ( cl1.get() ).isFailure() )if (counterStat->isQuiet() )counter("Fails to tag(E) cluster (1)")+=1; + if (m_tagger -> tagEnergy ( cl2.get() ).isFailure() )if (counterStat->isQuiet() )counter("Fails to tag(E) cluster (2)")+=1; + if (m_cov -> process( cl1.get() ).isFailure() )if (counterStat->isQuiet() )counter("Fails to set covariance (1)")+=1; + if (m_cov -> process( cl2.get() ).isFailure() )if (counterStat->isQuiet() )counter("Fails to set covariance (2)")+=1; + if (m_spread-> process( cl1.get() ).isFailure() )if (counterStat->isQuiet() )counter("Fails to set spread (1)") +=1; + if (m_spread-> process( cl2 .get()).isFailure() )if (counterStat->isQuiet() )counter("Fails to set spread (2)") +=1; + + // == insert splitClusters into their container + auto clu1 = cl1.get(); splitclusters->insert( cl1.release() ) ; + auto clu2 = cl2.get(); splitclusters->insert( cl2.release() ) ; + // == create CaloHypos if needed + if (!m_createClusterOnly) { + // new CaloHypos for splitPhotons + auto g1 = std::make_unique<LHCb::CaloHypo>() ; + g1 -> setHypothesis( LHCb::CaloHypo::Hypothesis::PhotonFromMergedPi0 ) ; + g1 -> addToClusters( cluster ) ; + g1 -> addToClusters( clu1 ) ; + g1 -> setPosition( std::make_unique< LHCb::CaloPosition>( clu1->position()) ); + + auto g2 = std::make_unique<LHCb::CaloHypo>() ; + g2 -> setHypothesis( LHCb::CaloHypo::Hypothesis::PhotonFromMergedPi0 ) ; + g2 -> addToClusters( cluster ) ; + g2 -> addToClusters( clu2 ) ; + g2 -> setPosition( std::make_unique<LHCb::CaloPosition>( clu2->position() ) ); + + // new CaloHypo for mergedPi0 + auto pi0 = std::make_unique<LHCb::CaloHypo>(); + pi0 -> setHypothesis( LHCb::CaloHypo::Hypothesis::Pi0Merged ) ; + pi0 -> addToClusters( cluster ); + pi0 -> addToHypos ( g2.get() ); + pi0 -> addToHypos ( g1.get() ); + + //-- Apply hypo tools : E/S/L-corrections + int i = 0; + for( ICaloFutureHypoTool* t : m_gTools ) { + i++; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) )debug() << " apply SplitPhoton tool " << i << "/" << m_gTools.size() << endmsg; + if( !t ) continue; + auto sc = (*t) ( g1.get() ) ; + if( sc.isFailure() ) Error("Error from 'Tool' for g1 " , sc ).ignore() ; + sc = (*t) ( g2.get() ) ; + if( sc.isFailure() )Error("Error from 'Tool' for g2 " , sc ).ignore() ; + } + + i = 0; + for( ICaloFutureHypoTool* t : m_pTools ) { + i++; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) )debug() << " apply MergedPi0 tool " << i << "/" << m_pTools.size() << endmsg; + if( !t ) { continue; } + auto sc = (*t) ( pi0.get() ) ; + if( sc.isFailure() )Error("Error from 'Tool' for pi0 " , sc ).ignore() ; + } + + + // skip negative energy CaloHypos + if( LHCb::CaloMomentum(g1.get()).pt() >= m_minET && LHCb::CaloMomentum(g2.get()).pt() >= m_minET ){ + if ( m_verbose ) info() << " >> MergedPi0 hypo Mass : " << LHCb::CaloMomentum(pi0.get()).mass() << endmsg; + phots ->insert( g1.release() ) ; + phots ->insert( g2.release() ) ; + pi0s -> insert( pi0.release() ) ; + } + } + } + + // ====================== // + if(counterStat->isQuiet()&&!m_createClusterOnly)counter ( m_clusters + "=>" + m_mergedPi0s ) += pi0s -> size() ; + if(counterStat->isQuiet()&&!m_createClusterOnly)counter ( m_clusters + "=>" + m_splitPhotons) += phots -> size() ; + if(counterStat->isQuiet())counter ( m_clusters + "=>" + m_splitClusters) += splitclusters -> size() ; + + // delete (empty) container* if not on TES + StatusCode sc = StatusCode::SUCCESS; + if(m_createClusterOnly){ + if( 0 != pi0s->size() || 0 != phots->size() ){ + sc = Error( "Container* to be deleted are not empty", StatusCode::FAILURE); + } + delete pi0s; + delete phots; + } + return sc; +} diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureMergedPi0.h b/CaloFuture/CaloFutureReco/src/CaloFutureMergedPi0.h new file mode 100644 index 0000000000000000000000000000000000000000..6a1c95c391e62d527d1548e80df2963a8972cede --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureMergedPi0.h @@ -0,0 +1,74 @@ +// ============================================================================ +#ifndef CALOFUTURERECO_CALOFUTUREMERGEDPI0_H +#define CALOFUTURERECO_CALOFUTUREMERGEDPI0_H 1 +// ============================================================================ +// Include files +// ============================================================================ +// from STL +// ============================================================================ +#include <string> +#include <vector> +// ============================================================================ +#include "GaudiAlg/GaudiAlgorithm.h" +#include "CaloFutureInterfaces/ICaloFutureClusterTool.h" +#include "FutureSubClusterSelectorTool.h" +#include "CaloFutureInterfaces/ICaloFutureHypoTool.h" +#include "CaloFutureInterfaces/ICaloFutureShowerOverlapTool.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" +#include "CaloDet/DeCalorimeter.h" +#include "Event/CaloCluster.h" +// ============================================================================ + +/** @class CaloFutureMergedPi0 CaloFutureMergedPi0.h + * + * Merged pi0 reconstruction with iterativ Method + * + * NEW IMPLEMENTATION + * + * @author Olivier Deschamps + * @date 05/05/2014 + */ + +class CaloFutureMergedPi0 : public GaudiAlgorithm{ +public: + + CaloFutureMergedPi0( const std::string& name , ISvcLocator* svcloc ); + + StatusCode initialize() override; + StatusCode execute() override; + StatusCode finalize() override; + +private: + bool isNeighbor(LHCb::CaloCellID id0, LHCb::CaloCellID id1); + + Gaudi::Property<std::string> m_clusters {this, "InputData" , LHCb::CaloClusterLocation::Ecal}; + Gaudi::Property<std::string> m_splitClusters {this, "SplitClusters", LHCb::CaloClusterLocation::EcalSplit}; + Gaudi::Property<std::string> m_mergedPi0s {this, "MergedPi0s" , LHCb::CaloHypoLocation::MergedPi0s}; + Gaudi::Property<std::string> m_splitPhotons {this, "SplitPhotons" , LHCb::CaloHypoLocation::SplitPhotons}; + + Gaudi::Property<float> m_etCut {this, "EtCut", 1500 * Gaudi::Units::MeV}; + Gaudi::Property<int> m_iter {this, "MaxIterations", 25}; + Gaudi::Property<bool> m_createClusterOnly {this, "CreateSplitClustersOnly", false}; + + // tools name + Gaudi::Property<std::vector<std::string>> m_photonTools {this, "PhotonTools"}; + Gaudi::Property<std::vector<std::string>> m_pi0Tools {this, "Pi0Tools"}; + + // tools interfaces + std::vector<ICaloFutureHypoTool*> m_gTools ; + std::vector<ICaloFutureHypoTool*> m_pTools ; + ICaloFutureShowerOverlapTool* m_oTool = nullptr ; + ICaloFutureClusterTool* m_cov = nullptr ; + ICaloFutureClusterTool* m_spread = nullptr ; + FutureSubClusterSelectorTool* m_tagger = nullptr ; + Gaudi::Property<std::vector<std::string>> m_taggerE {this, "EnergyTags"}; + Gaudi::Property<std::vector<std::string>> m_taggerP {this, "PositionTags"}; + Gaudi::Property<std::string> m_det {this, "Detector", DeCalorimeterLocation::Ecal}; + DeCalorimeter* m_detector = nullptr ; + Gaudi::Property<bool> m_verbose {this, "Verbose", false}; + Gaudi::Property<float> m_minET {this, "SplitPhotonMinET", 0.}; + std::map<std::string,std::vector<double> > m_covParams; + IFutureCounterLevel* counterStat = nullptr; +}; +// ============================================================================ +#endif // CALOFUTUREMERGEDPI0_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSCorrection.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureSCorrection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..948cd5efe0cdc801bcecde3acad945e3499e6e7b --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSCorrection.cpp @@ -0,0 +1,448 @@ +// ============================================================================ +// Include files +#include "GaudiKernel/SystemOfUnits.h" +#include "Event/CaloHypo.h" +#include "CaloFutureSCorrection.h" + +/** @file + * Implementation file for class : CaloFutureSCorrection + * + * @date 2003-03-10 + * @author Xxxx XXXXX xxx@xxx.com + */ + +DECLARE_COMPONENT( CaloFutureSCorrection ) + +// ============================================================================ +/** Standard constructor + * @see GaudiTool + * @see AlgTool + * @param type tool type (?) + * @param name tool name + * @param parent tool parent + */ +// ============================================================================ +CaloFutureSCorrection::CaloFutureSCorrection( const std::string& type , + const std::string& name , + const IInterface* parent ) + : CaloFutureCorrectionBase( type , name , parent ){ + + + // define conditionName + const std::string uName ( LHCb::CaloFutureAlgUtils::toUpper( name ) ) ; + if( uName.find( "ELECTRON" ) != std::string::npos ){ + m_conditionName = "Conditions/Reco/Calo/ElectronSCorrection"; + }else if ( uName.find( "MERGED" ) != std::string::npos || uName.find( "SPLITPHOTON" ) != std::string::npos ){ + m_conditionName = "Conditions/Reco/Calo/SplitPhotonSCorrection"; + } + else if ( uName.find( "PHOTON" ) ){ + m_conditionName = "Conditions/Reco/Calo/PhotonSCorrection"; + } + declareInterface<ICaloFutureHypoTool> ( this ) ; +} +// ============================================================================ + +StatusCode CaloFutureSCorrection::finalize() +{ + m_hypos.clear(); + // finalize the base class + return CaloFutureCorrectionBase::finalize () ; +} +// ============================================================================ + +StatusCode CaloFutureSCorrection::initialize (){ + // first initialize the base class + StatusCode sc = CaloFutureCorrectionBase::initialize(); + if( sc.isFailure() ) + { return Error ( "Unable initialize the base class CaloFutureCorrectionBase!" , sc ) ; } + if (UNLIKELY( msgLevel( MSG::DEBUG)) ) + debug() << "Condition name : " << m_conditionName << endmsg; + + return StatusCode::SUCCESS ; +} +// ============================================================================ + +StatusCode CaloFutureSCorrection::operator() ( LHCb::CaloHypo* hypo ) const{ +return process( hypo ); +} +// ============================================================================ + +// ============================================================================ +StatusCode CaloFutureSCorrection::process ( LHCb::CaloHypo* hypo ) const{ + + // check arguments + if( 0 == hypo )return Warning( " CaloHypo* points to NULL!",StatusCode::SUCCESS ) ; + + + // check the Hypo + Hypotheses::const_iterator h = + std::find( m_hypos.begin() , m_hypos.end() , hypo->hypothesis() ) ; + if( m_hypos.end() == h )return Error ( "Invalid hypothesis!",StatusCode::SUCCESS ) ; + + // No correction for negative energy : + if( hypo->e() < 0.){ + ++m_counterSkipNegativeEnergyCorrection; + return StatusCode::SUCCESS; + } + + // get cluster (special case for SplitPhotons) + // const LHCb::CaloCluster* GlobalCluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo(hypo, false); // not used + const LHCb::CaloCluster* MainCluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo(hypo,true) ; + + + /* + Cluster information (e/x/y and Prs/Spd digit) + */ + if( 0 == MainCluster )return Warning ( "CaloCLuster* points to NULL -> no correction applied" , StatusCode::SUCCESS) ; + + // ePrs, eSpd currently not used here + // + // // get Prs/Spd + // double ePrs = 0 ; + // double eSpd = 0 ; + // getPrsSpd(hypo,ePrs,eSpd); + // // For Split Photon - share the Prs energy + // if( LHCb::CaloHypo::Hypothesis::PhotonFromMergedPi0 == hypo->hypothesis() ){ + // ePrs *= MainCluster->position().e()/GlobalCluster->position().e() ; + // } + + // Get position + const LHCb::CaloPosition& position = MainCluster->position(); + const double xBar = position. x () ; + const double yBar = position. y () ; + + + // Informations from seed Digit Seed ID & position + const LHCb::CaloCluster::Entries& entries = MainCluster->entries(); + LHCb::CaloCluster::Entries::const_iterator iseed = + LHCb::ClusterFunctors::locateDigit ( entries.begin () ,entries.end () ,LHCb::CaloDigitStatus::SeedCell ); + if( entries.end() == iseed )return Warning( "The seed cell is not found -> no correction applied",StatusCode::SUCCESS ) ; + + // get the "area" of the cluster (where seed is) + const LHCb::CaloDigit* seed = iseed->digit(); + if( 0 == seed )return Warning ( "Seed digit points to NULL -> no correction applied",StatusCode::SUCCESS ) ; + + // int area = cellID.area(); // currently not used + + + + // Somewhat inelegant way of data sharing between this const method process() and calcSCorrection(). Use of private fields + // of this CaloFutureSCorrection class for the same purpose would break the constness of the process() interface. + struct SCorrInputParams params; // input parameters: currently only cellID, seedPos and MainCluster->position.z + struct SCorrOutputParams results = {0, 0}; // output parameters: just d(Xhypo)/d(Xcluster) and d(Yhypo)/d(Ycluster) + + // Cell ID for seed digit + params.cellID = seed->cellID() ; + params.seedPos = m_det->cellCenter( params.cellID ); + params.z = position. z () ; + + /** here all information is available + * + * (1) Ecal energy in 3x3 : eEcal ( not used ) + * (2) Prs and Spd energies : ePrs, eSpd ( not used ) + * (3) weighted barycenter : xBar, yBar + * (4) Zone/Area in Ecal : area ( not used ) + * (5) SEED digit : seed (NOT FOR SPLITPHOTONS !!) + * (6) CellID of seed digit : cellID + * (7) Position of seed cell : seedPos + */ + + + double xCor, yCor; // corrected hypo position + double xCor_x, xCor_y, yCor_x, yCor_y; + + + calcSCorrection(xBar, yBar, xCor, yCor, params, &results); + + const double &dXhy_dXcl = results.dXhy_dXcl; + const double &dYhy_dYcl = results.dYhy_dYcl; + + // protection against unphysical d(Xhypo)/d(Xcluster) == 0 or d(Yhypo)/d(Ycluster) == 0 + if ( fabs( dXhy_dXcl ) < 1e-10 ){ + warning() << "unphysical d(Xhypo)/d(Xcluster) = " << dXhy_dXcl << " reset to 1 as if Xhypo = Xcluster" << endmsg; + const_cast<double &>( dXhy_dXcl ) = 1.; + } + if ( fabs( dYhy_dYcl ) < 1e-10 ){ + warning() << "unphysical d(Yhypo)/d(Ycluster) = " << dYhy_dYcl << " reset to 1 as if Yhypo = Ycluster" << endmsg; + const_cast<double &>( dYhy_dYcl ) = 1.; + } + + + // numeric partial derivatives w.r.t. X and Y, necessary to check after any change to the S-corrections + if ( UNLIKELY(msgLevel(MSG::DEBUG)) && m_correctCovariance ){ + const double dx_rel(1.e-5); // dx ~ 0.1 mm for numeric derivative calculation + + debug() << " ---------- calculation of numeric derivative dXhypo/dXcluster follows -----------" << endmsg; + calcSCorrection(xBar*(1+dx_rel), yBar, xCor_x, yCor_x, params, NULL); + + debug() << " ---------- calculation of numeric derivative dYhypo/dYcluster follows -----------" << endmsg; + calcSCorrection(xBar, yBar*(1+dx_rel), xCor_y, yCor_y, params, NULL); + + const double dn_xCor_dx = (xCor_x-xCor)/xBar/dx_rel; + const double dn_yCor_dx = (yCor_x-yCor)/xBar/dx_rel; // sanity test, should be 0 + const double dn_xCor_dy = (xCor_y-xCor)/yBar/dx_rel; // sanity test, should be 0 + const double dn_yCor_dy = (yCor_y-yCor)/yBar/dx_rel; + + + if ( fabs((dXhy_dXcl-dn_xCor_dx)/dXhy_dXcl) > 0.02 || fabs((dYhy_dYcl-dn_yCor_dy)/dYhy_dYcl) > 0.02 + || fabs( dn_yCor_dx ) > 1e-8 || fabs( dn_xCor_dy ) > 1e-7 ) + debug() << " SCorrection numerically-caluclated Jacobian differs (by > 2%) from analytically-calculated one" << endmsg; + + debug() << "================== Jacobian elements ============= " << endmsg; + debug() << " semi-analytic dXhy_dXcl = " << dXhy_dXcl << " numeric dn_xCor_dx = " << dn_xCor_dx << " dn_xCor_dy = " << dn_xCor_dy << endmsg; + debug() << " semi-analytic dYhy_dYcl = " << dYhy_dYcl << " numeric dn_yCor_dy = " << dn_yCor_dy << " dn_yCor_dx = " << dn_yCor_dx << endmsg; + } + + const LHCb::CaloPosition* pos = hypo->position() ; + + if (UNLIKELY( msgLevel( MSG::DEBUG)) ){ + debug() << "Calo Hypothesis :" << hypo->hypothesis() << endmsg; + debug() << "cellID : " << params.cellID << endmsg; + debug() << "Hypo E : " << hypo->position ()->e() << " " << params.cellID << endmsg; + debug() << "xBar/yBar " << xBar << "/" << yBar << endmsg; + debug() << "xg/yg " << pos->x() << "/" << pos->y() << endmsg; + debug() << "xNew/yNew " << xCor << "/" << yCor << endmsg; + debug() << "xcel/ycel " << params.seedPos.x() << "/" << params.seedPos.y() << endmsg ; + } + + // update position + LHCb::CaloPosition::Parameters& parameters = hypo ->position() ->parameters () ; + parameters ( LHCb::CaloPosition::Index::X ) = xCor ; + parameters ( LHCb::CaloPosition::Index::Y ) = yCor ; + m_counterDeltaX += xCor-xBar; + m_counterDeltaY += yCor-yBar; + + // update cov.m.: error propagation due to the S-correction + if ( m_correctCovariance ){ + LHCb::CaloPosition::Covariance& covariance = hypo ->position() ->covariance () ; + + if ( UNLIKELY(msgLevel( MSG::DEBUG)) ){ + debug() << "before s-cor cov.m. = \n" << covariance << endmsg; + } + + // cov.m packing in double array[5] following ROOT::Math::SMatrix<double,3,3>::Array() + // for row/column indices (X:0, Y:1, E:2), see comments in CaloFutureECorrection::process() + double c1[6]; + + c1[0] = covariance(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::X); // arr[0] not relying on LHCb::CaloPosition::Index::X == 0 + c1[2] = covariance(LHCb::CaloPosition::Index::Y, LHCb::CaloPosition::Index::Y); // arr[2] not relying on LHCb::CaloPosition::Index::Y == 1 + c1[5] = covariance(LHCb::CaloPosition::Index::E, LHCb::CaloPosition::Index::E); // arr[5] not relying on LHCb::CaloPosition::Index::E == 2 + c1[1] = covariance(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::Y); // arr[1] + c1[3] = covariance(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::E); // arr[3] + c1[4] = covariance(LHCb::CaloPosition::Index::Y, LHCb::CaloPosition::Index::E); // arr[4] + + // cov1 = (J * cov0 * J^T) for the special case of diagonal Jacobian for (X,Y,E) -> (X1=X1(X), Y1=Y1(Y), E1=E) + c1[0] *= dXhy_dXcl * dXhy_dXcl; + c1[1] *= dXhy_dXcl * dYhy_dYcl; + c1[2] *= dYhy_dYcl * dYhy_dYcl; + c1[3] *= dXhy_dXcl; + c1[4] *= dYhy_dYcl; + // c1[5] remains unchanged (energy is not chaged by S-correction) + + + // alternatively, a code fragment for a general-form Jacobian (cf. a similar comment in CaloFutureECorrection::process()) + // TMatrixD jac(3, 3); // just a diagonal Jacobian in case of (X,Y,E) -> (X1(X), Y1(Y), E) transformation + // jac(0,0) = dXhy_dXcl; + // jac(1,1) = dYhy_dYcl; + // jac(2,2) = 1.; + // if ( msgLevel( MSG::DEBUG) ){ debug() << "s-cor jacobian = " << endmsg; jac.Print(); } + // TMarixDSym cov0(3) = ... // to be initilized from hypo->position()->covariance() + // TMarixDSym cov1(3); // resulting extrapolated cov.m. + // recalculate_cov(jac, cov0, cov1); // calculate: cov1 = (J * cov0 * J^T) + + + // finally update CaloHypo::position()->covariance() + covariance(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::X) = c1[0]; // cov1(0,0); + covariance(LHCb::CaloPosition::Index::Y, LHCb::CaloPosition::Index::Y) = c1[2]; // cov1(1,1); + covariance(LHCb::CaloPosition::Index::E, LHCb::CaloPosition::Index::E) = c1[5]; // cov1(2,2); + covariance(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::Y) = c1[1]; // cov1(0,1); + covariance(LHCb::CaloPosition::Index::X, LHCb::CaloPosition::Index::E) = c1[3]; // cov1(0,2); + covariance(LHCb::CaloPosition::Index::Y, LHCb::CaloPosition::Index::E) = c1[4]; // cov1(1,2); + + // // DG: my little paranoia, should be always ok since Covariance is SMatrix<3,3,double> internally represented as double array[5] + // assert( covariance(LHCb::CaloFuturePosition::Index::X, LHCb::CaloFuturePosition::Index::Y) == covariance(LHCb::CaloFuturePosition::Index::Y, LHCb::CaloFuturePosition::Index::X)); + // assert( covariance(LHCb::CaloFuturePosition::Index::X, LHCb::CaloFuturePosition::Index::E) == covariance(LHCb::CaloFuturePosition::Index::E, LHCb::CaloFuturePosition::Index::X)); + // assert( covariance(LHCb::CaloFuturePosition::Index::Y, LHCb::CaloFuturePosition::Index::E) == covariance(LHCb::CaloFuturePosition::Index::E, LHCb::CaloFuturePosition::Index::Y)); + + if ( UNLIKELY(msgLevel( MSG::DEBUG)) ){ + debug() << "after s-cor cov.m. = \n" << covariance << endmsg; + } + } + + + return StatusCode::SUCCESS ; + +} +// ============================================================================ + +void CaloFutureSCorrection::calcSCorrection( double xBar, double yBar, double &xCor, double &yCor, + const struct SCorrInputParams ¶ms, + struct SCorrOutputParams *results ) const +{ + // declare local short aliases for the input variables passed from process() to calcSCorrection() + const LHCb::CaloCellID &cellID = params.cellID; + const Gaudi::XYZPoint &seedPos = params.seedPos; + const double &z = params.z; + + + double CellSize = m_det->cellSize( cellID ); + double Asx = - ( xBar - seedPos.x() ) / CellSize ; + double Asy = - ( yBar - seedPos.y() ) / CellSize ; + + // cash intermediate values + const double Asx0 = Asx; + const double Asy0 = Asy; + + + // Sshape correction : + Asx = getCorrection(CaloFutureCorrection::shapeX , cellID , Asx , Asx ); // Asx1 + Asy = getCorrection(CaloFutureCorrection::shapeY , cellID , Asy , Asy ); // Asy1 + + // // cash intermediate values: necessary for debugging by calculating numeric derivatives dn_shapeX, dn_shapeY below + // const double Asx1 = Asx; + // const double Asy1 = Asy; + + + // Angular correction (if any) [ NEW - inserted between Sshape and residual correction ] + const double xs = seedPos.x() - Asx * CellSize; // xscor + const double ys = seedPos.y() - Asy * CellSize; // yscor + const double thx = myatan2( xs , z ); + const double thy = myatan2( ys , z ); + const double daX = getCorrection(CaloFutureCorrection::angularX , cellID , thx , 0.); + const double daY = getCorrection(CaloFutureCorrection::angularY , cellID , thy , 0.); + Asx -= daX; + Asy -= daY; + + // cash intermediate values + const double Asx2 = Asx; + const double Asy2 = Asy; + + + // residual correction (if any): + bool residualX_flag = false; + double dcX = getCorrection(CaloFutureCorrection::residual , cellID , Asx , 0.); + if( dcX == 0.){ + dcX = getCorrection(CaloFutureCorrection::residualX , cellID , Asx , 0.); // check X-specific correction + residualX_flag = true; + } + bool residualY_flag = false; + double dcY = getCorrection(CaloFutureCorrection::residual , cellID , Asy , 0.); + if( dcY == 0.){ + dcY = getCorrection(CaloFutureCorrection::residualY , cellID , Asy , 0.); // check Y-specific correction + residualY_flag = true; + } + Asx -= dcX; + Asy -= dcY; + + // cash intermediate values + const double Asx3 = Asx; + const double Asy3 = Asy; + + + // left/right - up/down asymmetries correction (if any) : + double ddcX = (xBar < 0 ) ? + getCorrection(CaloFutureCorrection::asymM , cellID , Asx , 0.): + getCorrection(CaloFutureCorrection::asymP , cellID , Asx , 0.); + double ddcY = (yBar < 0 ) ? + getCorrection(CaloFutureCorrection::asymM , cellID , Asy , 0.): + getCorrection(CaloFutureCorrection::asymP , cellID , Asy , 0.); + Asx += ddcX; // Asx4 + Asy += ddcY; // Asy4 + + + // Recompute position and fill CaloFuturePosition + xCor = seedPos.x() - Asx * CellSize; + yCor = seedPos.y() - Asy * CellSize; + + + +/* DG,20140714: derivative calculation for d(Xhypo)/d(Xcluster) + * + * Asx0 =-(xBar - seedPos.x)/CellSize; // xBar = Xcluster + * Asx1 = shapeX(Asx0) + * xs = seedPos.x - Asx1*CellSize + * thx = atan(xs/z); // in principle, this brings in an implicit dependence on cluster E, but it's logarithmic so let's neglect it + * daX = angular(thx) + * Asx2 = Asx1 - daX + * dcX = residual(Asx2) != 0 ? residual(Asx2) : residualX(Asx2); // add an auxiliary bool residualX_flag + * Asx3 = Asx2 - dcX + * ddcX = asym(Asx3) + * Asx4 = Asx3 + ddcX = Asx + * Xhypo= xCor(Asx4) = seedPos.x - Asx4*CellSize + * + * d(Xhypo)/d(Xcluster) = d(xCor)/d(Asx4) * product[ d(Asx%i)/d(Asx%{i-1}), for i=1..4 ] * d(Asx0)/d(Xcluster) + * + * d(xCor)/d(Asx4) =-CellSize + * d(Asx0)/d(Xcluster) = d(Asx0)/d(xBar) = -1/CellSize + * d(Asx1)/d(Asx0) = DshapeX(Asx0) + * d(thx)/d(Asx1) = d(thx)/d(xs) * d(xs)/d(Asx1) =-CellSize/(1+(xc/z)**2)*(1/z) + * d(xs)/d(Asx1) =-CellSize + * d(Asx2)/d(Asx1) = 1 - d(daX)/d(Asx1) = 1 - Dangular(thx)*d(thx)/d(Asx1) = 1 + Dangular(thx)*CellSize/z/(1+(xs/z)**2) + * d(Asx3)/d(Asx2) = 1 - d(dcX)/d(Asx2) = 1 - ( residual(Asx2) != 0 ? Dresidual(Asx2) : DresidualX(Asx2) ) + * residualX_flag = residual(Asx2) != 0 ? false : true + * d(Asx4)/d(Asx3) = 1 + d(ddcX)/d(Asx3) = 1 + Dasym(Asx3) + * + * + * d(Xhypo)/d(Xcluster) = (1 + Dasym(Asx3)) * (1 - (resudualX_flag ? DresidualX(Asx2) : Dresidual(Asx2))) + * *(1 + Dangular(thx)*CellSize/z/(1+(xs/z)**2)) * DshapeX(Asx0) + */ + + if ( m_correctCovariance && results ){ + // // ---- calculation of numeric derivatives of individual correction functions, important for debugging in case of code changes --- + // debug() << "---------- numeric derivatives of individual S-correction functions ---------------" << endmsg; + // double tmpd = ( fabs(Asx0) > 1.e-5 ) ? Asx0*2.e-2 : 2.e-7; + // double dn_shapeX = ( getCorrection(CaloFutureCorrection::shapeX, cellID, Asx0 + tmpd, Asx0 + tmpd) - Asx1 )/tmpd; + // tmpd = ( fabs(Asy0) > 1.e-5 ) ? Asy0*2.e-2 : 2.e-7; + // double dn_shapeY = ( getCorrection(CaloFutureCorrection::shapeY, cellID, Asy0 + tmpd, Asy0 + tmpd) - Asy1 )/tmpd; + // + // double dn_angularX = ( getCorrection(CaloFutureCorrection::angularX, cellID, thx*1.002, 0.) - daX )/thx/2e-3; + // double dn_angularY = ( getCorrection(CaloFutureCorrection::angularY, cellID, thy*1.002, 0.) - daY )/thy/2e-3; + // + // tmpd = ( fabs(Asx2) > 1.e-5 ) ? Asx2*2.e-3 : 2.e-8; + // double dn_residualX = ( getCorrection((residualX_flag ? CaloFutureCorrection::residualX : CaloFutureCorrection::residual), + // cellID, Asx2 + tmpd, 0.) - dcX )/tmpd; + // tmpd = ( fabs(Asy2) > 1.e-5 ) ? Asy2*2.e-3 : 2.e-8; + // double dn_residualY = ( getCorrection((residualY_flag ? CaloFutureCorrection::residualY : CaloFutureCorrection::residual), + // cellID, Asy2 + tmpd, 0.) - dcY )/tmpd; + // tmpd = ( fabs(Asx3) > 1.e-5 ) ? Asx3*2.e-3 : 2.e-8; + // double dn_asymX = (xBar < 0 ) ? + // ( getCorrection(CaloFutureCorrection::asymM , cellID , Asx2 + tmpd , 0.) - ddcX )/tmpd : + // ( getCorrection(CaloFutureCorrection::asymP , cellID , Asx2 + tmpd , 0.) - ddcX )/tmpd ; + // + // tmpd = ( fabs(Asy3) > 1.e-5 ) ? Asy3*2.e-3 : 2.e-8; + // double dn_asymY = (yBar < 0 ) ? + // ( getCorrection(CaloFutureCorrection::asymM , cellID , Asy2 + tmpd , 0.) - ddcY )/tmpd : + // ( getCorrection(CaloFutureCorrection::asymP , cellID , Asy2 + tmpd , 0.) - ddcY )/tmpd ; + // // ------------------------------------------------------------------------------------------------------------------------------- + + + // calculation of the analytic derivatives: + // NB: printouts comparing analytic calculations with numeric derivatives which are commented-out below + // are useful for debugging in case of changes in the correction function code + if ( UNLIKELY(msgLevel( MSG::DEBUG)) ) + debug() << "---------- analytic derivatives of individual S-correction functions ---------------" << endmsg; + + double DshapeX = getCorrectionDerivative(CaloFutureCorrection::shapeX , cellID , Asx0 , 1. ); + double DshapeY = getCorrectionDerivative(CaloFutureCorrection::shapeY , cellID , Asy0 , 1. ); + + + double DangularX = getCorrectionDerivative(CaloFutureCorrection::angularX , cellID , thx , 0.); + double DangularY = getCorrectionDerivative(CaloFutureCorrection::angularY , cellID , thy , 0.); + + double DresidualX = getCorrectionDerivative((residualX_flag ? CaloFutureCorrection::residualX : CaloFutureCorrection::residual), cellID , Asx2 , 0.); + double DresidualY = getCorrectionDerivative((residualY_flag ? CaloFutureCorrection::residualY : CaloFutureCorrection::residual), cellID , Asy2 , 0.); + + double DasymX = (xBar < 0 ) ? + getCorrectionDerivative(CaloFutureCorrection::asymM , cellID , Asx3 , 0.): + getCorrectionDerivative(CaloFutureCorrection::asymP , cellID , Asx3 , 0.); + double DasymY = (yBar < 0 ) ? + getCorrectionDerivative(CaloFutureCorrection::asymM , cellID , Asy3 , 0.): + getCorrectionDerivative(CaloFutureCorrection::asymP , cellID , Asy3 , 0.); + + double tx = xs / z; + double ty = ys / z; + + results->dXhy_dXcl = (1. + DasymX) * (1. - DresidualX) *(1. + DangularX*CellSize/z/(1.+tx*tx)) * DshapeX; + results->dYhy_dYcl = (1. + DasymY) * (1. - DresidualY) *(1. + DangularY*CellSize/z/(1.+ty*ty)) * DshapeY; + } +} diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSCorrection.h b/CaloFuture/CaloFutureReco/src/CaloFutureSCorrection.h new file mode 100644 index 0000000000000000000000000000000000000000..5b95f303ede0c59b0929db879b34d38baa337bae --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSCorrection.h @@ -0,0 +1,65 @@ +#ifndef CALOFUTURERECO_CALOFUTURESCORRECTION_H +#define CALOFUTURERECO_CALOFUTURESCORRECTION_H 1 +// Include files +// Include files +#include <string> +#include "CaloFutureInterfaces/ICaloFutureHypoTool.h" +#include "CaloFutureCorrectionBase.h" +#include "GaudiKernel/Counters.h" + +/** @class CaloFutureSCorrection CaloFutureSCorrection.h + * + * + * @author Deschamps Olivier + * @date 2003-03-10 + */ + +class CaloFutureSCorrection : + public virtual ICaloFutureHypoTool , + public CaloFutureCorrectionBase{ +public: + + StatusCode process ( LHCb::CaloHypo* hypo ) const override; + StatusCode operator() ( LHCb::CaloHypo* hypo ) const override; + +public: + + StatusCode initialize() override; + StatusCode finalize() override; + + CaloFutureSCorrection ( const std::string& type , + const std::string& name , + const IInterface* parent ) ; + +private: + + /// input variables calculated once in process() and passed to all calcSCorrection() calls + struct SCorrInputParams { + LHCb::CaloCellID cellID; + Gaudi::XYZPoint seedPos; + double z; + }; + + /// Jacobian elements returned from calcSCorrection() to process() + struct SCorrOutputParams { + double dXhy_dXcl; + double dYhy_dYcl; + }; + + + /// calculate corrected CaloHypo position depending on CaloCluster position + void calcSCorrection( double xBar, double yBar, double &xCor, double &yCor, + const struct SCorrInputParams ¶ms, + struct SCorrOutputParams *results ) const; + +private: + using IncCounter = Gaudi::Accumulators::Counter<>; + using SCounter = Gaudi::Accumulators::StatCounter<float>; + using MapOfCounters = std::map<std::string, SCounter >; + + mutable IncCounter m_counterSkipNegativeEnergyCorrection{this, "Skip negative energy correction"}; + mutable SCounter m_counterDeltaX{this, "Delta(X)"}; + mutable SCounter m_counterDeltaY{this, "Delta(Y)"}; +}; +// ============================================================================ +#endif // CALOFUTURERECO_CALOFUTURESCORRECTION_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelectChargedClusterWithSpd.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureSelectChargedClusterWithSpd.cpp new file mode 100644 index 0000000000000000000000000000000000000000..84eddea30292fe871ba4862358581d52b026f3fb --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelectChargedClusterWithSpd.cpp @@ -0,0 +1,37 @@ +// ============================================================================ +#include "CaloFutureSelectClusterWithSpd.h" +// ============================================================================ +/** @class CaloFutureSelectChargedClusterWithSpd + * Simple seleclton of newural clusters based on Spd information + * @author Olivier Deschamps + * @author Vanya BELYAEV + */ +// ============================================================================ + +class CaloFutureSelectChargedClusterWithSpd : public CaloFutureSelectClusterWithSpd +{ +public: + // ========================================================================== + bool select ( const LHCb::CaloCluster* cluster ) const override + { return (*this) ( cluster ) ; } + // ========================================================================== + bool operator()( const LHCb::CaloCluster* cluster ) const override + { + if ( 0 == cluster ) + { + Warning ( "CaloCluster* points to NULL, return false" ); + return false ; // RETURN + } + // + bool sel = cut() < n_hit ( *cluster ) ; + if(counterStat->isVerbose())counter("selected clusters") += (int) sel; + return sel; + } + // ========================================================================== + /// constructor + using CaloFutureSelectClusterWithSpd::CaloFutureSelectClusterWithSpd; + // ========================================================================== +}; +// ============================================================================ +DECLARE_COMPONENT( CaloFutureSelectChargedClusterWithSpd ) +// ============================================================================ diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelectCluster.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureSelectCluster.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fe2b37a30bb0121628978d5f0f2a9e21ca47537c --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelectCluster.cpp @@ -0,0 +1,46 @@ +#include "GaudiKernel/SystemOfUnits.h" +#include "CaloFutureUtils/CaloMomentum.h" +#include "Event/CaloCluster.h" +#include "CaloFutureSelectCluster.h" + +DECLARE_COMPONENT( CaloFutureSelectCluster ) + +// ============================================================================ +CaloFutureSelectCluster::CaloFutureSelectCluster +( const std::string& type, + const std::string& name, + const IInterface* parent) + : GaudiTool (type ,name ,parent) +{ + declareInterface<ICaloFutureClusterSelector> (this); +} +// ============================================================================ + +StatusCode CaloFutureSelectCluster::initialize (){ + StatusCode sc = GaudiTool::initialize () ; + return sc; +} + +bool CaloFutureSelectCluster::select( const LHCb::CaloCluster* cluster ) const +{ + return (*this) (cluster); +} + +bool CaloFutureSelectCluster::operator()( const LHCb::CaloCluster* cluster) const +{ + if ( 0 == cluster ) { Warning ( "CaloCluster* points to NULL!" ).ignore() ; return false ; } + + double e = cluster->e(); + LHCb::CaloMomentum moment = LHCb::CaloMomentum(cluster); + double et = moment.momentum().Pt(); + int m = cluster->entries().size(); + + if( UNLIKELY(msgLevel( MSG::DEBUG) ))debug() << "Cluster has " << m << " entries " + << " for a total energy of " << e << "(Et = " << et << ")" << endmsg; + + bool isSelected = (e>m_cut) && (m < m_mult) && (et > m_etCut) && (m > m_multMin); + if (isSelected ) { + ++m_counter; + } + return isSelected; +} diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelectCluster.h b/CaloFuture/CaloFutureReco/src/CaloFutureSelectCluster.h new file mode 100644 index 0000000000000000000000000000000000000000..237ed64f9d1649954e6dbfb2fa65a7f285474579 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelectCluster.h @@ -0,0 +1,33 @@ +// +// ============================================================================ +#ifndef CALOFUTURERECO_CALOFUTURESELECTCLUSTER_H +#define CALOFUTURERECO_CALOFUTURESELECTCLUSTER_H 1 +// ============================================================================ +#include <string> +#include "GaudiAlg/GaudiTool.h" +#include "CaloFutureInterfaces/ICaloFutureClusterSelector.h" +#include "GaudiKernel/Counters.h" +// ============================================================================ + +class CaloFutureSelectCluster : + public virtual ICaloFutureClusterSelector, + public GaudiTool +{ +public: + + bool select( const LHCb::CaloCluster* cluster ) const override; + virtual bool operator()( const LHCb::CaloCluster* cluster ) const override; + StatusCode initialize () override; + + CaloFutureSelectCluster( const std::string& type, + const std::string& name, + const IInterface* parent); + +private: + Gaudi::Property<float> m_cut {this, "MinEnergy", 0.}; + Gaudi::Property<float> m_etCut {this, "MinEt", 0.}; + Gaudi::Property<int> m_mult {this, "MaxDigits", 9999}; + Gaudi::Property<int> m_multMin {this, "MinDigits", -9999}; + mutable Gaudi::Accumulators::Counter<> m_counter{this, "selected clusters"}; +}; +#endif // CALOFUTURERECO_CALOFUTURESELECTCLUSTER_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelectClusterWithPrs.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureSelectClusterWithPrs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9b77cfa36a8f33783af5749c604e3204b08eb7e0 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelectClusterWithPrs.cpp @@ -0,0 +1,49 @@ +#include "GaudiKernel/SystemOfUnits.h" +#include "CaloFutureSelectClusterWithPrs.h" + +DECLARE_COMPONENT( CaloFutureSelectClusterWithPrs ) + +// ============================================================================ +CaloFutureSelectClusterWithPrs::CaloFutureSelectClusterWithPrs +( const std::string& type , + const std::string& name , + const IInterface* parent ) + : GaudiTool ( type , name , parent ) +{ + declareInterface<ICaloFutureClusterSelector> ( this ) ; +} +// ============================================================================ + +StatusCode CaloFutureSelectClusterWithPrs::initialize (){ + // initialize the base class + StatusCode sc = GaudiTool::initialize () ; + // + m_toPrs = tool<ICaloFutureHypo2CaloFuture>("CaloFutureHypo2CaloFuture", "CaloFutureHypo2Prs"); + m_toPrs->setCalos(m_det,"Prs"); + counterStat = tool<IFutureCounterLevel>("FutureCounterLevel"); + return sc; +} + +// ============================================================================ +/** @brief "select" method + * + * Cluster is considered to be "selected" if there are Spd/Prs hit in front + * + */ +// ============================================================================ +bool CaloFutureSelectClusterWithPrs::select( const LHCb::CaloCluster* cluster ) const{ +return (*this) ( cluster ); +} +// ============================================================================ +bool CaloFutureSelectClusterWithPrs::operator()( const LHCb::CaloCluster* cluster ) const{ + // check the cluster + if ( 0 == cluster ) { Warning ( "CaloCluster* points to NULL!" ).ignore() ; return false ; } + double ePrs = m_toPrs->energy( *cluster, "Prs"); + int mPrs = m_toPrs->multiplicity(); + if ( UNLIKELY(msgLevel( MSG::DEBUG) ))debug() << "Found " << mPrs << "Prs hits " + << " for a total energy of " << ePrs << endmsg; + + bool sel = (ePrs>m_cut) && (mPrs>m_mult) ; + if(counterStat->isVerbose())counter("selected clusters") += (int) sel; + return sel; +} diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelectClusterWithPrs.h b/CaloFuture/CaloFutureReco/src/CaloFutureSelectClusterWithPrs.h new file mode 100644 index 0000000000000000000000000000000000000000..44b824da266e24c0f47e95c522dfb40b3323d644 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelectClusterWithPrs.h @@ -0,0 +1,33 @@ +// ============================================================================ +#ifndef CALOFUTURERECO_CALOFUTURESELECTCLUSTERWITHPRS_H +#define CALOFUTURERECO_CALOFUTURESELECTCLUSTERWITHPRS_H 1 +// ============================================================================ +#include <string> +#include "GaudiAlg/GaudiTool.h" +#include "CaloFutureInterfaces/ICaloFutureClusterSelector.h" +#include "CaloFutureInterfaces/ICaloFutureHypo2CaloFuture.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" +// ============================================================================ + +class CaloFutureSelectClusterWithPrs : + public virtual ICaloFutureClusterSelector , + public GaudiTool +{ +public: + + bool select( const LHCb::CaloCluster* cluster ) const override; + bool operator()( const LHCb::CaloCluster* cluster ) const override; + StatusCode initialize() override; + + CaloFutureSelectClusterWithPrs( const std::string& type , + const std::string& name , + const IInterface* parent ); + +private: + Gaudi::Property<float> m_cut {this, "MinEnergy", -10. *Gaudi::Units::MeV}; + Gaudi::Property<float> m_mult {this, "MinMultiplicity", 0.}; + ICaloFutureHypo2CaloFuture* m_toPrs = nullptr; + Gaudi::Property<std::string> m_det {this, "Detector", "Ecal"}; + IFutureCounterLevel* counterStat = nullptr; +}; +#endif // CALOFUTURERECO_CALOFUTURESELECTCLUSTERWITHPRS_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelectClusterWithSpd.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureSelectClusterWithSpd.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7e7ebe0b90863585cb7d2454c593ea803d450890 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelectClusterWithSpd.cpp @@ -0,0 +1,41 @@ +// ============================================================================ +// Include files +// ============================================================================ +// Local +// ============================================================================ +#include "CaloFutureSelectClusterWithSpd.h" +// ============================================================================ +/** @file + * Implementation file for class CaloFutureSelectClusterWithSpd + * @date 2009-07-18 + * @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl + */ +// ============================================================================ +// standard constructor +// ============================================================================ +CaloFutureSelectClusterWithSpd::CaloFutureSelectClusterWithSpd +( const std::string& type , + const std::string& name , + const IInterface* parent ) + : GaudiTool ( type , name , parent ) +{ + declareInterface<ICaloFutureClusterSelector> ( this ) ; +} +// ============================================================================ +// initialization +// ============================================================================ +StatusCode CaloFutureSelectClusterWithSpd::initialize () +{ + // initialize the base class + StatusCode sc = GaudiTool::initialize () ; + m_toSpd = tool<ICaloFutureHypo2CaloFuture> ( "CaloFutureHypo2CaloFuture", "CaloFutureHypo2Spd" , this ); + m_toSpd->setCalos( m_det,"Spd"); + counterStat = tool<IFutureCounterLevel>("FutureCounterLevel"); + return sc ; +} +// ============================================================================ +// the main method +// ============================================================================ +int CaloFutureSelectClusterWithSpd::n_hits( const LHCb::CaloCluster& cluster ) const +{ return m_toSpd->multiplicity ( cluster, "Spd" ) ; } + diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelectClusterWithSpd.h b/CaloFuture/CaloFutureReco/src/CaloFutureSelectClusterWithSpd.h new file mode 100644 index 0000000000000000000000000000000000000000..b30eec41e9e58e37a50c2261ae6729b808a46341 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelectClusterWithSpd.h @@ -0,0 +1,68 @@ +// ============================================================================ +#ifndef CALOFUTURESELECTCLUSTERWITHSPD_H +#define CALOFUTURESELECTCLUSTERWITHSPD_H 1 +// ============================================================================ +// Include files +// ============================================================================ +// GaudiAlg +// ============================================================================ +#include "GaudiAlg/GaudiTool.h" +// ============================================================================ +// CaloFutureInterfaces +// ============================================================================ +#include "CaloFutureInterfaces/ICaloFutureClusterSelector.h" +#include "CaloFutureInterfaces/ICaloFutureHypo2CaloFuture.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" +// ============================================================================ +/** @class CaloFutureSelectClusterWithSpd + * Helper base class for "cluster selectioin with Spd" tools + * + * @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl + * @date 2009-07-18 + */ +// ============================================================================ +class CaloFutureSelectClusterWithSpd : + public virtual ICaloFutureClusterSelector , + public GaudiTool +{ +public: + // ========================================================================== + /// initialize the tool + StatusCode initialize() override; + // ========================================================================== +public: + // ========================================================================== + /// number of hits in SPD + int n_hits ( const LHCb::CaloCluster& cluster ) const ; + /// number of hits in SPD + int n_hit ( const LHCb::CaloCluster& cluster ) const + { return n_hits ( cluster ) ; } + // ========================================================================== + /// standard constructor + CaloFutureSelectClusterWithSpd + ( const std::string& type , + const std::string& name , + const IInterface* parent ) ; + // ========================================================================== +protected: + // ========================================================================== + /// get number of hits + int cut () const { return m_cut ; } + /// get the tool + ICaloFutureHypo2CaloFuture* calo2calo () const { return m_toSpd ; } + /// get the calorimeter + const std::string& det() const { return m_det ; } + IFutureCounterLevel* counterStat = nullptr; + // ========================================================================== +private: + // ========================================================================== + /// number of hits in spd + Gaudi::Property<int> m_cut {this, "MinMultiplicity", 0, "number of hits in spd "}; + /// Calo -> Calo tool + ICaloFutureHypo2CaloFuture* m_toSpd = nullptr; + /// Calorimeter + Gaudi::Property<std::string> m_det {this, "Detector", "Ecal"}; + // ========================================================================== +}; +#endif // CALOFUTURESELECTCLUSTERWITHSPD_H +// ============================================================================ diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelectNeutralClusterWithSpd.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureSelectNeutralClusterWithSpd.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9b1b6aa0cf5a30a220e764fa0fecb9bbcfc6df35 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelectNeutralClusterWithSpd.cpp @@ -0,0 +1,39 @@ +// ============================================================================ +// Local +// ============================================================================ +#include "CaloFutureSelectClusterWithSpd.h" +// ============================================================================ +/** @class CaloFutureSelectNsutralClusterWithSpd + * Simple seleclton of newural clusters based on Spd information + * @author Olivier Deschamps + * @author Vanya BELYAEV + */ +// ============================================================================ +class CaloFutureSelectNeutralClusterWithSpd : public CaloFutureSelectClusterWithSpd +{ +public: + // ========================================================================== + bool select ( const LHCb::CaloCluster* cluster ) const override + { return (*this) ( cluster ) ; } + // ========================================================================== + bool operator()( const LHCb::CaloCluster* cluster ) const override + { + if ( 0 == cluster ) + { + Warning ( "CaloCluster* points to NULL, return false" ); + return false ; // RETURN + } + // + + bool sel = cut() >= n_hit ( *cluster ) ; + if(counterStat->isVerbose())counter("selected clusters") += (int) sel; + return sel; + } + // ========================================================================== + /// constructor + using CaloFutureSelectClusterWithSpd::CaloFutureSelectClusterWithSpd; + // ========================================================================== +}; +// ============================================================================ +DECLARE_COMPONENT( CaloFutureSelectNeutralClusterWithSpd ) +// ============================================================================ diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelectNeutralClusterWithTracks.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureSelectNeutralClusterWithTracks.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eb32794ac61a5c5b29de4e6dc783af4e9c39c5aa --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelectNeutralClusterWithTracks.cpp @@ -0,0 +1,106 @@ +// ============================================================================ +//CaloFutureUtils +#include "CaloFutureUtils/CaloFuture2Track.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +// local +#include "CaloFutureSelectNeutralClusterWithTracks.h" + +// ============================================================================ +/** @file + * + * implementation file for class CaloFutureSelectNeutralClusterWithTracks + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 26 Apr 2002 + */ +// ============================================================================ + +DECLARE_COMPONENT( CaloFutureSelectNeutralClusterWithTracks ) + +// ============================================================================ +/** Standard constructor + * @see GaudiTool + * @see AlgTool + * @see IAlgTool + * @param type tool type (?) + * @param name name of the concrete instance + * @param parent pointer to the parent + */ +// ============================================================================ +CaloFutureSelectNeutralClusterWithTracks::CaloFutureSelectNeutralClusterWithTracks +( const std::string& type , + const std::string& name , + const IInterface* parent ) + : GaudiTool ( type , name , parent ) +{ + declareInterface<ICaloFutureClusterSelector> (this) ; + m_tableLocation = LHCb::CaloFutureAlgUtils::CaloFutureIdLocation( "ClusterMatch", context() ); +} + +// ============================================================================ +/** standard initialization method + * @see GaudiTool + * @see AlgTool + * @see IAlgTool + * @return status code + */ +// ============================================================================ +StatusCode +CaloFutureSelectNeutralClusterWithTracks::initialize () +{ + // initialize the base class + StatusCode sc = GaudiTool::initialize () ; + if( sc.isFailure() ) + {return Error("Could not initialize the base class GaudiTool!",sc); } + m_tables = tool<ICaloFutureRelationsGetter>("CaloFutureRelationsGetter","CaloFutureRelationsGetter",this); + return StatusCode::SUCCESS ; +} + +// ============================================================================ +/** @brief "select" method + * + * Cluster is considered to be "selected" + * if there are no reconstructed tracks with + * chi2 value for 2D-matching under the threshold value + * + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ +// ============================================================================ +bool CaloFutureSelectNeutralClusterWithTracks::select +( const LHCb::CaloCluster* cluster ) const +{ return (*this) ( cluster ); } +// ============================================================================ + +// ============================================================================ +/** @brief "select" method (functor interface) + * + * Cluster is considered to be "selected" + * if there are no reconstructed tracks with + * chi2 value for 2D-matching under the threshold value + * + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ +// ============================================================================ +bool CaloFutureSelectNeutralClusterWithTracks::operator() + ( const LHCb::CaloCluster* cluster ) const +{ + // check the cluster + if ( 0 == cluster ) { Warning ( "CaloCluster* points to NULL!" ).ignore() ; return false ; } + + // locate the table + LHCb::CaloFuture2Track::IClusTrTable* table = m_tables->getClusTrTable( m_tableLocation ); + if( NULL == table )return true; + + // get all relations with WEIGHT = 'chi2' under the threshold value + const LHCb::CaloFuture2Track::IClusTrTable::Range range = table -> relations ( cluster , m_chi2cut , false ) ; + + bool isSelected = range.empty(); + if (isSelected ) { + ++m_counter; + } + return isSelected; +} diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelectNeutralClusterWithTracks.h b/CaloFuture/CaloFutureReco/src/CaloFutureSelectNeutralClusterWithTracks.h new file mode 100644 index 0000000000000000000000000000000000000000..14d64c0b18e1674fc05abb347d872c7a83744c32 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelectNeutralClusterWithTracks.h @@ -0,0 +1,93 @@ +// ===================================================q========================= +#ifndef CALOFUTURERECO_CALOFUTURESELECTNEUTRALCLUSTERWITHTRACKS_H +#define CALOFUTURERECO_CALOFUTURESELECTNEUTRALCLUSTERWITHTRACKS_H 1 +// ============================================================================ +// Include files +#include "Relations/IRelationWeighted.h" +// from STL +#include <string> +// CaloFutureInterfaces +#include "CaloFutureInterfaces/ICaloFutureClusterSelector.h" +#include "CaloFutureInterfaces/ICaloFutureRelationsGetter.h" +// GaudiAlg +#include "GaudiAlg/GaudiTool.h" +//Event +#include "Event/CaloCluster.h" +#include "Event/Track.h" +#include "GaudiKernel/Counters.h" +// ============================================================================ + +/** @class CaloFutureSelectNeutralClusterWithTracks CaloFutureSelectNeutralClusterWithTracks.h + * + * Concrete tool, which select the Neutral clusters + * (photon candidates) looking through the relation table + * of 2D-matched CaloClusters and Tracks + * + * Cluster is considered to be "selected" + * if there are no reconstructed tracks with + * chi2 value for 2D-matching under the threshold value + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 26/04/2002 + */ +class CaloFutureSelectNeutralClusterWithTracks : + public virtual ICaloFutureClusterSelector , + public GaudiTool +{ +public: + + /** @brief "select" method + * + * Cluster is considered to be "selected" + * if there are no reconstructed tracks with + * chi2 value for 2D-matching under the threshold value + * + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ + bool select + ( const LHCb::CaloCluster* cluster ) const override; + + /** @brief "select" method (functor interface) + * + * Cluster is considered to be "selected" + * if there are no reconstructed tracks with + * chi2 value for 2D-matching under the threshold value + * + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ + bool operator() + ( const LHCb::CaloCluster* cluster ) const override; + + /** standard initialization method + * @see GaudiTool + * @see AlgTool + * @see IAlgTool + * @return status code + */ + StatusCode initialize() override; + + /** Standard constructor + * @see GaudiTool + * @see AlgTool + * @see IAlgTool + * @param type tool type (?) + * @param name name of the concrete instance + * @param parent pointer to the parent + */ + CaloFutureSelectNeutralClusterWithTracks + ( const std::string& type , + const std::string& name , + const IInterface* parent ); + +private: + + Gaudi::Property<std::string> m_tableLocation {this, "Table", LHCb::CaloFutureIdLocation::ClusterMatch}; + Gaudi::Property<float> m_chi2cut {this, "MinChi2", -100}; + ICaloFutureRelationsGetter* m_tables = nullptr; + mutable Gaudi::Accumulators::Counter<> m_counter{this, "selected clusters"}; +}; +#endif // CALOFUTURERECO_CALOFUTURESELECTNEUTRALCLUSTERWITHTRACKS_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelector.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureSelector.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e2ba4e8c688a449c9e60749707d01a8180de8ad3 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelector.cpp @@ -0,0 +1,98 @@ +// ============================================================================ +// Include files +// CaloFutureInterfaces +#include "CaloFutureInterfaces/ICaloFutureLikelihood.h" +// local +#include "CaloFutureSelector.h" + +// ============================================================================ +/** @file CaloFutureSelector.cpp + * + * Implementation file for class : CaloFutureSelector + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 31/03/2002 + */ +// ============================================================================ + +DECLARE_COMPONENT( CaloFutureSelector ) + +// ============================================================================ +/** Standard constructor + * @param type tool type (?) + * @param name tool name + * @param parent tool parent + */ +// ============================================================================ +CaloFutureSelector::CaloFutureSelector( const std::string& type , + const std::string& name , + const IInterface* parent ) + : GaudiTool ( type, name , parent ) +{ + // interfaces + declareInterface<ICaloFutureClusterSelector> (this); +} + +// ============================================================================ +/** standard initialization of the tool + * @see IAlgTool + * @see AlgTool + * @see GaudiTool + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureSelector::initialize() +{ + // initialialize the base class + StatusCode sc = GaudiTool::initialize() ; + if( sc.isFailure() ) + { return Error("Could not initialize the base class GaudiTool!",sc);} + /// locate the tool + m_likelihood = m_lhName.empty() ? + tool<ICaloFutureLikelihood>( m_lhType , this ) : + tool<ICaloFutureLikelihood>( m_lhType , m_lhName , this ) ; + if( 0 == m_likelihood ) { return StatusCode::FAILURE ; } + // + return StatusCode::SUCCESS ; +} + +// ============================================================================ +/** standard finalization of the tool + * @see IAlgTool + * @see AlgTool + * @see GaudiTool + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureSelector::finalize() +{ + ///finalize the base class + return GaudiTool::finalize() ; +} + +// ============================================================================ +/** "select"/"preselect" method (functor interface) + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ +// ============================================================================ +bool CaloFutureSelector::operator() ( const LHCb::CaloCluster* cluster ) const +{ + if( 0 == cluster ) { return false ; } + return m_cut <= (*m_likelihood) (cluster) ; +} + +// ============================================================================ +/** "select"/"preselect" method + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ +// ============================================================================ +bool CaloFutureSelector::select ( const LHCb::CaloCluster* cluster ) const +{ return (*this) ( cluster ); } + +// ============================================================================ +// The End +// ============================================================================ diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelector.h b/CaloFuture/CaloFutureReco/src/CaloFutureSelector.h new file mode 100644 index 0000000000000000000000000000000000000000..a8c1e51d5eb039ec2ac4fd0ccc2a857628bba30e --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelector.h @@ -0,0 +1,92 @@ +#ifndef CALOFUTURERECO_CALOFUTURESELECTOR_H +#define CALOFUTURERECO_CALOFUTURESELECTOR_H 1 +// Include files +// from STL +#include <string> +// from GaudiAlg +#include "GaudiAlg/GaudiTool.h" +// from CaloFutureInterfaces +#include "CaloFutureInterfaces/ICaloFutureClusterSelector.h" +// forward declaratiosn +struct ICaloFutureLikelihood ; // from CaloFutureInterfaces ; + +/** @class CaloFutureSelector CaloFutureSelector.h + * + * Concrete cluster-selector tool, to select CaloFutureClusters + * which satisfy the given calorimeter hypothesis + * Tool in turn uses the tool with ICaloFutureLikelihood + * interaface to calculate the likelihood. + * @see ICaloFutureClusterSelector + * @see ICaloFutureLikelyhood + * @see CaloCluster + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 31/03/2002 + */ +class CaloFutureSelector : + public virtual ICaloFutureClusterSelector , + public GaudiTool +{ +public: + + /** "select"/"preselect" method + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ + bool select ( const LHCb::CaloCluster* cluster ) const override; + + /** "select"/"preselect" method (functor interface) + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ + bool operator() ( const LHCb::CaloCluster* cluster ) const override; + + /** standard initialization of the tool + * @see IAlgTool + * @see AlgTool + * @see GaudiTool + * @return status code + */ + StatusCode initialize() override; + + /** standard finalization of the tool + * @see IAlgTool + * @see AlgTool + * @see GaudiTool + * @return status code + */ + StatusCode finalize() override; + + /** Standard constructor + * @param type tool type (?) + * @param name tool name + * @param parent tool parent + */ + CaloFutureSelector + ( const std::string& type , + const std::string& name , + const IInterface* parent ); + +private: + + // type of Likelyhood tool to be used + Gaudi::Property<std::string> m_lhType + {this, "LikelihoodType", "", "type of Likelyhood tool to be used"}; + + // name of Likelyhood tool to be used + Gaudi::Property<std::string> m_lhName + {this, "LikelihoodName", "", "name of Likelyhood tool to be used"}; + + // Likelyhood tool to be used + ICaloFutureLikelihood* m_likelihood = nullptr; + + // cut on likelyhood + Gaudi::Property<double> m_cut {this, "LikelihoodCut", 1.e+50, "cut on likelyhood"}; + +}; + +// ============================================================================ +#endif // CALOFUTURERECO_CALOFUTURESELECTOR_H +// ============================================================================ diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelectorAND.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureSelectorAND.cpp new file mode 100644 index 0000000000000000000000000000000000000000..830a61ae015f9b29b112895cd1689a024a4d6ec3 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelectorAND.cpp @@ -0,0 +1,103 @@ +// ============================================================================ +// Include files +// ============================================================================ +// Local +// ============================================================================ +#include "CaloFutureSelectorAND.h" +// ============================================================================ +/** @file + * + * Implementation file for class : CaloFutureSelectorAND + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 27 Apr 2002 + */ +// ============================================================================ +DECLARE_COMPONENT( CaloFutureSelectorAND ) +// ============================================================================ +/* Standard constructor + * @see GaudiTool + * @see AlgTool + * @see IAlgTool + * @param type tool type (?) + * @param name tool name + * @param parent tool parent + */ +// ============================================================================ +CaloFutureSelectorAND::CaloFutureSelectorAND +( const std::string& type, + const std::string& name, + const IInterface* parent ) + : GaudiTool ( type, name , parent ) +{ + declareInterface<ICaloFutureClusterSelector> (this); +} +// ============================================================================ +/* standard initialization of the tool + * @see IAlgTool + * @see AlgTool + * @see GaudiTool + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureSelectorAND::initialize () +{ + // initialize the base class + StatusCode sc = GaudiTool::initialize() ; + if( sc.isFailure() ) + { return Error("Could not initialize the base class GaudiTool",sc);} + // locate selectors + std::transform( m_selectorsTypeNames.begin(), m_selectorsTypeNames.end(), + std::back_inserter(m_selectors), + [&](const std::string& name) + { return tool<ICaloFutureClusterSelector>( name, this ); } ); + /// + return StatusCode::SUCCESS ; +} +// ============================================================================ +/* standard finalization of the tool + * @see IAlgTool + * @see AlgTool + * @see GaudiTool + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureSelectorAND::finalize () +{ + // clear containers + m_selectors .clear() ; + m_selectorsTypeNames .clear() ; + // finalize the base class + return GaudiTool::finalize () ; +} +// ============================================================================ + +// ============================================================================ +/** "select"/"preselect" method + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ +// ============================================================================ +bool CaloFutureSelectorAND::select +( const LHCb::CaloCluster* cluster ) const { return (*this) ( cluster ) ; } +// ============================================================================ + +// ============================================================================ +/** "select"/"preselect" method (functor interface) + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ +// ============================================================================ +bool CaloFutureSelectorAND::operator() ( const LHCb::CaloCluster* cluster ) const +{ + // no selectors! + if( m_selectors.empty() ) { return false ; } // note: this is not what std::all_of does for an empty range! + return std::all_of( m_selectors.begin(), m_selectors.end(), + [&](Selectors::const_reference s) + { return (*s)(cluster); } ); +} +// ============================================================================ +// The END +// ============================================================================ diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelectorAND.h b/CaloFuture/CaloFutureReco/src/CaloFutureSelectorAND.h new file mode 100644 index 0000000000000000000000000000000000000000..32eb5de49483d9f65746c49e2d76c7c27293b6b7 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelectorAND.h @@ -0,0 +1,99 @@ +#ifndef CALOFUTURERECO_CALOFUTURESELECTORAND_H +#define CALOFUTURERECO_CALOFUTURESELECTORAND_H +// Include files +// from STL +#include <string> +// from GaudiAlg +#include "GaudiAlg/GaudiTool.h" +// From CaloFutureInterfaces +#include "CaloFutureInterfaces/ICaloFutureClusterSelector.h" + +/** @class CaloFutureSelectorAND CaloFutureSelectorAND.h + * + * Helper concrete tool for selection of calocluster objects + * This selector selects the cluster if + * all of its daughter selector select it! + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 27/04/2002 + */ +class CaloFutureSelectorAND : + public virtual ICaloFutureClusterSelector , + public GaudiTool +{ +public: + /// container of types&names + typedef std::vector<std::string> Names ; + /// container of selectors + typedef std::vector<ICaloFutureClusterSelector*> Selectors ; + +public: + + /** "select"/"preselect" method + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ + bool select + ( const LHCb::CaloCluster* cluster ) const override; + + /** "select"/"preselect" method (functor interface) + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ + bool operator () + ( const LHCb::CaloCluster* cluster ) const override; + + /** standard initialization of the tool + * @see IAlgTool + * @see AlgTool + * @see GaudiTool + * @return status code + */ + StatusCode initialize() override; + + /** standard finalization of the tool + * @see IAlgTool + * @see AlgTool + * @see GaudiTool + * @return status code + */ + StatusCode finalize() override; + + /** Standard constructor + * @see GaudiTool + * @see AlgTool + * @see IAlgTool + * @param type tool type (?) + * @param name tool name + * @param parent tool parent + */ + CaloFutureSelectorAND + ( const std::string& type, + const std::string& name, + const IInterface* parent); + +private: + + /// default constructor is private + CaloFutureSelectorAND(); + /// copy constructor is private + CaloFutureSelectorAND + (const CaloFutureSelectorAND& ); + /// assignement operator is private + CaloFutureSelectorAND& operator= + (const CaloFutureSelectorAND& ); + +private: + + Gaudi::Property<Names> m_selectorsTypeNames {this, "SelectorTools"}; + Selectors m_selectors; + +}; + +// ============================================================================ +// The END +// ============================================================================ +#endif // CALOFUTURERECO_CALOFUTURESELECTORAND_H +// ============================================================================ diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelectorNOT.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureSelectorNOT.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cbe3530784811ce033bb2d7e1c67d5c460dcce01 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelectorNOT.cpp @@ -0,0 +1,107 @@ +// ============================================================================ +// Include files +// ============================================================================ +// local +#include "CaloFutureSelectorNOT.h" +// ============================================================================ +/** @file + * + * Implementation file for class : CaloFutureSelectorNOT + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 27 Apr 2002 + */ +// ============================================================================ +DECLARE_COMPONENT( CaloFutureSelectorNOT ) +// ============================================================================ +/* StNOTard constructor + * @see GaudiTool + * @see AlgTool + * @see IAlgTool + * @param type tool type (?) + * @param name tool name + * @param parent tool parent + */ +// ============================================================================ +CaloFutureSelectorNOT::CaloFutureSelectorNOT +( const std::string& type, + const std::string& name, + const IInterface* parent ) + : GaudiTool ( type, name, parent ) +{ + declareInterface<ICaloFutureClusterSelector> (this); +} +// ============================================================================ +/* stNOTard initialization of the tool + * @see IAlgTool + * @see AlgTool + * @see GaudiTool + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureSelectorNOT::initialize () +{ + // initialize the base class + StatusCode sc = GaudiTool::initialize() ; + if ( sc.isFailure() ) { + return Error("Could not initialize the base class GaudiTool", sc); + } + // locate selectors + for ( Names::const_iterator it = m_selectorsTypeNames.begin() ; + m_selectorsTypeNames.end() != it ; ++it ) { + ICaloFutureClusterSelector* selector = tool<ICaloFutureClusterSelector>( *it, this ); + m_selectors.push_back( selector ); + }; + /// + return StatusCode::SUCCESS ; +} +// ============================================================================ +/* stNOTard finalization of the tool + * @see IAlgTool + * @see AlgTool + * @see GaudiTool + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureSelectorNOT::finalize () +{ + // clear containers + m_selectors .clear() ; + m_selectorsTypeNames .clear() ; + // finalize the base class + return GaudiTool::finalize () ; +} +// ============================================================================ +/* "select"/"preselect" method + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ +// ============================================================================ +bool CaloFutureSelectorNOT::select( const LHCb::CaloCluster* cluster ) const +{ + return (*this) (cluster); +} +// ============================================================================ +/* "select"/"preselect" method (functor interface) + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ +// ============================================================================ +bool CaloFutureSelectorNOT::operator() ( const LHCb::CaloCluster* cluster ) const +{ + bool notSelected = false ; + for ( Selectors::const_iterator selector = m_selectors.begin() ; + !notSelected && m_selectors.end() != selector ; ++selector ) { + notSelected = (**selector)( cluster ); + } + if (!notSelected) { + ++m_counter; + } + return !notSelected; +} + + + + diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelectorNOT.h b/CaloFuture/CaloFutureReco/src/CaloFutureSelectorNOT.h new file mode 100644 index 0000000000000000000000000000000000000000..44b85c625fa08ce814e9b34b13dc8c53b2b5a6a4 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelectorNOT.h @@ -0,0 +1,64 @@ +#ifndef CALOFUTURERECO_CALOFUTURESELECTORNOT_H +#define CALOFUTURERECO_CALOFUTURESELECTORNOT_H 1 +// Include files +// from STL +#include <string> +// from GaudiAlg +#include "GaudiAlg/GaudiTool.h" +#include "GaudiKernel/Counters.h" +// From CaloFutureInterfaces +#include "CaloFutureInterfaces/ICaloFutureClusterSelector.h" +/** @class CaloFutureSelectorNOT CaloFutureSelectorNOT.h + * + * Helper concrete tool for selection of calocluster objects + * This selector selects the cluster if + * none of its daughter selector select it! + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 27/04/2002 + */ +class CaloFutureSelectorNOT : + public virtual ICaloFutureClusterSelector, + public GaudiTool +{ +public: + using Names = std::vector<std::string>; + using Selectors= std::vector<ICaloFutureClusterSelector*>; + using IncCounter = Gaudi::Accumulators::Counter<>; + + /** "select"/"preselect" method + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ + bool select + (const LHCb::CaloCluster* cluster) const override; + + /** "select"/"preselect" method (functor interface) + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ + bool operator () + ( const LHCb::CaloCluster* cluster ) const override; + + StatusCode initialize() override; + StatusCode finalize() override; + + /** StNOTard constructor + * @param type tool type + * @param name tool name + * @param parent tool parent + */ + CaloFutureSelectorNOT + (const std::string& type, + const std::string& name, + const IInterface* parent); + +private: + Gaudi::Property<Names> m_selectorsTypeNames {this, "SelectorTools"}; + Selectors m_selectors; + mutable IncCounter m_counter{this, "selected clusters"}; +}; +// ============================================================================ +#endif // CALOFUTURERECO_CALOFUTURESELECTORNOT_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelectorOR.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureSelectorOR.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d3baea35ebc157ef02c14ddee01999374c429a44 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelectorOR.cpp @@ -0,0 +1,97 @@ +// ============================================================================ +// Include files +// ============================================================================ +// local +// ============================================================================ +#include "CaloFutureSelectorOR.h" +// ============================================================================ +/** @file + * + * Implementation file for class : CaloFutureSelectorOR + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 27 Apr 2002 + */ +// ============================================================================ +DECLARE_COMPONENT( CaloFutureSelectorOR ) +// ============================================================================ +/* Standard constructor + * @see GaudiTool + * @see AlgTool + * @see IAlgTool + * @param type tool type (?) + * @param name tool name + * @param parent tool parent + */ +// ============================================================================ +CaloFutureSelectorOR::CaloFutureSelectorOR +( const std::string& type, + const std::string& name, + const IInterface* parent ) + : GaudiTool ( type, name , parent ) +{ + declareInterface<ICaloFutureClusterSelector> (this); +} +// ============================================================================ +/* standard initialization of the tool + * @see IAlgTool + * @see AlgTool + * @see GaudiTool + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureSelectorOR::initialize () +{ + // initialize the base class + StatusCode sc = GaudiTool::initialize() ; + if( sc.isFailure() ) + { return Error("Could not initialize the base class GaudiTool",sc);} + // locate selectors + std::transform( m_selectorsTypeNames.begin(), m_selectorsTypeNames.end(), + std::back_inserter(m_selectors), + [&](const std::string& name) + { return tool<ICaloFutureClusterSelector>( name, this ); } ); + /// + return StatusCode::SUCCESS ; +} +// ============================================================================ +/* standard finalization of the tool + * @see IAlgTool + * @see AlgTool + * @see GaudiTool + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureSelectorOR::finalize () +{ + // clear containers + m_selectors .clear() ; + m_selectorsTypeNames .clear() ; + // finalize the base class + return GaudiTool::finalize () ; +} +// ============================================================================ +/* "select"/"preselect" method + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ +// ============================================================================ +bool CaloFutureSelectorOR::select +( const LHCb::CaloCluster* cluster ) const { return (*this) ( cluster ) ; } +// ============================================================================ +/** "select"/"preselect" method (functor interface) + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ +// ============================================================================ +bool CaloFutureSelectorOR::operator() ( const LHCb::CaloCluster* cluster ) const +{ + return std::any_of( m_selectors.begin(), m_selectors.end(), + [&](typename Selectors::const_reference s) + { return (*s)(cluster); } ); +} +// ============================================================================ +// The END +// ============================================================================ diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSelectorOR.h b/CaloFuture/CaloFutureReco/src/CaloFutureSelectorOR.h new file mode 100644 index 0000000000000000000000000000000000000000..3d4888fbeecc02201ef0268717e1f7bfa30a32f9 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSelectorOR.h @@ -0,0 +1,99 @@ +#ifndef CALOFUTURERECO_CALOFUTURESELECTOROR_H +#define CALOFUTURERECO_CALOFUTURESELECTOROR_H 1 +// Include files +// from STL +#include <string> +// from GaudiAlg +#include "GaudiAlg/GaudiTool.h" +// From CaloFutureInterfaces +#include "CaloFutureInterfaces/ICaloFutureClusterSelector.h" + +/** @class CaloFutureSelectorOR CaloFutureSelectorOR.h + * + * Helper concrete tool for selection of calocluster objects + * This selector selects the cluster if + * at least one of its daughter selector select it! + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 27/04/2002 + */ +class CaloFutureSelectorOR : + public virtual ICaloFutureClusterSelector , + public GaudiTool +{ +public: + /// container of types&names + typedef std::vector<std::string> Names ; + /// container of selectors + typedef std::vector<ICaloFutureClusterSelector*> Selectors ; + +public: + + /** "select"/"preselect" method + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ + bool select + ( const LHCb::CaloCluster* cluster ) const override; + + /** "select"/"preselect" method (functor interface) + * @see ICaloFutureClusterSelector + * @param cluster pointer to calo cluster object to be selected + * @return true if cluster is selected + */ + bool operator () + ( const LHCb::CaloCluster* cluster ) const override; + + /** standard initialization of the tool + * @see IAlgTool + * @see AlgTool + * @see GaudiTool + * @return status code + */ + StatusCode initialize() override; + + /** standard finalization of the tool + * @see IAlgTool + * @see AlgTool + * @see GaudiTool + * @return status code + */ + StatusCode finalize() override; + + /** Standard constructor + * @see GaudiTool + * @see AlgTool + * @see IAlgTool + * @param type tool type (?) + * @param name tool name + * @param parent tool parent + */ + CaloFutureSelectorOR + ( const std::string& type, + const std::string& name, + const IInterface* parent); + +private: + + /// default constructor is private + CaloFutureSelectorOR(); + /// copy constructor is private + CaloFutureSelectorOR + (const CaloFutureSelectorOR& ); + /// assignement operator is private + CaloFutureSelectorOR& operator= + (const CaloFutureSelectorOR& ); + +private: + + Gaudi::Property<Names> m_selectorsTypeNames {this, "SelectorTools"}; + Selectors m_selectors; + +}; + +// ============================================================================ +// The END +// ============================================================================ +#endif // CALOFUTURERECO_CALOFUTURESELECTOROR_H +// ============================================================================ diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSharedCellAlg.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureSharedCellAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e55adfe5e9d6167e2cb5875e83b024fe0632cb9c --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSharedCellAlg.cpp @@ -0,0 +1,174 @@ +// =========================================================================== +// Include files +// from GaudiKernel +#include "GaudiKernel/MsgStream.h" +// CaloFutureGen +#include "CaloKernel/CaloException.h" +//LHCb Kernel +#include "GaudiKernel/SystemOfUnits.h" +// CaloFutureEvent +#include "Event/CaloCluster.h" +#include "Event/CaloDigit.h" +// CaloFutureUtils +#include "CaloFutureUtils/Digit2ClustersConnector.h" +#include "CaloFutureUtils/ClusterFunctors.h" +#include "CaloFutureUtils/SharedCells.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +// local +#include "CaloFutureSharedCellAlg.h" + +// ============================================================================ +/** @file CaloFutureSharedCellAlg.cpp + * + * Implementation file for class : CaloFutureSharedCellAlg + * + * @see CaloFutureSharedCellAlg + * @see Digit2ClustersConnector + * @see SharedCells + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 30/06/2001 + */ +// ============================================================================ + +DECLARE_COMPONENT( CaloFutureSharedCellAlg ) + +// ============================================================================ +// Standard creator, initializes variables +// ============================================================================ +CaloFutureSharedCellAlg::CaloFutureSharedCellAlg( const std::string& name, + ISvcLocator* pSvcLocator) + : GaudiAlgorithm ( name , pSvcLocator ) +{ + // set default data as a function of detector + m_detData= LHCb::CaloFutureAlgUtils::DeCaloFutureLocation( name ) ; + m_inputData = LHCb::CaloFutureAlgUtils::CaloFutureClusterLocation( name , context() ); +} + +// ============================================================================ +// Initialisation. Check parameters +// ============================================================================ +StatusCode CaloFutureSharedCellAlg::initialize() +{ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "==> Initialise" << endmsg; + /// + StatusCode sc = GaudiAlgorithm::initialize(); + /// + if( sc.isFailure() ) + { return Error("could not initialize base class GaudiAlgorithm!");} + + /// copy mode ? + m_copy = (!m_outputData.empty()) && (m_outputData.value() != m_inputData.value()); + + counterStat = tool<IFutureCounterLevel>("FutureCounterLevel"); + return StatusCode::SUCCESS; +} + +// ============================================================================ +// Main execution +// ============================================================================ +StatusCode CaloFutureSharedCellAlg::execute() +{ + // avoid long names + using namespace SharedCells ; + using namespace LHCb::CaloDigitStatus ; + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "==> Execute" << endmsg; + // + + // useful typedefs + typedef LHCb::CaloClusters Clusters ; + typedef const DeCalorimeter Detector ; + + // locate input data + Clusters* clusters = get<Clusters>( m_inputData ); + if( 0 == clusters ) { return StatusCode::FAILURE ; } + + // locate geometry (if needed) + Detector* detector = 0; + if( m_useDistance ) + { + detector = getDet<DeCalorimeter> ( m_detData ); + if( 0 == detector ){ return StatusCode::FAILURE ;} + } + + Clusters* output = 0; + if( m_copy ) ///< make a new container + { + output = new Clusters(); + put( output , m_outputData ); + // make a copy + for ( const LHCb::CaloCluster* i : *clusters ) + { if( i ) { output->insert( new LHCb::CaloCluster{ *i }); } } + } + else { output = clusters; } ///< update existing sequence + + /** build inverse connection table/object + * keep only digits which have connections + * with 2 clusters and more! + */ + const unsigned int cutOff = 2 ; + typedef Digit2ClustersConnector Table; + Table table; + StatusCode scc = table.load( output->begin() , output->end () , cutOff ) ; + if(scc.isFailure())warning()<<"Unable to load the table"<<endmsg; + + // sort digit by energy in order the subsequent processing is pointer address independent ! + std::vector<const LHCb::CaloDigit*> reOrder; + for( Table::Map::iterator entry = table.map().begin() ; table.map().end() != entry ; ++entry ){ + const LHCb::CaloDigit* dig = entry->first ; + reOrder.push_back( dig ); + } + std::stable_sort( reOrder.begin(), reOrder.end () ,LHCb::CaloDataFunctor::inverse( LHCb::CaloDataFunctor::Less_by_Energy ) ) ; + + + /// loop over all digits in the table + for( std::vector<const LHCb::CaloDigit*>::const_iterator idig = reOrder.begin() ; reOrder.end() != idig ; ++idig ){ + Table::Map::iterator entry = table.map().find( *idig ); + if( entry == table.map().end() ) continue; + const LHCb::CaloDigit* dig = entry->first ; + /// ignore artificial zeros + if( 0 == dig ) { continue; } + + StatusCode sc = StatusCode::SUCCESS; + if ( m_useSumEnergy && !m_useDistance ){ + sc = summedEnergyAlgorithm ( entry->second , m_numIterations ) ; // do not apply weights at this stage + } + else if ( !m_useSumEnergy && !m_useDistance ){ + sc = seedEnergyAlgorithm( entry->second , SeedCell ) ; + } + else if ( m_useSumEnergy && m_useDistance ){ + sc = summedDistanceAlgorithm( entry->second , + detector , + dig->cellID() , + m_showerSizes , + m_numIterations ) ; + } + else if ( !m_useSumEnergy && m_useDistance ){ + sc = seedDistanceAlgorithm( entry->second , + detector , + SeedCell , + dig->cellID() , + m_showerSizes ) ; + } + else { return Error("Funny condition :-)) "); } + /// + if( sc.isFailure() ){ return Error("Could not redistribute the energy!"); } + } + + + if(counterStat->isQuiet())counter ( "#Clusters from '" + m_inputData +"'") += clusters->size() ; + + /// + return StatusCode::SUCCESS; + /// +} + +StatusCode CaloFutureSharedCellAlg::finalize() { + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "==> Finalize" << endmsg; + + return GaudiAlgorithm::finalize(); // must be called after all other actions +} + + diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSharedCellAlg.h b/CaloFuture/CaloFutureReco/src/CaloFutureSharedCellAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..604a6797b4fecf4e4a6eb7d1af9a89a3b5f77129 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSharedCellAlg.h @@ -0,0 +1,87 @@ +#ifndef CALOFUTURERECO_CALOFUTURESHAREDCELLALG_H +#define CALOFUTURERECO_CALOFUTURESHAREDCELLALG_H 1 +// ============================================================================ +// Include files +// CaloDet +#include "CaloDet/DeCalorimeter.h" +// CaloFutureEvent/Event +#include "Event/CaloCluster.h" +// from GaudiAlg +#include "GaudiAlg/GaudiAlgorithm.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" + +/** @class CaloFutureSharedCellAlg CaloFutureSharedCellAlg.h + * + * A very simple algorithm, which performs the + * energy redistribution + * between shared cells + * + * @author Ivan Belyaev + * @date 30/06/2001 + */ + +class CaloFutureSharedCellAlg : public GaudiAlgorithm +{ +public: + + /** standard initialization method + * @see CaloFutureAlgorithm + * @see Algorithm + * @see IAlgorithm + * @return status code + */ + StatusCode initialize() override; + StatusCode finalize() override; + + /** standard execution method + * @see CaloFutureAlgorithm + * @see Algorithm + * @see IAlgorithm + * @return status code + */ + StatusCode execute() override; + + /** Standard constructor + * @param name name of the algorithm + * @param pSvcLocator poinetr to Service Locator + */ + CaloFutureSharedCellAlg + ( const std::string& name , + ISvcLocator* pSvcLocator ); + +private: + + bool m_copy = true; ///< copy flag + + Gaudi::Property<bool> m_useSumEnergy + {this, "ShareSumEnergy", true, + "should one use the summed cluster energy or central cell energy?"}; + + Gaudi::Property<int> m_numIterations + {this, "Iterations", 5, + "number of iterations iif one use summed cluster energy"}; + + Gaudi::Property<bool> m_useDistance + {this, "ShareDistance", false, + "should one take into account the the distance?"}; + + Gaudi::Property<std::vector<double>> m_showerSizes + {this, "ShowerSizes", { + 0.1090 * 121.50 * Gaudi::Units::mm, + 0.1326 * 60.75 * Gaudi::Units::mm, + 0.1462 * 40.50 * Gaudi::Units::mm, + }, "shower size parameters (for different areas)"}; + + Gaudi::Property<std::string> m_inputData + {this, "InputData", LHCb::CaloClusterLocation::Ecal}; + + Gaudi::Property<std::string> m_outputData + {this, "OutputData"}; + + Gaudi::Property<std::string> m_detData + {this, "Detector", DeCalorimeterLocation::Ecal}; + + IFutureCounterLevel* counterStat = nullptr; +}; +// ============================================================================ +#endif // CALOFUTURESHAREDCELLALG_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlap.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlap.cpp new file mode 100644 index 0000000000000000000000000000000000000000..54c20f464c6610e50c9e42a6989ee363342f73fc --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlap.cpp @@ -0,0 +1,99 @@ +// Include files + + // from Gaudi +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +// local +#include "CaloFutureShowerOverlap.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : CaloFutureShowerOverlap +// +// 2014-06-02 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( CaloFutureShowerOverlap ) + + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +CaloFutureShowerOverlap::CaloFutureShowerOverlap( const std::string& name, + ISvcLocator* pSvcLocator) +: GaudiAlgorithm ( name , pSvcLocator ) +{ + m_input = LHCb::CaloFutureAlgUtils::CaloFutureClusterLocation( name , context() ); + m_det = LHCb::CaloFutureAlgUtils::DeCaloFutureLocation( name ) ; +} + +//============================================================================= +// Initialization +//============================================================================= +StatusCode CaloFutureShowerOverlap::initialize() { + StatusCode sc = GaudiAlgorithm::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; // error printed already by GaudiAlgorithm + + if ( msgLevel(MSG::DEBUG) ) debug() << "==> Initialize" << endmsg; + + m_oTool = tool<ICaloFutureShowerOverlapTool>("CaloFutureShowerOverlapTool","PhotonShowerOverlap",this); + m_tagger = tool<FutureSubClusterSelectorTool>( "FutureSubClusterSelectorTool" , "EcalClusterTag" , this ); + + m_detector = getDet<DeCalorimeter> ( m_det ); + return StatusCode::SUCCESS; +} + +//============================================================================= +// Main execution +//============================================================================= +StatusCode CaloFutureShowerOverlap::execute() { + + if ( UNLIKELY(msgLevel(MSG::DEBUG) ) )debug() << "==> Execute" << endmsg; + LHCb::CaloDataFunctor::EnergyTransverse<const DeCalorimeter*> eT(m_detector); + + // locate data + LHCb::CaloClusters* clusters = get<LHCb::CaloClusters>( m_input ); + if( 0 == clusters ) { return StatusCode::FAILURE ; } + + LHCb::CaloDigits* spds = getIfExists<LHCb::CaloDigits>( LHCb::CaloDigitLocation::Spd ); + + for( LHCb::CaloClusters::iterator i1 = clusters->begin() ; clusters->end() != i1 ; ++i1 ){ + double et1 = eT( *i1 ); + if( et1 < m_etMin )continue; // neglect overlap from/to low ET clusters + const LHCb::CaloCellID id1=(*i1)->seed(); + const LHCb::CaloDigit* spd1 = (spds == NULL) ? NULL : spds->object( (*i1)->seed() ); + for( LHCb::CaloClusters::iterator i2 = i1+1 ; clusters->end() != i2 ; ++i2 ){ + double et2=eT( *i2 ); + if( et2 < m_etMin )continue; // neglect overlap from/to low ET clusters + if( et1 < m_etMin2 && et2 < m_etMin2 )continue; // require at least one cluster above threshold (speed-up) + const LHCb::CaloCellID id2=(*i2)->seed(); + if( id1.area() != id2.area() ) continue; + if( abs( int(id1.col()) - int(id2.col()) ) > m_dMin || abs( int(id1.row()) - int(id2.row()) ) > m_dMin )continue; + const LHCb::CaloDigit* spd2 = (spds == NULL) ? NULL : spds->object( (*i2)->seed() ); + int s1= (spd1 == NULL) ? 0 : int(spd1->e() > 0.) ; + int s2= (spd2 == NULL) ? 0 : int(spd2->e() > 0.) ; + + + // initial weights for shared cells + LHCb::CaloCluster* cl1 = *i1; + LHCb::CaloCluster* cl2 = *i2; + for( LHCb::CaloCluster::Entries::iterator e1 = cl1->entries().begin() ; cl1->entries().end() != e1 ; ++e1 ){ + for( LHCb::CaloCluster::Entries::iterator e2 = cl2->entries().begin() ; cl2->entries().end() != e2 ; ++e2 ){ + if( e1->digit()->cellID() == e2->digit()->cellID() ){ + const auto totE = ( cl1->e() + cl2->e() ); + e1->setFraction( cl1->e() / totE ); + e2->setFraction( cl2->e() / totE ); + } + } + } + // tag the cluster position to have correct corrections + const StatusCode sc = StatusCode{ m_tagger->tagPosition( cl1 ) && + m_tagger->tagPosition( cl2 ) }; + if( sc.isFailure() )Warning("Cluster tagging failed - keep the initial 3x3 tagging").ignore(); + // correct entry weight for shower overlap (assuming EM cluster) + m_oTool->process(*i1,*i2, s1*10+s2, m_iter); + } + } + return StatusCode::SUCCESS; +} + +//============================================================================= diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlap.h b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlap.h new file mode 100644 index 0000000000000000000000000000000000000000..5178b641b8d67aec777b0c370a871741e1823943 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlap.h @@ -0,0 +1,50 @@ +#ifndef CALOFUTURESHOWEROVERLAP_H +#define CALOFUTURESHOWEROVERLAP_H 1 + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiAlgorithm.h" +#include "Event/CaloDataFunctor.h" +#include "Event/CellID.h" +#include "FutureSubClusterSelectorTool.h" +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureInterfaces/ICaloFutureShowerOverlapTool.h" +#include "Event/CaloCluster.h" + +/** @class CaloFutureShowerOverlap CaloFutureShowerOverlap.h + * + * + * @author Olivier Deschamps + * @date 2014-06-02 + */ +class CaloFutureShowerOverlap : public GaudiAlgorithm +{ + +public: + + /// Standard constructor + CaloFutureShowerOverlap( const std::string& name, ISvcLocator* pSvcLocator ); + + StatusCode initialize() override; ///< Algorithm initialization + StatusCode execute() override; ///< Algorithm execution + +private: + + Gaudi::Property<int> m_dMin {this, "DistanceThreshold", 4}; + Gaudi::Property<float> m_etMin {this, "MinEtThreshold", 50., "( ET1 > x && ET2 > x)"}; + Gaudi::Property<float> m_etMin2 {this, "MaxEtThreshold", 150., "( ET2 > y || ET2 > y)"}; + Gaudi::Property<int> m_iter {this, "Iterations", 5}; + Gaudi::Property<std::string> m_input {this, "InputData", LHCb::CaloClusterLocation::Ecal}; + Gaudi::Property<std::string> m_det {this, "Detector" , DeCalorimeterLocation::Ecal}; + + // following properties are inherited by the selector tool when defined : + Gaudi::Property<std::vector<std::string>> m_taggerP {this, "PositionTags"}; + Gaudi::Property<std::vector<std::string>> m_taggerE {this, "EnergyTags"}; + + const DeCalorimeter* m_detector = nullptr ; + ICaloFutureShowerOverlapTool* m_oTool = nullptr ; + FutureSubClusterSelectorTool* m_tagger = nullptr ; + +}; + +#endif // CALOFUTURESHOWEROVERLAP_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..afec30f4a49ebd61ff9effc496a56e882cbefc4f --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.cpp @@ -0,0 +1,302 @@ +// Include files + +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "Event/CaloDataFunctor.h" +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureUtils/CaloMomentum.h" + +// local +#include "CaloFutureShowerOverlapTool.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : CaloFutureShowerOverlapTool +// +// 2014-06-02 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( CaloFutureShowerOverlapTool ) + + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +CaloFutureShowerOverlapTool::CaloFutureShowerOverlapTool( const std::string& type, + const std::string& name, + const IInterface* parent ) +: GaudiTool ( type, name , parent ) +{ + declareInterface<ICaloFutureShowerOverlapTool>(this); + + // define type from instance name + const std::string uName ( LHCb::CaloFutureAlgUtils::toUpper( name ) ) ; + if ( uName.find( "MERGED" ) != std::string::npos || uName.find( "SPLITPHOTON" ) != std::string::npos )m_type = "SplitPhoton"; + else if ( uName.find( "PHOTON" ) )m_type="Photon"; + else m_type="Photon"; // the default +} + +//============================================================================= + +StatusCode CaloFutureShowerOverlapTool::initialize() { + StatusCode sc = GaudiTool::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; // error printed already by GaudiAlgorithm + if ( UNLIKELY(msgLevel(MSG::DEBUG)) ) debug() << "==> Initialize" << endmsg; + m_det = getDet<DeCalorimeter> ( m_detLoc ); + + m_shape = tool<CaloFutureCorrectionBase>("CaloFutureCorrectionBase","ShowerProfile",this); + m_stool = tool<ICaloFutureHypoTool>("CaloFutureSCorrection",m_type+"SCorrection",this); + m_ltool = tool<ICaloFutureHypoTool>("CaloFutureLCorrection",m_type+"LCorrection",this); + counterStat = tool<IFutureCounterLevel>("FutureCounterLevel"); + sc = setProfile(m_pcond); + return sc; +} + +//============================================================================= + +StatusCode CaloFutureShowerOverlapTool::setProfile(std::string prof){ + m_pcond=prof; + StatusCode sc = m_shape->setConditionParams(m_pcond,true); + return sc; +} + +void CaloFutureShowerOverlapTool::storeInitialWeights(const LHCb::CaloCluster* cl1,const LHCb::CaloCluster* cl2){ + m_weights.clear(); + std::map<LHCb::CaloCellID,double> weights; + for( const auto& i1 : cl1->entries() ) { + weights[i1.digit()->cellID()]=i1.fraction(); + //info() << " part1 " << i1.digit()->cellID() << " : " << i1.fraction() << endmsg; + } + for( const auto& i2 : cl2->entries()) { + LHCb::CaloCellID id2=i2.digit()->cellID(); + auto it = weights.find(id2); + //info() << " part2 " << i2.digit()->cellID() << " : " << i2.fraction() << endmsg; + if( it == weights.end() ) weights[ id2 ]=i2.fraction(); + else{ + it->second += i2.fraction(); + } + } + // check + for( const auto& it : weights ) { + if( it.second == 1.) continue; + m_weights[it.first]=it.second; + //info() << "storing weight " << it.first << " : " << it.second << endmsg; + } + //info() << " Stored weights " << m_weights.size() << endmsg; +} + +double CaloFutureShowerOverlapTool::getInitialWeight(const LHCb::CaloCellID id){ + if( m_weights.empty() ) return 1.; + auto it = m_weights.find(id); + return it != m_weights.end() ? it->second : 1. ; +} + + + +void CaloFutureShowerOverlapTool::process(const LHCb::CaloCluster* cl1 , const LHCb::CaloCluster* cl2 , + int spd, int niter,bool propagateInitialWeights){ + + if( cl1->entries().size() < m_minSize || cl2->entries().size() < m_minSize ){ + if(counterStat->isQuiet())counter("Overlap correction skipped due to cluster size") += 1; + return; // skip small clusters + } + + m_a1=cl1->seed().area(); + m_a2=cl2->seed().area(); + m_s1= spd / 10 ; + m_s2= spd % 10 ; + + m_weights.clear(); // clear initial weights + if( propagateInitialWeights )storeInitialWeights(cl1,cl2); + + // 0 - evaluate parameters (applying photon hypo corrections for the position) + LHCb::CaloCluster* w1 = (LHCb::CaloCluster*) cl1; + LHCb::CaloCluster* w2 = (LHCb::CaloCluster*) cl2; + evaluate(w1); + evaluate(w2); + + if( w1->e() <= 0. || w2->e() <= 0){ + if(counterStat->isQuiet())counter("Overlap correction skipped due to cluster energy") += 1; + return; + } + + if( m_verbose ){ + info() << " ======== Shower Overlap =======" << endmsg; + info() << " CL1/CL2 : " << cl1->e() << " " << cl2->e() << " " << cl1->e()+cl2->e()<< endmsg; + info() << " seed : " << cl1->seed() << " " << cl2->seed() << endmsg; + info() << " area : " << m_a1 << " " << m_a2 << endmsg; + info() << " Spd : " << spd << " " << m_s1 << " " << m_s2 << endmsg; + info() << " params : " << cl1->position().parameters() << " / " << cl2->position().parameters() << endmsg; + } + + int iter = 0; + + // 1 - determine the energy fractions of each entry + while( iter < niter ){ + + if( m_verbose )info() << " ------ iter = " << iter << endmsg; + + subtract(w1,w2,propagateInitialWeights); + + if( m_verbose )info() << " >> CL1/CL2 : " << w1->e() << " " << w2->e() << " " << w1->e() + w2->e() << endmsg; + if( m_verbose )info() << " >> params : " << w1->position().parameters() << " / " << w2->position().parameters() << endmsg; + // + if( m_verbose ){ + LHCb::CaloMomentum momentum; + momentum.addCaloPosition(w1); + momentum.addCaloPosition(w2); + //info() << " >> Mass : " << momentum.mass() << endmsg; + } + + iter++; + } + // 3 - reset cluster-like parameters + evaluate(w1,false); + evaluate(w2,false); + +} + + +double CaloFutureShowerOverlapTool::fraction(LHCb::CaloCluster* cluster, LHCb::CaloDigit* digit,int flag){ + + if( digit == NULL)return 1.; + const LHCb::CaloCellID cellID=digit->cellID(); + + + double size = m_det->cellSize( cellID ) ; + double xd = m_det->cellX ( cellID ) ; + double yd = m_det->cellY ( cellID ) ; + double xc = cluster->position().parameters()( LHCb::CaloPosition::Index::X ); + double yc = cluster->position().parameters()( LHCb::CaloPosition::Index::Y ); + double zc = cluster->position().z(); + double zd = (xc*xc + yc*yc + zc*zc - xc*xd - yc* yd )/zc; + double d3d = std::sqrt( (xd - xc)*(xd - xc ) + + (yd - yc)*(yd - yc ) + + (zd - zc)*(zd - zc ) )/size; + int area = (flag == 1) ? m_a1 : m_a2; + int spd = (flag == 1) ? m_s1 : m_s2; + double f = showerFraction( d3d, area, spd ); + double ed = digit->e(); + double ec = f * cluster->position().parameters()( LHCb::CaloPosition::Index::E ); + double frac= (ed > ec ) ? (ed - ec )/ ed : 0.; + + // info() << " --> Digit : " << cellID << " fraction : " << frac << endmsg; + return frac; +} + + + +void CaloFutureShowerOverlapTool::subtract(LHCb::CaloCluster* cl1, LHCb::CaloCluster* cl2,bool propagateInitialWeight){ + + // cluster1 -> cluster2 spillover + //info() << " --- 1st cluster overlap ----- " << cl1->seed() << endmsg; + for( auto& i2 : cl2->entries() ) { + if( (LHCb::CaloDigitStatus::UseForEnergy & i2.status())==0 && + (LHCb::CaloDigitStatus::UseForPosition & i2.status())==0 )continue; + double initialWeight = propagateInitialWeight ? getInitialWeight( i2.digit()->cellID() ) : 1.; + i2.setFraction( fraction( cl1, i2.digit() , 1)*initialWeight ); + //info() << "cl1 -> 2 : " << i2.digit()->cellID() << " " << i2.digit()->e() << " " << i2.fraction() << endmsg; + } + + // re-evaluate cluster2 accordingly + evaluate(cl2); + if( cl2->e() < 0)return; // skip negative energy "clusters" + + //info() << " --- 2nd cluster overlap ----- " << cl2->seed() << endmsg; + // cluster2 -> cluster1 spillover + for( auto& i1 : cl1->entries() ) { + const LHCb::CaloDigit* dig1 = i1.digit(); + if( (LHCb::CaloDigitStatus::UseForEnergy & i1.status()) ==0 && + (LHCb::CaloDigitStatus::UseForPosition & i1.status())==0 )continue; + double initialWeight = propagateInitialWeight ? getInitialWeight( i1.digit()->cellID() ) : 1.; + i1.setFraction( fraction( cl2, i1.digit() , 2)*initialWeight ); + //info() << "cl2 -> 1 : " << i1.digit()->cellID() << " " << i1.digit()->e() << " " << i1.fraction() << endmsg; + double eps = 1.e-4; + // normalize the sum of partial weights in case of shared cells + for( auto& i2 : cl2->entries()) { + const LHCb::CaloDigit* dig2 = i2.digit(); + if( !(dig2->cellID() == dig1->cellID()) )continue; + if( (LHCb::CaloDigitStatus::UseForEnergy & i2.status())==0 && + (LHCb::CaloDigitStatus::UseForPosition & i2.status())==0 )continue; + double f1 = i1.fraction(); + double f2 = i2.fraction(); + double sum = f1 + f2 ; + if( fabs( sum - initialWeight) > eps ){ + if( sum < initialWeight && f2 == 0. )i2.setFraction( initialWeight - f1 ); + else if ( sum < initialWeight && f1 == 0.)i1.setFraction (initialWeight - f2); + else{ + i1.setFraction( initialWeight*f1/(f1+f2) ); + i2.setFraction( initialWeight*f2/(f1+f2) ); + } + //info() << " -> SHARED " << f1 << " -> " << i1.fraction() << " | " << f2 << " -> " << i2.fraction() << " => " << i1.fraction()+i2.fraction() << endmsg; + } + } + } + + // reevaluate cluster1 & 2 accordingly + evaluate(cl1); + evaluate(cl2); + +} + +double CaloFutureShowerOverlapTool::showerFraction(double d3d, unsigned int area ,int spd){ + LHCb::CaloCellID cellID(2,area,0,0); //fake cell + double frac = m_shape->getCorrection( spd ? CaloFutureCorrection::profileC + : CaloFutureCorrection::profile, cellID , d3d ,0.) ; + return std::max( 0., std::min( frac, 1. ) ); +} + +void CaloFutureShowerOverlapTool::evaluate(LHCb::CaloCluster* cluster,bool hypoCorrection){ + + + // 0 - reset z-position of cluster + LHCb::ClusterFunctors::ZPosition zPosition( m_det ); + cluster->position().setZ( zPosition( cluster ) ); + + // 1 - 3x3 energy and energy-weighted barycenter + double E, X, Y; + StatusCode sc = LHCb::ClusterFunctors::calculateEXY( cluster->entries().begin() , + cluster->entries().end () , + m_det , E , X , Y ); + if( sc.isSuccess() ){ + cluster->position().parameters()( LHCb::CaloPosition::Index::E ) = E ; + cluster->position().parameters()( LHCb::CaloPosition::Index::X ) = X ; + cluster->position().parameters()( LHCb::CaloPosition::Index::Y ) = Y ; + } + else{ + if ( UNLIKELY(msgLevel(MSG::DEBUG)) ) debug() << " E,X and Y of cluster could not be evaluated " << endmsg; + if(counterStat->isQuiet())counter("Cluster position failed") += 1; + //Warning( " E,X and Y of cluster could not be evaluated!",StatusCode::SUCCESS,1).ignore(); + } + + + if( cluster->e() < 0)return; // skip correction for negative energy "clusters" + + //------------------------------------------------------------------- + if( !hypoCorrection ) return; // do not apply 'photon' hypo correction + + // 2 - apply 'photon hypothesis' corrections + + // create a fake CaloHypo + LHCb::CaloHypo hypo{}; + hypo.setHypothesis ( LHCb::CaloHypo::Hypothesis::Photon ); + hypo.addToClusters ( cluster ); + hypo.setPosition ( std::make_unique<LHCb::CaloPosition>(cluster->position()) ); + + // Apply transversal corrections + sc=m_stool->process(&hypo); + if( sc.isSuccess() ){ + cluster->position().parameters()( LHCb::CaloPosition::Index::X ) = hypo.position()->parameters()( LHCb::CaloPosition::Index::X) ; + cluster->position().parameters()( LHCb::CaloPosition::Index::Y ) = hypo.position()->parameters()( LHCb::CaloPosition::Index::Y) ; + }else + Error(" SCorrection could not be evaluated!",sc,1).ignore(); + + // Apply longitudinal correction + sc=m_ltool->process(&hypo); + if( sc.isSuccess() ){ + cluster->position().setZ( hypo.position()->z() ); + } else + Error(" LCorrection could not be evaluated!",sc,1).ignore(); + +} + + diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.h b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.h new file mode 100644 index 0000000000000000000000000000000000000000..d301bebdf730b20b360879071d28c22bfa5bbf93 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureShowerOverlapTool.h @@ -0,0 +1,58 @@ +#ifndef CALOFUTURESHOWEROVERLAPTOOL_H +#define CALOFUTURESHOWEROVERLAPTOOL_H 1 + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiTool.h" +#include "CaloDet/DeCalorimeter.h" +#include "Event/CaloCluster.h" +#include "CaloFutureCorrectionBase.h" +#include "CaloFutureInterfaces/ICaloFutureHypoTool.h" +#include "CaloFutureInterfaces/ICaloFutureShowerOverlapTool.h" // Interface +#include "CaloFutureInterfaces/IFutureCounterLevel.h" + + +/** @class CaloFutureShowerOverlapTool CaloFutureShowerOverlapTool.h + * + * + * @author Olivier Deschamps + * @date 2014-06-02 + */ +class CaloFutureShowerOverlapTool : public GaudiTool, virtual public ICaloFutureShowerOverlapTool { +public: + /// Standard constructor + CaloFutureShowerOverlapTool( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + + StatusCode setProfile(std::string) override; + void process(const LHCb::CaloCluster* c1, const LHCb::CaloCluster* c2, + int spd=0, int niter=10,bool propagateInitialWeights=false) override; + +protected: + void storeInitialWeights(const LHCb::CaloCluster* cl1,const LHCb::CaloCluster* cl2); + double getInitialWeight(const LHCb::CaloCellID id); + double fraction(LHCb::CaloCluster* c, LHCb::CaloDigit* d,int flag); + void subtract(LHCb::CaloCluster* c1,LHCb::CaloCluster* c2,bool propagateInitialWeights); + double showerFraction(double d3d,unsigned int area,int spd); + void evaluate(LHCb::CaloCluster* c,bool hypoCorrection = true); +private: + int m_a1 = 0; + int m_a2 = 0; + int m_s1 = 0; + int m_s2 = 0; + Gaudi::Property<std::string> m_detLoc {this, "Detector", DeCalorimeterLocation::Ecal}; + Gaudi::Property<std::string> m_pcond {this, "Profile", "Conditions/Reco/Calo/PhotonShowerProfile"}; + std::string m_type; + const DeCalorimeter* m_det = nullptr; + ICaloFutureHypoTool* m_stool = nullptr; + ICaloFutureHypoTool* m_ltool = nullptr; + CaloFutureCorrectionBase* m_shape = nullptr; + std::map<const LHCb::CaloCellID,double> m_weights; + Gaudi::Property<bool> m_verbose {this, "Verbose", false}; + Gaudi::Property<unsigned int> m_minSize {this, "ClusterMinSize", 2}; + IFutureCounterLevel* counterStat = nullptr; +}; +#endif // CALOFUTURESHOWEROVERLAPTOOL_H diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSinglePhotonAlg.cpp b/CaloFuture/CaloFutureReco/src/CaloFutureSinglePhotonAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e98dd8a171d9f6850834442d0f79a2b988b86f4f --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSinglePhotonAlg.cpp @@ -0,0 +1,156 @@ +// ============================================================================ +// Include files +// ============================================================================ +// STD & STL +// ============================================================================ +#include <algorithm> +// ============================================================================ +#include "GaudiKernel/SystemOfUnits.h" +#include "CaloFutureUtils/CaloFutureDataFunctor.h" +#include "Event/CellID.h" +#include "CaloFutureInterfaces/ICaloFutureClusterSelector.h" +#include "CaloFutureInterfaces/ICaloFutureHypoTool.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "CaloFutureSinglePhotonAlg.h" +#include "CaloFutureUtils/CaloMomentum.h" +// ============================================================================ +/** @file + * + * Implementation file for class : CaloFutureSinglePhotonAlg + * The implementation is based on F.Machefert's codes. + * @see CaloFutureSinglePhotonAlg + * + * @author Frederic Machefert machefer@in2p3.fr + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 31/03/2002 + */ +// ============================================================================ +namespace +{ +template <typename Container, typename Arg, typename Parent> +bool apply(const Container& c, Arg& arg, const char* errmsg, const Parent& parent) +{ + bool r = std::all_of( std::begin(c), std::end(c), + [&](typename Container::const_reference elem) { + return (*elem)(&arg).isSuccess(); + } ); + if (UNLIKELY(!r)) parent.Error( errmsg, StatusCode::FAILURE ).ignore(); + return r; +} +} + +DECLARE_COMPONENT( CaloFutureSinglePhotonAlg ) +// ============================================================================ +/* Standard constructor + * @param name algorithm name + * @param pSvc service locator + */ +// ============================================================================ +CaloFutureSinglePhotonAlg::CaloFutureSinglePhotonAlg ( const std::string& name, + ISvcLocator* pSvc ) + : ScalarTransformer( name, pSvc, + KeyValue("InputData", {}), // note: context can not be used here -- only _after_ the baseclass is initialized! +KeyValue("OutputData", {}) ) +{ + // context() is only available _after_ the baseclass is fully initialized -- so we cannot put + // the 'final' default which uses it as argument to it... + // bit tricky: as these are datahandles, they have multiple options.... what to do with the + // not specified options? -- so we 'hide' the futuredetails inside 'updateHandleLocation' + updateHandleLocation( *this, "InputData", LHCb::CaloFutureAlgUtils::CaloFutureClusterLocation("Ecal", context() )); + updateHandleLocation( *this, "OutputData", LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation("Photons", context() )); + + setProperty ( "PropertiesPrint", true ) ; +} +// ============================================================================ +/* standard Algorithm initialization + * @return status code + */ +// ============================================================================ +StatusCode CaloFutureSinglePhotonAlg::initialize() +{ + StatusCode sc = ScalarTransformer::initialize(); + if ( sc.isFailure() ) { + return Error("Could not initialize the base class!", sc); + } + + // check the geometry information + m_det = getDet<DeCalorimeter>( m_detData ) ; + if ( !m_det ) return Error("Detector information is not available!"); + + m_eT = LHCb::CaloDataFunctor::EnergyTransverse<const DeCalorimeter*> { m_det } ; // TODO: can we combine this into Over_Et_Threshold and make it a property?? + + // locate selector tools + std::transform( m_selectorsTypeNames.begin(), m_selectorsTypeNames.end(), + std::back_inserter(m_selectors), + [&](const std::string & name) { + return this->tool<ICaloFutureClusterSelector>( name, this ); + } ); + if ( m_selectors.empty() )info() << "No Cluster Selection tools are specified!" << endmsg ; + // locate correction tools + std::transform( m_correctionsTypeNames.begin(), m_correctionsTypeNames.end(), + std::back_inserter(m_corrections), + [&](const std::string & name) { + return this->tool<ICaloFutureHypoTool>( name, this ); + } ); + if ( m_corrections.empty() )info() << "No Hypo Correction tools are specified!" << endmsg ; + // locate other hypo tools + std::transform( m_hypotoolsTypeNames.begin(), m_hypotoolsTypeNames.end(), + std::back_inserter(m_hypotools), + [&](const std::string & name) { + return this->tool<ICaloFutureHypoTool>( name, this ); + } ); + if ( m_hypotools.empty() )info() << "No Hypo Processing tools are specified!" << endmsg ; + /// + return StatusCode::SUCCESS; +} + +// ============================================================================ +/* standard Algorithm finalization + * @return status code + */ +// ============================================================================ +StatusCode +CaloFutureSinglePhotonAlg::finalize() +{ + m_selectors.clear () ; + m_corrections.clear () ; + m_hypotools.clear () ; + m_selectorsTypeNames.clear () ; + m_correctionsTypeNames.clear () ; + m_hypotoolsTypeNames.clear () ; + + return ScalarTransformer::finalize() ; +} +// ============================================================================ +// Algorithm execution +// ============================================================================ +boost::optional<LHCb::CaloHypo> +CaloFutureSinglePhotonAlg::operator()(const LHCb::CaloCluster& cluster) const +{ + // loop over all selectors + bool select = ( m_eT(&cluster) >= m_eTcut && + std::all_of(m_selectors.begin(), + m_selectors.end(), + [&] (Selectors::const_reference sel) { + return (*sel)(&cluster); + })); + if ( !select ) return boost::none; + + LHCb::CaloHypo hypo; + + hypo.setHypothesis( LHCb::CaloHypo::Hypothesis::Photon ); + hypo.addToClusters( &cluster ); + hypo.setPosition( std::make_unique<LHCb::CaloPosition>(cluster.position()) ); //@FIXME: why not CaloPosition by (optional) value? + + return boost::make_optional( + apply( m_hypotools, hypo, "Error from Other Hypo Tool, skip the cluster ", *this) && // loop over other hypo tools (e.g. add extra digits) + apply( m_corrections, hypo, "Error from Correction Tool skip the cluster", *this) && // loop over all corrections and apply corrections + LHCb::CaloMomentum(&hypo).pt() >= m_eTcut, // check momentum after all corrections, and insert into container pass... + hypo ); +} + +void CaloFutureSinglePhotonAlg::postprocess(const LHCb::CaloHypos& hypos) const +{ + if (msgLevel(MSG::DEBUG)) debug() << " # of created Photon Hypos is " << hypos.size() << endmsg; + m_counterHypos += hypos.size(); +} diff --git a/CaloFuture/CaloFutureReco/src/CaloFutureSinglePhotonAlg.h b/CaloFuture/CaloFutureReco/src/CaloFutureSinglePhotonAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..ce13d409f72072cf3b377df8c9d5bb88528aaf5c --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CaloFutureSinglePhotonAlg.h @@ -0,0 +1,82 @@ +// ============================================================================ +#ifndef CALOFUTUREALGS_CALOFUTURESINGLEPHOTONALG_H +#define CALOFUTUREALGS_CALOFUTURESINGLEPHOTONALG_H 1 +// ============================================================================ +#include <string> +#include "GaudiAlg/ScalarTransformer.h" +#include "CaloDet/DeCalorimeter.h" +#include "Event/CaloHypo.h" +#include "Event/CaloCluster.h" +#include "GaudiKernel/Counters.h" +struct ICaloFutureClusterSelector; +struct ICaloFutureHypoTool; + +/** @class CaloFutureSinglePhotonAlg CaloFutureSinglePhotonAlg.h + * + * The simplest algorithm of reconstruction of + * single photon in electromagnetic calorimeter. + * The implementation is based on F.Machefert's codes. + * + * @author Frederic Machefert machefer@in2p3.fr + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 31/03/2002 + */ + +class CaloFutureSinglePhotonAlg + : public Gaudi::Functional::ScalarTransformer<CaloFutureSinglePhotonAlg, LHCb::CaloHypos(const LHCb::CaloClusters&)> +{ +public: + CaloFutureSinglePhotonAlg( const std::string& name, ISvcLocator* pSvc ); + + StatusCode initialize () override; + StatusCode finalize () override; + + using ScalarTransformer::operator(); + boost::optional<LHCb::CaloHypo> operator()(const LHCb::CaloCluster& ) const; + void postprocess(const LHCb::CaloHypos&) const; + +private: + + /// container of names + typedef std::vector<std::string> Names; + /// container of selector tools + typedef std::vector<ICaloFutureClusterSelector*> Selectors; + /// containers of hypo tools + typedef std::vector<ICaloFutureHypoTool*> HypoTools; + /// container of correction tools (S-,L-,...) + typedef HypoTools Corrections; + + Selectors m_selectors; + Gaudi::Property<Names> m_selectorsTypeNames { + this, "SelectionTools", { + "CaloFutureSelectCluster/PhotonCluster", + "CaloFutureSelectNeutralClusterWithTracks/NeutralCluster" + }, "List of tools for selection of clusters"}; + + HypoTools m_hypotools; + Gaudi::Property<Names> m_hypotoolsTypeNames { + this, "HypoTools", + { "CaloFutureExtraDigits/SpdPrsExtraG" }, + "List of generic Hypo-tools to apply to newly created hypos"}; + + Corrections m_corrections; + Gaudi::Property<Names> m_correctionsTypeNames { + this, "CorrectionTools2", { + "CaloFutureECorrection/ECorrection", + "CaloFutureSCorrection/SCorrection", + "CaloFutureLCorrection/LCorrection", + }, "List of tools for 'fine-corrections' "}; + + Gaudi::Property<std::string> m_detData + {this, "Detector", LHCb::CaloFutureAlgUtils::DeCaloFutureLocation("Ecal")}; + + Gaudi::Property<double> m_eTcut + {this, "EtCut", 0., "Threshold on cluster & hypo ET"}; + + LHCb::CaloDataFunctor::EnergyTransverse<const DeCalorimeter*> m_eT { nullptr } ; // TODO: can we combine this into Over_Et_Threshold and make it a property?? + + const DeCalorimeter* m_det = nullptr; + mutable Gaudi::Accumulators::StatCounter<> m_counterHypos{this, "hyposNumber"}; +}; +// ============================================================================ +#endif // CALOFUTURESINGLEPHOTONALG_H diff --git a/CaloFuture/CaloFutureReco/src/CelAutoTaggedCell.h b/CaloFuture/CaloFutureReco/src/CelAutoTaggedCell.h new file mode 100644 index 0000000000000000000000000000000000000000..6e7bdcd75be782af81691c9f8adb8fd843c12099 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/CelAutoTaggedCell.h @@ -0,0 +1,109 @@ +// ============================================================================ +#ifndef CALOFUTURECA_CELAUTOTAGGEDCEL_H +#define CALOFUTURECA_CELAUTOTAGGEDCEL_H 1 +// ============================================================================ +// Include files +// ============================================================================ +// STD & STL +// ============================================================================ +#include <vector> +// ============================================================================ +// Kernel +// ============================================================================ +#include "GaudiKernel/SystemOfUnits.h" +#include "Kernel/CaloCellID.h" +// ============================================================================ +/** @class CelAutoTaggedCell CelAutoTaggedCell.h + * + * Object Tagged Cell + * + * @author Nicole Brun + * @date 27/02/2001 + */ +// ============================================================================ +class CelAutoTaggedCell final +{ + // ========================================================================== +public: + // ========================================================================== + enum Tag + { + DefaultFlag , + Clustered , + Edge + }; + + enum FlagState + { + NotTagged , + Tagged + } ; + // ========================================================================== +public: + // ========================================================================== + // Constructor + CelAutoTaggedCell ( ) + { + m_seeds.reserve( 3 ) ; + } + // ========================================================================== + // Getters + const LHCb::CaloDigit* digit () const { return m_digit ; } + const LHCb::CaloCellID& cellID() const { return digit() -> cellID () ; } + double e () const { return digit() -> e () ; } + bool isEdge() const{ return ( ( Tagged == m_status ) && ( Edge == m_tag ) ); } + bool isClustered() const{ return ( ( Tagged == m_status ) && ( Clustered == m_tag ) ); } + const LHCb::CaloCellID& seedForClustered() const { return m_seeds[0]; } + const std::vector<LHCb::CaloCellID>& seeds() const { return m_seeds; } + size_t numberSeeds() const { return m_seeds.size(); } + bool isSeed() const{ return ( ( m_seeds.size() != 1 ) ? false : cellID() == m_seeds [0] ); } + bool isWithSeed ( const LHCb::CaloCellID& seed ){ return m_seeds.end() != std::find( m_seeds.begin() , m_seeds.end() , seed );} + Tag tag( ) const{return m_tag;} + FlagState status( ) const{return m_status;} + // ========================================================================== + // Setters + void setIsSeed() + { + m_tag = Clustered; + m_status = Tagged; + m_seeds.push_back ( cellID() ); + } + // ========================================================================== + void setEdge () { m_tag = Edge ; } + void setClustered () { m_tag = Clustered ; } + void setStatus () { if ( ( Edge == m_tag ) || ( Clustered == m_tag ) ) + { m_status = Tagged; } } + void addSeed ( const LHCb::CaloCellID& seed ) { m_seeds.push_back ( seed ); } + // ========================================================================== + // operator + CelAutoTaggedCell& operator=( const LHCb::CaloDigit* digit ) + { + reset() ; + m_digit = digit ; + return *this ; + } + // ========================================================================== +protected: + // ========================================================================== + void reset() + { + m_seeds.clear() ; + m_seeds.reserve( 3 ) ; + m_tag = DefaultFlag ; + m_status = NotTagged ; + m_digit = nullptr ; + } + // ========================================================================== +private: + // ========================================================================== + Tag m_tag = DefaultFlag ; + FlagState m_status = NotTagged; + const LHCb::CaloDigit* m_digit = nullptr; + // ========================================================================== + // Ident.seed(s) + LHCb::CaloCellID::Vector m_seeds; + // ========================================================================== +}; +// ============================================================================ +#endif // CALOFUTURECA_CELAUTOTAGGEDCELL_H +// ============================================================================ diff --git a/CaloFuture/CaloFutureReco/src/FutureCellularAutomatonAlg.cpp b/CaloFuture/CaloFutureReco/src/FutureCellularAutomatonAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6930d3b2f52ee7b825ec393a48a2bb9cd6ba52e9 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/FutureCellularAutomatonAlg.cpp @@ -0,0 +1,145 @@ +// ============================================================================ +// Include files +// ============================================================================ +#include "GaudiAlg/FunctionalUtilities.h" +// ============================================================================ +// DetDesc +// ============================================================================ +#include "DetDesc/IGeometryInfo.h" +// ============================================================================ +// Event +// ============================================================================ +#include "Event/CaloDigit.h" +#include "Event/CaloCluster.h" +#include "Event/CaloDataFunctor.h" +#include "Event/CellID.h" +// ============================================================================ +// CaloFutureUtils +// ============================================================================ +#include "CaloFutureUtils/ClusterFunctors.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +// ============================================================================ +// local +// ============================================================================ +#include "FutureCellularAutomatonAlg.h" +// ============================================================================ +/** @file + * Implementation file for class : FutureCellularAutomatonAlg + * + * @date 2008-04-03 + * @author Victor Egorychev + */ +// ============================================================================ +// Declaration of the Algorithm Factory +// ============================================================================ +DECLARE_COMPONENT( FutureCellularAutomatonAlg ) +// ============================================================================ +// Standard constructor, initializes variables +// ============================================================================ +FutureCellularAutomatonAlg::FutureCellularAutomatonAlg( const std::string& name, + ISvcLocator* pSvcLocator ) +: Transformer ( name, pSvcLocator, + KeyValue{"InputData" , LHCb::CaloDigitLocation::Ecal }, + KeyValue{"OutputData", LHCb::CaloClusterLocation::Ecal } ) +{ + // set default data as a function of detector + m_detData = LHCb::CaloFutureAlgUtils::DeCaloFutureLocation( name ) ; + + updateHandleLocation(*this,"InputData" , LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation ( name , context() )); + updateHandleLocation(*this,"OutputData", LHCb::CaloFutureAlgUtils::CaloFutureClusterLocation( name , context() )); +} + +// ============================================================================ +// Initialization +// ============================================================================ +StatusCode FutureCellularAutomatonAlg::initialize() +{ + StatusCode sc = GaudiAlgorithm::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; // error printed already by GaudiAlgorithm + + /// Retrieve geometry of detector + m_detector = getDet<DeCalorimeter>( m_detData ); + if( !m_detector ) { return StatusCode::FAILURE; } + + // Tool Interface + m_tool = tool<ICaloFutureClusterization>(m_toolName, this); + + return StatusCode::SUCCESS; +} +// ============================================================================ +// Main execution +// ============================================================================ +LHCb::CaloCluster::Container +FutureCellularAutomatonAlg::operator()(const LHCb::CaloDigits& digits) const ///< Algorithm execution +{ + // Create the container of clusters + LHCb::CaloCluster::Container output; + // update the version number (needed for serialization) + output.setVersion( 2 ) ; + + // create vector of pointers for CaloFutureCluster + std::vector<LHCb::CaloCluster*> clusters; + + // clusterization tool which return the vector of pointers for CaloClusters + unsigned int stepPass; + if( m_neig_level> 0){ + std::vector<LHCb::CaloCellID> seeds; + stepPass = m_tool->clusterize(clusters, digits, m_detector, seeds, m_neig_level) ; + } else{ + stepPass = m_tool->clusterize(clusters, digits, m_detector) ; + } + + // put to the container of clusters + for ( const auto& clus : clusters ) { output.insert( clus ) ; } + + /** sort the sequence to simplify the comparison + * with other clusterisation techniques + */ + if ( m_sort ) { + if ( !m_sortByET ) { + // sorting criteria: Energy + // perform the sorting + std::stable_sort ( clusters.begin() , + clusters.end () , + LHCb::CaloDataFunctor::inverse( LHCb::CaloDataFunctor::Less_by_Energy ) ) ; + } else { + // sorting criteria : Transverse Energy + LHCb::CaloDataFunctor::Less_by_TransverseEnergy<const DeCalorimeter*> Cmp ( m_detector ) ; + // perform the sorting + std::stable_sort ( clusters.begin() , + clusters.end () , + LHCb::CaloDataFunctor::inverse( Cmp ) ) ; + } + } + + // statistics + m_passes += stepPass; + m_clusters += output.size(); + + if (UNLIKELY( msgLevel( MSG::DEBUG) )){ + debug() << "Built " << clusters.size() <<" cellular automaton clusters with " + << stepPass << " iterations" <<endmsg; + debug() << " ----------------------- Cluster List : " << endmsg; + for(const auto& c : clusters ) { + debug() << " Cluster seed " << c->seed() + << " energy " << c->e() + << " #entries " << c->entries().size() + << endmsg; + } + } + return output; +} +// ============================================================================ +// Finalize +// ============================================================================ +StatusCode FutureCellularAutomatonAlg::finalize() +{ + info() << "Built <" << m_clusters.mean() + <<"> cellular automaton clusters/event with <" + << m_passes.mean() << "> iterations (min,max)=(" << m_passes.min() << "," << m_passes.max() << ") on average " << endmsg; + + return GaudiAlgorithm::finalize(); // must be called after all other actions +} +// ============================================================================= +// the END +// ============================================================================= diff --git a/CaloFuture/CaloFutureReco/src/FutureCellularAutomatonAlg.h b/CaloFuture/CaloFutureReco/src/FutureCellularAutomatonAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..d1a6ccd828a084a1f7cf3f376a36da9a6305e733 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/FutureCellularAutomatonAlg.h @@ -0,0 +1,45 @@ +#ifndef CELLULARAUTOMATONALG_H +#define CELLULARAUTOMATONALG_H 1 + +// Include files +// from Gaudi +#include "GaudiAlg/Transformer.h" +#include "GaudiKernel/Counters.h" + +#include "CaloFutureInterfaces/ICaloFutureClusterization.h" + +/** @class FutureCellularAutomatonAlg FutureCellularAutomatonAlg.h + * + * + * @author Victor Egorychev + * @date 2008-04-03 + */ +class FutureCellularAutomatonAlg +: public Gaudi::Functional::Transformer<LHCb::CaloCluster::Container(const LHCb::CaloDigits&)> +{ + +public: + /// Standard constructor + FutureCellularAutomatonAlg( const std::string& name, ISvcLocator* pSvcLocator ); + + StatusCode initialize() override; ///< Algorithm initialization + StatusCode finalize () override; ///< Algorithm finalization + + LHCb::CaloCluster::Container operator()(const LHCb::CaloDigits&) const override; ///< Algorithm execution + +private: + Gaudi::Property<std::string> m_detData {this, "Detector" , DeCalorimeterLocation::Ecal}; + const DeCalorimeter* m_detector = nullptr; + + Gaudi::Property<bool> m_sort {this, "Sort" , true}; + Gaudi::Property<bool> m_sortByET {this, "SortByET", false}; + + Gaudi::Property<std::string> m_toolName {this, "Tool", "CaloFutureClusterizationTool"}; + ICaloFutureClusterization* m_tool = nullptr; + + Gaudi::Property<unsigned int> m_neig_level {this, "Level", 0}; + + mutable Gaudi::Accumulators::StatCounter<> m_clusters{this, "# clusters"}; + mutable Gaudi::Accumulators::StatCounter<> m_passes{this, "# clusterization passes"}; +}; +#endif // CELLULARAUTOMATONALG_H diff --git a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b34a2c45b8f0074de0a5c63c0c732e42f38872de --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.cpp @@ -0,0 +1,224 @@ +// ============================================================================ +// Include files +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "Event/CaloCluster.h" +#include "FutureClusterCovarianceMatrixTool.h" + +// ============================================================================ +/** @file + * + * Implementation file for class FutureClusterCovarianceMatrixTool + * + * @date 02/11/2001 + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * modified 02/07/2014 by O. Deschamps + */ +// ============================================================================ + +DECLARE_COMPONENT( FutureClusterCovarianceMatrixTool ) + +// ============================================================================ +/** Standard constructor + * @param type tool type (useless) + * @param name tool name + * @param parent pointer to parent object (service, algorithm or tool) + */ +// ============================================================================ +FutureClusterCovarianceMatrixTool::FutureClusterCovarianceMatrixTool +( const std::string& type , + const std::string& name , + const IInterface* parent ) + : GaudiTool( type , name , parent ) +{ + // interface! + declareInterface<ICaloFutureClusterTool> (this); + + // properties : + declareProperty("Parameters", m_parameters); + + // set default configuration as a function of detector + using namespace CaloFutureCovariance; + m_detData = LHCb::CaloFutureAlgUtils::DeCaloFutureLocation( name ) ; + std::string caloName = LHCb::CaloFutureAlgUtils::CaloFutureNameFromAlg( name ); + m_conditionName = "Conditions/Reco/Calo/"+caloName+"Covariance"; + + + // get parameters from parent property when defined + ParameterProperty p("CovarianceParameters", m_parameters); + if( 0 != parent ){ const IProperty* prop = dynamic_cast<const IProperty*> ( parent ); + if( 0 != prop ){ + if( prop->getProperty( &p ).isSuccess() && p.value().size() != 0 ){ + m_parameters = p.value(); + m_useDB = false ; // parent settings win ! + } + } + } + + // apply local parameters if not defined in parent algorithm + if(caloName == "Ecal"){ + if(m_parameters.find(ParameterName[Stochastic]) ==m_parameters.end())m_parameters[ParameterName[Stochastic]] .push_back( 0.10); + if(m_parameters.find(ParameterName[GainError]) ==m_parameters.end())m_parameters[ParameterName[GainError]] .push_back( 0.01 ); + if(m_parameters.find(ParameterName[IncoherentNoise])==m_parameters.end())m_parameters[ParameterName[IncoherentNoise]].push_back( 1.20 ); + if(m_parameters.find(ParameterName[CoherentNoise]) ==m_parameters.end())m_parameters[ParameterName[CoherentNoise]] .push_back( 0.30 ); + if(m_parameters.find(ParameterName[ConstantE]) ==m_parameters.end())m_parameters[ParameterName[ConstantE]] .push_back( 0. ); + if(m_parameters.find(ParameterName[ConstantX]) ==m_parameters.end())m_parameters[ParameterName[ConstantX]] .push_back( 0. ); + if(m_parameters.find(ParameterName[ConstantY]) ==m_parameters.end())m_parameters[ParameterName[ConstantY]] .push_back( 0. ); + }else if( caloName == "Hcal"){ + if(m_parameters.find(ParameterName[Stochastic]) ==m_parameters.end())m_parameters[ParameterName[Stochastic]] .push_back( 0.70 ); + if(m_parameters.find(ParameterName[GainError]) ==m_parameters.end())m_parameters[ParameterName[GainError]] .push_back( 0.10 ); + if(m_parameters.find(ParameterName[IncoherentNoise])==m_parameters.end())m_parameters[ParameterName[IncoherentNoise]].push_back( 1.20 ); + if(m_parameters.find(ParameterName[CoherentNoise]) ==m_parameters.end())m_parameters[ParameterName[CoherentNoise]] .push_back( 0.30 ); + if(m_parameters.find(ParameterName[ConstantE]) ==m_parameters.end())m_parameters[ParameterName[ConstantE]] .push_back( 0. ); + if(m_parameters.find(ParameterName[ConstantX]) ==m_parameters.end())m_parameters[ParameterName[ConstantX]] .push_back( 0. ); + if(m_parameters.find(ParameterName[ConstantY]) ==m_parameters.end())m_parameters[ParameterName[ConstantY]] .push_back( 0. ); + } +} + +//============================================================================== + +StatusCode FutureClusterCovarianceMatrixTool::getParamsFromOptions(){ + m_source.clear(); + unsigned int nareas = m_det->numberOfAreas(); + for(CaloFutureCovariance::ParameterMap::const_iterator imap = m_parameters.begin() ; m_parameters.end() != imap ; ++imap){ + const std::vector<double>& pars = imap->second; + if( pars.size() == 1)m_parameters[imap->first] = std::vector<double>( nareas , pars[0] ); + if( pars.size() != nareas )return Error("Parameters must be set for each calo area",StatusCode::FAILURE); + } + // check all expected parameters are defined + using namespace CaloFutureCovariance; + for(unsigned int index = 0 ; index < CaloFutureCovariance::Last ; ++index){ + if( m_parameters.find(ParameterName[index]) == m_parameters.end() ) + return Error("No default value for parameter '"+ParameterName[index]+"'", StatusCode::FAILURE); + m_source[index]="from options"; + } + return StatusCode::SUCCESS; +} + +//------ +StatusCode FutureClusterCovarianceMatrixTool::getParamsFromDB(){ + + unsigned int nareas = m_det->numberOfAreas(); + // overwrite m_parameters using DB value + if( !m_useDB )return StatusCode::SUCCESS; + m_source.clear(); + using namespace CaloFutureCovariance; + ParameterMap parameters; + for( unsigned int area = 0 ; area < nareas ; ++area){ // loop over calo area + const LHCb::CaloCellID id(m_det->caloName(),area,0,0); // fake cell + const auto & params = m_dbAccessor->getParamVector(CaloFutureCorrection::ClusterCovariance,id); + if( params.size() > CaloFutureCovariance::Last ) + Warning("Parameters vector exceeds the number of known parameters - only " + +Gaudi::Utils::toString(Last)+" parameters will be applied",StatusCode::SUCCESS).ignore(); + for(unsigned int index = 0 ; index < CaloFutureCovariance::Last ; ++index){ + if( index < params.size() ){ + parameters[ParameterName[index]].push_back( params[index] ); + m_source[index]="from Covariance DB"; + }else{ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Parameter '"<<ParameterName[index] << "' not found in DB - use default options value"<<endmsg; + if( m_parameters.find(ParameterName[index]) == m_parameters.end() ) + return Error("No default value for parameter '"+ParameterName[ index ]+"'", StatusCode::FAILURE); + parameters[ParameterName[index]].push_back( m_parameters[ParameterName[index]][area] ); + m_source[index]="from options"; + } + } + } + m_parameters=parameters; + if( m_parameters.size() == 0)return StatusCode::FAILURE; // no parameters set + return StatusCode::SUCCESS; +} + +//------- +void FutureClusterCovarianceMatrixTool::setEstimatorParams(bool init){ + + // update DB parameters + if( !init && !m_useDB)return; // estimator setting via options : at initialization only + if( !init && !m_dbAccessor-> hasConditionChanged())return; // estimator setting via DB : no need to update - condition has not changed + if( m_useDB && getParamsFromDB().isFailure() ){ + Error("Failed updating the covariance parameters from DB",StatusCode::FAILURE).ignore(); // update DB parameters + return; // failed to update parameters from DB + } + using namespace CaloFutureCovariance; + m_estimator.setStochastic ( m_parameters[ParameterName[Stochastic]] ) ; + m_estimator.setGainError ( m_parameters[ParameterName[GainError]] ) ; + m_estimator.setIncoherentNoise ( m_parameters[ParameterName[IncoherentNoise]] ) ; + m_estimator.setCoherentNoise ( m_parameters[ParameterName[CoherentNoise]] ) ; + m_estimator.setConstantE ( m_parameters[ParameterName[ConstantE]] ) ; + m_estimator.setConstantX ( m_parameters[ParameterName[ConstantX]] ) ; + m_estimator.setConstantY ( m_parameters[ParameterName[ConstantY]] ) ; + if(counterStat->isVerbose())counter("Parameter update") += 1; + //info() << "ESTIMATOR HAS BEEN UPDATED (" << m_conditionName << ") : init = " << init << endmsg; +} + +//--------- +StatusCode FutureClusterCovarianceMatrixTool::initialize (){ + StatusCode sc = GaudiTool::initialize (); + if( sc.isFailure() ){ return Error("Could not initialize the base class!") ; } + counterStat = tool<IFutureCounterLevel>("FutureCounterLevel"); + + + // register to incident service + IIncidentSvc* inc = incSvc() ; + if ( 0 != inc )inc -> addListener ( this , IncidentType::BeginEvent ) ; + + // get detector + m_det = getDet<DeCalorimeter>( m_detData ) ; + + // set DB accessor + m_dbAccessor = tool<CaloFutureCorrectionBase>("CaloFutureCorrectionBase","DBAccessor",this); + if( m_useDB && (m_conditionName == "" || m_dbAccessor->setConditionParams(m_conditionName,true).isFailure()) ) + return Error("Cannot access DB",StatusCode::FAILURE); + + // always set default parameters from options (will be updated by DB if requested) + sc= getParamsFromOptions(); + + // check the parameters consistency + for(CaloFutureCovariance::ParameterMap::const_iterator imap = m_parameters.begin() ; m_parameters.end() != imap ; ++imap){ + std::string name = imap->first; + bool ok = false; + for(unsigned int index = 0 ; index < CaloFutureCovariance::Last ; ++index){ + if( CaloFutureCovariance::ParameterName[index] == name ){ ok = true; break;} + } + if( !ok )return Error("Parameter type '"+name+"' is unknown",StatusCode::FAILURE); + } + + // configure estimator (possibly from DB if requested) + m_estimator.setDetector( m_det ) ; + setEstimatorParams(true); // force initialization + info() << " Has initialized with parameters: " << endmsg + << " \t 'Detector' = '" << m_detData.value() << "'" << endmsg + // << " \t Estimator is " << m_estimator << endmsg; + << " \t == Parameters for covariance estimation ==" << endmsg; + using namespace CaloFutureCovariance; + for(unsigned int index = 0 ; index < CaloFutureCovariance::Last ; ++index){ + info() << CaloFutureCovariance::ParameterName[index] << " \t : " + << m_parameters[ParameterName[index]] + << " " << ParameterUnit[index] + << "\t : "<< m_source[index]<<""<< endmsg; + } + return sc; +} +// ============================================================================ +StatusCode FutureClusterCovarianceMatrixTool::finalize (){ + IIncidentSvc* inc = incSvc() ; + if ( 0 != inc ) { inc -> removeListener ( this ) ; } + return GaudiTool::finalize (); +} + +// ============================================================================ +StatusCode +FutureClusterCovarianceMatrixTool::operator() ( LHCb::CaloCluster* cluster ) const{ + /// check the argument + if( 0 == cluster )return Error( "CaloCluster* points to NULL!") ; + if( 0 == m_estimator.detector() )return Error( "DeCalorimeter* points to NULL!") ; + /// apply the estimator + return m_estimator( cluster ); +} +// ============================================================================ + +StatusCode FutureClusterCovarianceMatrixTool::process ( LHCb::CaloCluster* cluster ) const { + return (*this)( cluster ); +} +// ============================================================================ + diff --git a/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h new file mode 100644 index 0000000000000000000000000000000000000000..848a0efd8a059a2116c1119a15d557d55a3ab5ac --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/FutureClusterCovarianceMatrixTool.h @@ -0,0 +1,85 @@ +#ifndef CLUSTERCOVARIANCEMATRIXTOOL_H +#define CLUSTERCOVARIANCEMATRIXTOOL_H 1 +// Include files +#include "GaudiAlg/GaudiTool.h" +#include "GaudiKernel/IIncidentListener.h" +#include "GaudiKernel/IIncidentSvc.h" +#include "GaudiKernel/Incident.h" +#include "CaloFutureUtils/CovarianceEstimator.h" +#include "CaloFutureInterfaces/ICaloFutureClusterTool.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" +#include "CaloFutureCorrectionBase.h" + + +/** @class FutureClusterCovarianceMatrixTool + * FutureClusterCovarianceMatrixTool.h + * + * Concrete tool for calculation of covariance matrix + * for the whole cluster object + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 02/11/2001 + */ + +namespace CaloFutureCovariance{ + enum Parameters{ + Stochastic = 0 , // stochastig term Cov(EE)_i += [ S * sqrt(E_i_GeV) ]^2 + GainError = 1 , // constant term Cov(EE)_i += [ G * E_i ]^2 + IncoherentNoise = 2 , // noise (inc.) term Cov(EE)_i += [ iN * gain_i ]^2 + CoherentNoise = 3 , // noise (coh.) term Cov(EE)_i += [ cN * gain_i ]^2 + ConstantE = 4 , // additional term Cov(EE) += [ cE ]^2 + ConstantX = 5 , // additional term Cov(XX) += [ cX ]^2 + ConstantY = 6 , // additional term Cov(XX) += [ cY ]^2 + Last + }; + static const int nParams=Last+1; + static const std::string ParameterName[nParams] = {"Stochastic","GainError","IncoherentNoise","CoherentNoise", + "ConstantE" ,"ConstantX","ConstantY"}; + static const std::string ParameterUnit[nParams] = {"Sqrt(GeV)" , "" , "ADC" , "ADC" , "MeV" , "mm" , "mm"}; + typedef std::map<std::string,std::vector<double> > ParameterMap; + typedef SimplePropertyRef< ParameterMap > ParameterProperty; +} + + + + +class FutureClusterCovarianceMatrixTool: public virtual ICaloFutureClusterTool , public GaudiTool , virtual public IIncidentListener{ +public: + + StatusCode initialize() override; + StatusCode finalize() override; + StatusCode process ( LHCb::CaloCluster* cluster ) const override; + StatusCode operator() ( LHCb::CaloCluster* cluster ) const override; + + + void handle(const Incident& ) override { + if( UNLIKELY( msgLevel(MSG::DEBUG) ) )debug() << "IIncident Svc reset" << endmsg; + setEstimatorParams(); // reset estimator when parameters change + } + + +protected: + + StatusCode getParamsFromOptions(); + StatusCode getParamsFromDB(); + void setEstimatorParams(bool init=false); + +public: + FutureClusterCovarianceMatrixTool( const std::string& type , + const std::string& name , + const IInterface* parent ); + +private: + + CovarianceEstimator m_estimator ; + CaloFutureCovariance::ParameterMap m_parameters; + Gaudi::Property<std::string> m_detData {this, "Detector"}; + const DeCalorimeter* m_det = nullptr; + Gaudi::Property<bool> m_useDB {this, "UseDBParameters", true}; + CaloFutureCorrectionBase* m_dbAccessor = nullptr; + Gaudi::Property<std::string> m_conditionName {this, "ConditionName"}; + std::map<unsigned int,std::string> m_source; + IFutureCounterLevel* counterStat = nullptr; +}; ///< end of class FutureClusterCovarianceMatrixTool +// ============================================================================ +#endif // CLUSTERCOVARIANCEMATRIXTOOL_H diff --git a/CaloFuture/CaloFutureReco/src/FutureClusterSpreadTool.cpp b/CaloFuture/CaloFutureReco/src/FutureClusterSpreadTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f6b2f39a08a00ba3b66a02af50c1aa2173ac01ac --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/FutureClusterSpreadTool.cpp @@ -0,0 +1,101 @@ +// ============================================================================ +// Include files +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "FutureClusterSpreadTool.h" +// ============================================================================ +/** @file FutureClusterSpreadTool.cpp + * + * Implementation file for class : FutureClusterSpreadTool + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 23/11/2001 + */ +// ============================================================================ +DECLARE_COMPONENT( FutureClusterSpreadTool ) +// ============================================================================ +/* Standard constructor + * @param type tool type (useless) + * @param name tool name + * @param parent pointer to parent object (service, algorithm or tool) + */ +// ============================================================================ +FutureClusterSpreadTool::FutureClusterSpreadTool +( const std::string& type , + const std::string& name , + const IInterface* parent ) + : GaudiTool ( type , name , parent ) +{ + // setup calo-dependent property + m_detData = LHCb::CaloFutureAlgUtils::DeCaloFutureLocation( name ) ; + + /// declare available interafces + declareInterface<ICaloFutureClusterTool>(this); +} +// ============================================================================ +/* standard initialization method + * @return status code + */ +// ============================================================================ +StatusCode FutureClusterSpreadTool::initialize () +{ + /// initialize the base class + StatusCode sc = GaudiTool::initialize(); + if( sc.isFailure() ) + { return Error("Could not initialize the base class ",sc);} + /// + m_det = getDet<DeCalorimeter>( m_detData) ; + /// configure the estimator + m_estimator.setDetector( m_det ) ; + /// + return StatusCode::SUCCESS; +} +// ============================================================================ +/* standard finalization method + * @return status code + */ +// ============================================================================ +StatusCode FutureClusterSpreadTool::finalize () +{ + if ( UNLIKELY(msgLevel ( MSG::DEBUG ) ) ) + { + debug () << " Corrected Clusters, Ratio : " + << m_estimator.invalidRatio () << endmsg ; + debug () << " Corrected Clusters, Et : " + << m_estimator.invalidEnergy () << endmsg ; + debug () << " Corrected Clusters, Cells : " + << m_estimator.invalidCells () << endmsg ; + } + /// finalize the base class + return GaudiTool::finalize (); +} +// ============================================================================ +/* The main processing method + * @param cluster pointer to CaloCluster object to be processed + * @return status code + */ +// ============================================================================ +StatusCode FutureClusterSpreadTool::process +( LHCb::CaloCluster* cluster ) const { return (*this)( cluster ); } +// ============================================================================ +/* The main processing method (functor interface) + * @param cluster pointer to CaloCluster object to be processed + * @return status code + */ +// ============================================================================ +StatusCode FutureClusterSpreadTool::operator() + ( LHCb::CaloCluster* cluster ) const +{ + /// check the argument + if( 0 == cluster ) + { return Error( "CaloCluster* points to NULL!") ; } + if( 0 == m_estimator.detector() ) + { return Error( "DeCalorimeter* points to NULL!") ; } + /// apply the estimator + return m_estimator( cluster ); +} +// ============================================================================ +// The END +// ============================================================================ + + diff --git a/CaloFuture/CaloFutureReco/src/FutureClusterSpreadTool.h b/CaloFuture/CaloFutureReco/src/FutureClusterSpreadTool.h new file mode 100644 index 0000000000000000000000000000000000000000..92dd5e6345f53bb74e8766d3f9f0a4aeb117093b --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/FutureClusterSpreadTool.h @@ -0,0 +1,80 @@ +#ifndef CALOFUTURERECO_CLUSTERSPREADTOOL_H +#define CALOFUTURERECO_CLUSTERSPREADTOOL_H 1 +// ============================================================================ +// Include files +// ============================================================================ +// GaudiKernel +// ============================================================================ +#include "GaudiKernel/Property.h" +// ============================================================================ +// CaloFutureInterfaces +// ============================================================================ +#include "CaloFutureInterfaces/ICaloFutureClusterTool.h" +// ============================================================================ +// GaudiAlg +// ============================================================================ +#include "GaudiAlg/GaudiTool.h" +// ============================================================================ +// CaloFutureUtil +// ============================================================================ +#include "CaloFutureUtils/SpreadEstimator.h" +// ============================================================================ +/** @class FutureClusterSpreadTool FutureClusterSpreadTool.h + * + * Concrete tool for estimation of the + * effective cluster size ("spread") + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 22/11/2001 + */ +// ============================================================================ +class FutureClusterSpreadTool: + public virtual ICaloFutureClusterTool , + public GaudiTool +{ +public: + // ========================================================================== + /** standard initialization method + * @return status code + */ + StatusCode initialize() override; + // ========================================================================== + /** standard finalization method + * @return status code + */ + StatusCode finalize() override; + // ========================================================================== + /** The main processing method + * @param cluster pointer to CaloCluster object to be processed + * @return status code + */ + StatusCode process ( LHCb::CaloCluster* cluster ) const override; + // ========================================================================== + /** The main processing method (functor interface) + * @param cluster pointer to CaloCluster object to be processed + * @return status code + */ + StatusCode operator() ( LHCb::CaloCluster* cluster ) const override; + // ========================================================================== + /** Standard constructor + * @param type tool type (useless) + * @param name tool name + * @param parent pointer to parent object (service, algorithm or tool) + */ + FutureClusterSpreadTool + ( const std::string& type , + const std::string& name , + const IInterface* parent ); + // ========================================================================== +private: + // ========================================================================== + SpreadEstimator m_estimator ; + Gaudi::Property<std::string> m_detData {this, "Detector"}; + const DeCalorimeter* m_det = nullptr; + // ========================================================================== +}; +// ============================================================================ +// The End +// ============================================================================ +#endif // CALOFUTURERECO_CLUSTERSPREADTOOL_H +// ============================================================================ diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelector2x2.cpp b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelector2x2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..983084f5e5df239fd8161f3d60d2f8d559e1e2ab --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelector2x2.cpp @@ -0,0 +1,197 @@ +// ============================================================================ +// Include files +// Event +#include "Event/CaloCluster.h" +#include "Event/CaloDigit.h" +// CaloFutureUtils +#include "CaloFutureUtils/ClusterFunctors.h" +#include "CaloFutureUtils/CaloFutureDataFunctor.h" +#include "CaloFutureUtils/CellMatrix2x2.h" +// local +#include "FutureSubClusterSelector2x2.h" + +// ============================================================================ +/** @file FutureSubClusterSelector2x2.cpp + * + * Implementation file for class : FutureSubClusterSelector2x2 + * + * @author F. Machefert + * @date 06/14/2014 + */ +// ============================================================================ + +DECLARE_COMPONENT( FutureSubClusterSelector2x2 ) + +// ============================================================================ +/** Standard Tool Constructor + * @param type type of the tool (useless ? ) + * @param name name of the tool + * @param parent the tool parent + */ +// ============================================================================ + +FutureSubClusterSelector2x2::FutureSubClusterSelector2x2( const std::string& type, + const std::string& name, + const IInterface* parent ) + : FutureSubClusterSelectorBase ( type, name , parent ) + , m_matrix () +{} + +// ============================================================================ +/** standard initiliazation + * @return status code + */ +// ============================================================================ +StatusCode FutureSubClusterSelector2x2::initialize() +{ + /// initliaze the base class + StatusCode sc = FutureSubClusterSelectorBase::initialize() ; + if( sc.isFailure() ) + { return Error("Could not initialize the base class!",sc); } + if( 0 != det() ) + { + m_det=det(); + m_matrix.setDet( m_det ) ; + } + else + { return Error("DeCalorimeter* ponts to NULL!"); } + /// + return StatusCode::SUCCESS ; +} + +// ============================================================================ +/** The main processing method + * @param cluster pointer to CaloFutureCluster object to be processed + * @return status code + */ +// ============================================================================ +StatusCode FutureSubClusterSelector2x2::tag ( LHCb::CaloCluster* cluster ) const{ + double energy; + CellMatrix2x2::SubMatrixType type; + // + StatusCode sc = choice2x2( cluster , type, energy ); + if( sc.isFailure() )return Error( "Error from 'choice2x2()'" , sc ); + // + m_matrix.setType( type ); + sc =LHCb::ClusterFunctors:: + tagTheSubCluster( cluster , + m_matrix , + modify() , + mask(), + LHCb::CaloDigitStatus::ModifiedByMax2x2Tagger ) ; + + // + if( sc.isFailure() ) + { return Error( "Error from 'tagTheSubCluster()'" , sc ); } + // + return StatusCode::SUCCESS ; } + +// ============================================================================ +/** The main processing method (untag) + * @param cluster pointer to CaloCluster object to be processed + * @return status code + */ +// ============================================================================ +StatusCode FutureSubClusterSelector2x2::untag ( LHCb::CaloCluster* cluster ) const +{ + double energy; + CellMatrix2x2::SubMatrixType type; + // + StatusCode sc = choice2x2( cluster , type, energy ); + if( sc.isFailure() ) + { return Error( "Error from 'choice2x2()'" , sc ); } + // + m_matrix.setType( type ); + sc = LHCb::ClusterFunctors:: + untagTheSubCluster( cluster , + m_matrix , + LHCb::CaloDigitStatus::ModifiedByMax2x2Tagger ); + // + if( sc.isFailure() ) + { return Error( "Error from 'untagTheSubCluster()'" , sc ); } + // + return StatusCode::SUCCESS ; +} + +// ============================================================================ +/** The method that selects the 2x2 cluster out of the full cluster + * @param cluster pointer to CaloCluster object to be processed + * @param type the selected type of cluster + * @param energy the energy of the selected cluster + * @return status code + */ +// ============================================================================ +StatusCode FutureSubClusterSelector2x2::choice2x2 ( + LHCb::CaloCluster* cluster , + CellMatrix2x2::SubMatrixType &type, + double &energy) const +{ + // check the arguments + if( 0 == cluster ) { + return Error ( "cluster points to NULL in 'choice 2x2()'" ); + } + // get all entries + LHCb::CaloCluster::Entries& entries = cluster->entries() ; + // find seed digit + LHCb::CaloCluster::Entries::iterator seedEntry = + LHCb::ClusterFunctors::locateDigit( entries.begin () , + entries.end () , + LHCb::CaloDigitStatus::SeedCell ); + // check the seed + if( entries.end() == seedEntry ) { + return Error ( "could not find the seed of the cluster in 'choice2x2()'." ); + } + const LHCb::CaloDigit* seed = seedEntry->digit() ; + if( 0 == seed ) { + return Error ( "cluster seed points to NULL in 'choice2x2()'." ); + } + + LHCb::CaloCellID seedCell = seed->cellID(); + + // loop over all entried + CellMatrix2x2 matrix( m_det ); + + double e[4]; + CellMatrix2x2::SubMatrixType mode[4]; + + mode[0] = CellMatrix2x2::UpperLeft; + mode[1] = CellMatrix2x2::UpperRight; + mode[2] = CellMatrix2x2::LowerLeft; + mode[3] = CellMatrix2x2::LowerRight; + +// std::cout << " * Running on a cluster e=" +// << cluster->e() +// << std::endl; + + for ( int j=0; j<4; ++j ){ + e[j]=0.; + matrix.setType ( mode[j] ); + // std::cout << " Mode "<< mode[j] << " -> "; + for( LHCb::CaloCluster::Entries::iterator entry = entries.begin() ; + entries.end() != entry ; ++entry ) + { + const LHCb::CaloDigit* digit = entry->digit() ; + if( 0 == digit ){ continue ; } // CONTINUE + double tmp = digit->e(); + LHCb::CaloCellID cell = digit->cellID(); + double frac = matrix ( seedCell, cell ) ; + e[j] += frac * tmp; + // std::cout << " - " << frac << " " << tmp << "(" << e[j] <<")" ; + } + // std::cout << " -> " << e[j] << std::endl; + } + // select the max energy case + type= mode[0]; energy = e[0]; + for (int i=1; i<4; ++i) { + if (e[i]>energy) { energy = e[i] ; type = mode[i]; } + } + // std::cout << " Summary 2x2 clusterisation: " + // << e[0] << " " << e[1] << " " << e[2] << " " << e[3] + // << " --> " << energy << "[" << type << "]" << std::endl; + return StatusCode::SUCCESS; +} + + +// ============================================================================ +// The End +// ============================================================================ diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelector2x2.h b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelector2x2.h new file mode 100644 index 0000000000000000000000000000000000000000..823a7cb196465f3636631994f06e22ff227dde30 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelector2x2.h @@ -0,0 +1,30 @@ +#ifndef CALOFUTURERECO_SUBCLUSTERSELECTOR2x2_H +#define CALOFUTURERECO_SUBCLUSTERSELECTOR2x2_H 1 +// Include files +#include "FutureSubClusterSelectorBase.h" +#include "CaloFutureUtils/CellMatrix2x2.h" + + +class FutureSubClusterSelector2x2: public FutureSubClusterSelectorBase{ +public: + + StatusCode initialize() override; + StatusCode tag ( LHCb::CaloCluster* cluster ) const override; + StatusCode untag ( LHCb::CaloCluster* cluster ) const override; + +protected: + StatusCode choice2x2 (LHCb::CaloCluster* cluster, + CellMatrix2x2::SubMatrixType &type, + double &energy) const ; + +public: + FutureSubClusterSelector2x2( const std::string& type , + const std::string& name , + const IInterface* parent ); + +private: + const DeCalorimeter* m_det = NULL; + CellMatrix2x2 m_matrix; +}; + +#endif // SUBCLUSTERSELECTOR2X2_H diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelector3x3.cpp b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelector3x3.cpp new file mode 100644 index 0000000000000000000000000000000000000000..23ff3431b1cedc9ee169fae7dc64c01e49c41187 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelector3x3.cpp @@ -0,0 +1,98 @@ +// ============================================================================ +// Include files +// Event +#include "Event/CaloCluster.h" +#include "Event/CaloDigit.h" +// CaloFutureUtils +#include "CaloFutureUtils/ClusterFunctors.h" +// local +#include "FutureSubClusterSelector3x3.h" + +// ============================================================================ +/** @file FutureSubClusterSelector3x3.cpp + * + * Implementation file for class : FutureSubClusterSelector3x3 + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 07/11/2001 + */ +// ============================================================================ + +DECLARE_COMPONENT( FutureSubClusterSelector3x3 ) + +// ============================================================================ +/** Standard Tool Constructor + * @param type type of the tool (useless ? ) + * @param name name of the tool + * @param parent the tool parent + */ +// ============================================================================ + +FutureSubClusterSelector3x3::FutureSubClusterSelector3x3( const std::string& type, + const std::string& name, + const IInterface* parent ) + : FutureSubClusterSelectorBase ( type, name , parent ) + , m_matrix () +{} + +// ============================================================================ +/** standard initiliazation + * @return status code + */ +// ============================================================================ +StatusCode FutureSubClusterSelector3x3::initialize() +{ + /// initliaze the base class + StatusCode sc = FutureSubClusterSelectorBase::initialize() ; + if( sc.isFailure() ) + { return Error("Could not initialize the base class!",sc); } + if( 0 != det() ) + { m_matrix.setDet( det() ) ; } + else + { return Error("DeCalorimeter* ponts to NULL!"); } + /// + return StatusCode::SUCCESS ; +} + +// ============================================================================ +/** The main processing method + * @param cluster pointer to CaloCluster object to be processed + * @return status code + */ +// ============================================================================ +StatusCode FutureSubClusterSelector3x3::tag ( LHCb::CaloCluster* cluster ) const{ + + + StatusCode sc = LHCb::ClusterFunctors::tagTheSubCluster( cluster , + m_matrix , + modify() , + mask() , + LHCb::CaloDigitStatus::ModifiedBy3x3Tagger) ; + // + if( sc.isFailure() ){ return Error( "Error from 'tagTheSubCluster()'" , sc ); } + // + return StatusCode::SUCCESS ; +} + +// ============================================================================ +/** The main processing method (untag) + * @param cluster pointer to CaloCluster object to be processed + * @return status code + */ +// ============================================================================ +StatusCode FutureSubClusterSelector3x3::untag ( LHCb::CaloCluster* cluster ) const{ + StatusCode sc = + LHCb::ClusterFunctors:: + untagTheSubCluster( cluster , + m_matrix , + LHCb::CaloDigitStatus::ModifiedBy3x3Tagger ); + // + if( sc.isFailure() ) + { return Error( "Error from 'untagTheSubCluster()'" , sc ); } + // + return StatusCode::SUCCESS ; +} + +// ============================================================================ +// The End +// ============================================================================ diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelector3x3.h b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelector3x3.h new file mode 100644 index 0000000000000000000000000000000000000000..cdf001f6b0f93473f02bf9aaf512b23bb56aefb6 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelector3x3.h @@ -0,0 +1,63 @@ +#ifndef CALOFUTURERECO_SUBCLUSTERSELECTOR3x3_H +#define CALOFUTURERECO_SUBCLUSTERSELECTOR3x3_H 1 +// Include files +#include "FutureSubClusterSelectorBase.h" +#include "CaloFutureUtils/CellMatrix3x3.h" + +/** @class FutureSubClusterSelector3x3 FutureSubClusterSelector3x3.h + * + * The simplest concrete "subcluster selector" - + * it just tag/select digits which form + * 3x3 sub-matrix centered with the seed cells + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 07/11/2001 + */ + +class FutureSubClusterSelector3x3 : public FutureSubClusterSelectorBase{ +public: + + StatusCode initialize() override; + + /** The main processing method + * + * @see ICaloFutureSubClusterTag + * + * Error codes: + * - 225 cluster points to NULL + * - 226 empty cell/digit container for given cluster + * - 227 SeedCell is not found + * - 228 Seed points to NULL + * + * @see ICaloFutureClusterTool + * @see ICaloFutureSubClusterTag + * + * @param cluster pointer to CaloFutureCluster object to be processed + * @return status code + */ + + StatusCode tag ( LHCb::CaloCluster* cluster) const override; + + /** The main method - "undo" of tagging from "tag" method + * @see ICaloFutureSubClusterTag + * @param cluster pointer to ClaoCluster object to be untagged + * @return status code + */ + StatusCode untag ( LHCb::CaloCluster* cluster ) const override; + + /** Standard Tool Constructor + * @param type type of the tool (useless ? ) + * @param name name of the tool + * @param parent the tool parent + */ + FutureSubClusterSelector3x3( const std::string& type , + const std::string& name , + const IInterface* parent ); + +private: + + CellMatrix3x3 m_matrix; + +}; + +#endif // SUBCLUSTERSELECTOR3x3_H diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorBase.cpp b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorBase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..abcb5856c328737a5af4e502c66bb8f5acc2e511 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorBase.cpp @@ -0,0 +1,93 @@ +// ============================================================================ +// Include files +// ============================================================================ +// CaloFutureInterfaces +#include "CaloFutureInterfaces/ICaloFutureClusterTool.h" +// CaloDet +#include "CaloDet/DeCalorimeter.h" +// CaloFutureEvent +#include "Event/CaloCluster.h" +// local +#include "FutureSubClusterSelectorBase.h" + +// ============================================================================ +/** @file SubclusterSelectorBase.cpp + * + * Implementation file for class : FutureSubClusterSelectorBase + * + * @date 07/11/2001 + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + */ +// ============================================================================ + +// ============================================================================ +/** Standard Tool Constructor + * @param type type of the tool (useless ? ) + * @param name name of the tool + * @param parent the tool parent + */ +// ============================================================================ +FutureSubClusterSelectorBase::FutureSubClusterSelectorBase( const std::string& type, + const std::string& name, + const IInterface* parent ) + : GaudiTool ( type, name , parent ) + , m_mask(defaultStatus) +{ + /// declare the available interfaces + declareInterface<ICaloFutureClusterTool> ( this ) ; + declareInterface<ICaloFutureSubClusterTag> ( this ) ; +} +// ============================================================================ + +// ============================================================================ +/** standard finalization method + * @return status code + */ +// ============================================================================ +StatusCode FutureSubClusterSelectorBase::finalize () +{ return GaudiTool::finalize(); } +// ============================================================================ + +// ============================================================================ +/** standard initialization method + * @return status code + */ +// ============================================================================ +StatusCode FutureSubClusterSelectorBase::initialize () +{ + // initialize the base class + StatusCode sc = GaudiTool::initialize() ; + if( sc.isFailure() ) + { return Error("Could not initialize the base class!",sc);} + // load and set the detector + m_det = getDet<DeCalorimeter>( m_detData ) ; + // + return StatusCode::SUCCESS; +} +// ============================================================================ + +// ============================================================================ +/** The main processing method (functor interface) + * @param cluster pointer to CaloCluster object to be processed + * @return status code + */ +// ============================================================================ +StatusCode FutureSubClusterSelectorBase::process ( LHCb::CaloCluster* cluster ) const{ + return tag ( cluster ) ; +} + +// ============================================================================ + +// ============================================================================ +/** The main processing method + * @see ICaloFutureSubClusterTag + * @see ICaloFutureClusterTool + * @param cluster pointer to CaloCluster object to be processed + * @return status code + */ +// ============================================================================ +StatusCode FutureSubClusterSelectorBase::operator() ( LHCb::CaloCluster* cluster ) const{ + return tag ( cluster ) ; +} +// ============================================================================ + diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorBase.h b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorBase.h new file mode 100644 index 0000000000000000000000000000000000000000..a8245f3fdef46c5645a319b5422f9754552201d9 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorBase.h @@ -0,0 +1,80 @@ +// $Id: FutureSubClusterSelectorBase.h,v 1.5 2010-03-08 01:19:40 odescham Exp $ + +#ifndef CALOFUTURERECO_SUBCLUSTERSELECTORBASE_H +#define CALOFUTURERECO_SUBCLUSTERSELECTORBASE_H 1 +// Include files +#include "CaloFutureInterfaces/ICaloFutureSubClusterTag.h" +#include "Event/CaloDigitStatus.h" +#include "GaudiAlg/GaudiTool.h" +class CaloFutureCluster ; + + +class FutureSubClusterSelectorBase : public virtual ICaloFutureSubClusterTag , public GaudiTool{ + +public: + + static const LHCb::CaloDigitStatus::Status defaultStatus = + LHCb::CaloDigitStatus::UseForEnergy |LHCb::CaloDigitStatus::UseForPosition | LHCb::CaloDigitStatus::UseForCovariance ; + + + StatusCode initialize() override; + StatusCode finalize() override; + StatusCode process(LHCb::CaloCluster* cluster)const override; + StatusCode operator()(LHCb::CaloCluster* cluster)const override; + void setMask(const LHCb::CaloDigitStatus::Status mask)const override { + m_mask=mask; + if ( UNLIKELY(msgLevel(MSG::DEBUG)) )debug() << "The default status tag is changed to " << m_mask + << " -> use for Energy : " << ((mask & LHCb::CaloDigitStatus::UseForEnergy) != 0) + << " | for Position : " << ((mask & LHCb::CaloDigitStatus::UseForPosition) != 0) + << " | for Covariance : " << ((mask & LHCb::CaloDigitStatus::UseForCovariance) != 0) + << endmsg; + } + unsigned int mask()const override {return m_mask;}; + + + +protected: + + + /** return flag to modify the fractions + * @return flag to modify the fractions + */ + inline bool modify() const { return m_modify ; } + + /** set new value for "modify" parameter + * @param value new value of modify parameter + */ + inline void setModify( const bool value ) const { m_modify = value ; } + + inline const DeCalorimeter* det() {return m_det; } + + + protected: + + /** Standard Tool Constructor + * @param type type of the tool (useless ? ) + * @param name name of the tool + * @param parent the tool parent + */ + FutureSubClusterSelectorBase( const std::string& type , + const std::string& name , + const IInterface* parent ); + +private: + + /// default constructor is private + FutureSubClusterSelectorBase(); + /// copy constructor is private + FutureSubClusterSelectorBase( const FutureSubClusterSelectorBase& ); + /// assignement operator is private + FutureSubClusterSelectorBase& operator=( const FutureSubClusterSelectorBase& ); + +private: + mutable LHCb::CaloDigitStatus::Status m_mask; + mutable Gaudi::Property<bool> m_modify {this, "ModifyFractions", false}; + Gaudi::Property<std::string> m_detData {this, "Detector", DeCalorimeterLocation::Ecal}; + const DeCalorimeter* m_det = nullptr; + +}; +// ============================================================================ +#endif // SUBCLUSTERSELECTORBASE_H diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorSwissCross.cpp b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorSwissCross.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8bebb19b04f2bfb4df8de83b517c444981fb29da --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorSwissCross.cpp @@ -0,0 +1,98 @@ +// ============================================================================ +// Include files +// Event +#include "Event/CaloCluster.h" +#include "Event/CaloDigit.h" +// CaloFutureUtils +#include "CaloFutureUtils/ClusterFunctors.h" +// local +#include "FutureSubClusterSelectorSwissCross.h" + +// ============================================================================ +/** @file FutureSubClusterSelectorSwissCross.cpp + * + * Implementation file for class : FutureSubClusterSelectorSwissCross + * + * @author Vanya Belyaev Ivan.Belyaev@itep.ru + * @date 07/11/2001 + */ +// ============================================================================ + +DECLARE_COMPONENT( FutureSubClusterSelectorSwissCross ) + +// ============================================================================ +/** Standard Tool Constructor + * @param type type of the tool (useless ? ) + * @param name name of the tool + * @param parent the tool parent + */ +// ============================================================================ + +FutureSubClusterSelectorSwissCross::FutureSubClusterSelectorSwissCross( const std::string& type, + const std::string& name, + const IInterface* parent ) + : FutureSubClusterSelectorBase ( type, name , parent ) + , m_matrix () +{} + +// ============================================================================ +/** standard initiliazation + * @return status code + */ +// ============================================================================ +StatusCode FutureSubClusterSelectorSwissCross::initialize() +{ + /// initliaze the base class + StatusCode sc = FutureSubClusterSelectorBase::initialize() ; + if( sc.isFailure() ) + { return Error("Could not initialize the base class!",sc); } + if( 0 != det() ) + { m_matrix.setDet( det() ) ; } + else + { return Error("DeCalorimeter* ponts to NULL!"); } + /// + return StatusCode::SUCCESS ; +} + +// ============================================================================ +/** The main processing method + * @param cluster pointer to CaloCluster object to be processed + * @return status code + */ +// ============================================================================ +StatusCode FutureSubClusterSelectorSwissCross::tag ( LHCb::CaloCluster* cluster ) const{ + + + StatusCode sc = LHCb::ClusterFunctors::tagTheSubCluster( cluster , + m_matrix , + modify() , + mask(), + LHCb::CaloDigitStatus::ModifiedBySwissCrossTagger) ; + // + if( sc.isFailure() ){ return Error( "Error from 'tagTheSubCluster()'" , sc ); } + // + return StatusCode::SUCCESS ; +} + +// ============================================================================ +/** The main processing method (untag) + * @param cluster pointer to CaloCluster object to be processed + * @return status code + */ +// ============================================================================ +StatusCode FutureSubClusterSelectorSwissCross::untag ( LHCb::CaloCluster* cluster ) const{ + StatusCode sc = + LHCb::ClusterFunctors:: + untagTheSubCluster( cluster , + m_matrix , + LHCb::CaloDigitStatus::ModifiedBySwissCrossTagger ); + // + if( sc.isFailure() ) + { return Error( "Error from 'untagTheSubCluster()'" , sc ); } + // + return StatusCode::SUCCESS ; +} + +// ============================================================================ +// The End +// ============================================================================ diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorSwissCross.h b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorSwissCross.h new file mode 100644 index 0000000000000000000000000000000000000000..283871ebdd3596af42f90862d9f29b59ddd457eb --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorSwissCross.h @@ -0,0 +1,27 @@ +#ifndef CALOFUTURERECO_SUBCLUSTERSELECTORSwissCross_H +#define CALOFUTURERECO_SUBCLUSTERSELECTORSwissCross_H 1 +// Include files +// CaloFutureTools +#include "FutureSubClusterSelectorBase.h" +// CaloFutureUtils +#include "CaloFutureUtils/CellSwissCross.h" + + +class FutureSubClusterSelectorSwissCross : public FutureSubClusterSelectorBase{ +public: + StatusCode initialize() override; + + StatusCode tag ( LHCb::CaloCluster* cluster)const override; + StatusCode untag ( LHCb::CaloCluster* cluster ) const override; + + FutureSubClusterSelectorSwissCross( const std::string& type , + const std::string& name , + const IInterface* parent ); + +private: + + CellSwissCross m_matrix; + +}; + +#endif diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ceec0367a1738af6ec090bc8b477b0c12b8043fe --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.cpp @@ -0,0 +1,209 @@ +// Include files + +// local +#include "FutureSubClusterSelectorTool.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : FutureSubClusterSelectorTool +// +// 2014-06-20 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( FutureSubClusterSelectorTool ) + + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +FutureSubClusterSelectorTool::FutureSubClusterSelectorTool( const std::string& type, + const std::string& name, + const IInterface* parent ) + : GaudiTool ( type, name , parent ) +{ + declareInterface<FutureSubClusterSelectorTool>(this); + StringArrayProperty eTags( "EnergyTags" , m_taggerE ) ; + StringArrayProperty pTags( "PositionTags" , m_taggerP ) ; + + // inherit properties from parents + if( 0 != parent ){ + const IProperty* prop = dynamic_cast<const IProperty*> ( parent ); + if( 0 != prop ){ + StatusCode sc1=prop->getProperty( &eTags ); + if( sc1.isSuccess() )m_taggerE = eTags.value(); + StatusCode sc2=prop->getProperty( &pTags ); + if( sc2.isSuccess() )m_taggerP = pTags.value(); + } + } + + // declare Properties + declareProperty("EnergyTags" , m_taggerE ); + declareProperty("PositionTags" , m_taggerP ); + + // define calo-dependent property + m_det = LHCb::CaloFutureAlgUtils::DeCaloFutureLocation( name ) ; + m_condition = "Conditions/Reco/Calo/"+ LHCb::CaloFutureAlgUtils::CaloFutureNameFromAlg( name ) + "ClusterMasks"; + + // apply local default setting if not defined by parent + if (m_taggerE.empty()) m_taggerE = std::vector<std::string>(1,"useDB"); + if (m_taggerP.empty()) m_taggerP = std::vector<std::string>(1,"useDB"); + +} + +//============================================================================= + +StatusCode FutureSubClusterSelectorTool::initialize() { + StatusCode sc = GaudiTool::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; // error printed already by GaudiTool + if ( msgLevel(MSG::DEBUG) ) debug() << "==> Initialize" << endmsg; + + // register to incident service + IIncidentSvc* inc = incSvc() ; + if ( 0 != inc )inc -> addListener ( this , IncidentType::BeginEvent ) ; + + // get detector element + m_detector = getDet<DeCalorimeter> ( m_det ); + if( NULL == m_detector)return Error("Cannot access DetectorElement at '"+m_det,StatusCode::FAILURE); + + // setup DB accessor tool + m_dbAccessor = tool<CaloFutureCorrectionBase>("CaloFutureCorrectionBase","DBAccessor",this); + sc = m_dbAccessor->setConditionParams(m_condition,true);// force access via DB - if not exist will return empty params + if(sc.isFailure())return Warning("Cannot access DB",StatusCode::FAILURE); + m_DBtaggerE=std::vector<std::string>(m_detector->numberOfAreas(),"unset"); + m_DBtaggerP=std::vector<std::string>(m_detector->numberOfAreas(),"unset"); + m_sourceE=" (none)"; + m_sourceP=" (none)"; + + // always set options parameters first + sc=getParamsFromOptions(); + if( sc.isFailure())return Error("Cannot setup initial parameters",StatusCode::FAILURE); + + + // then possibly update from DB + updateParamsFromDB(); + + info() << " Energy mask : " << m_DBtaggerE << m_sourceE << endmsg; + info() << " Position mask : " << m_DBtaggerP << m_sourceP << endmsg; + + return sc; +} + + +StatusCode FutureSubClusterSelectorTool::tagEnergy( LHCb::CaloCluster* cluster ){ + // get the tagger + LHCb::CaloCellID id = cluster->seed(); + ICaloFutureSubClusterTag* tagger = ( id.area() < m_tagE.size() ) ? m_tagE[id.area()] : NULL ; + if( NULL == tagger )return Warning( "Tagger not found" , StatusCode::FAILURE); + return tagger->tag(cluster); +} + +StatusCode FutureSubClusterSelectorTool::tagPosition( LHCb::CaloCluster* cluster ){ + // get the tagger + LHCb::CaloCellID id = cluster->seed(); + ICaloFutureSubClusterTag* tagger = ( id.area() < m_tagP.size() ) ? m_tagP[id.area()] : NULL ; + if( NULL == tagger )return Warning( "Tagger not found" , StatusCode::FAILURE); + return tagger->tag(cluster); +} + +StatusCode FutureSubClusterSelectorTool::tag( LHCb::CaloCluster* cluster ){ + StatusCode sc; + sc = tagEnergy( cluster); + sc = tagPosition(cluster ); + return sc; +} + + +void FutureSubClusterSelectorTool::updateParamsFromDB(){ + + using namespace CaloFutureClusterMask; + unsigned int narea = m_detector->numberOfAreas(); + for( unsigned int area = 0 ; area < narea ; ++area){ + LHCb::CaloCellID id = LHCb::CaloCellID(m_detector->caloName(), area ,0,0); + + if( m_taggerE[area] == "useDB"){ + m_sourceE=" (from DB) "; + Mask maskE = (Mask) m_dbAccessor->getParameter(CaloFutureCorrection::EnergyMask ,0, id , 0.); // default is 3x3 when no DB + std::string nameE=maskName[maskE]; + if( nameE != m_DBtaggerE[area] ){ // DB has changed ! update ! + std::string taggerE = (m_clusterTaggers.find(nameE) != m_clusterTaggers.end()) ? m_clusterTaggers[nameE] : ""; + if(taggerE != ""){ + ICaloFutureSubClusterTag* tE = tool<ICaloFutureSubClusterTag>(taggerE,id.areaName()+"EnergyTagger",this); + tE->setMask(m_energyStatus); + m_tagE.push_back( tE ); + m_DBtaggerE[area] = nameE; + }else + Warning("Cannot update energy mask from DB",StatusCode::FAILURE).ignore(); + } + } + + if( m_taggerP[area] == "useDB"){ + m_sourceP=" (from DB) "; + Mask maskP = (Mask) m_dbAccessor->getParameter(CaloFutureCorrection::PositionMask ,0, id , 0.); // default is 3x3 when no DB + std::string nameP=maskName[maskP]; + if( nameP != m_DBtaggerP[area] ){ // DB has changed ! update ! + std::string taggerP = (m_clusterTaggers.find(nameP) != m_clusterTaggers.end()) ? m_clusterTaggers[nameP] : ""; + if(taggerP != ""){ + ICaloFutureSubClusterTag* tP = tool<ICaloFutureSubClusterTag>(taggerP,id.areaName()+"PositionTagger",this); + tP->setMask(m_positionStatus); + m_tagP.push_back( tP ); + m_DBtaggerP[area] = nameP; + }else + Warning("Cannot update position mask from DB",StatusCode::FAILURE).ignore(); + } + } + } +} + + + + +StatusCode FutureSubClusterSelectorTool::getParamsFromOptions(){ + + unsigned int narea = m_detector->numberOfAreas(); + + // extend tagger per area when needed + if( m_taggerE.size() == 1)m_taggerE = std::vector<std::string>(narea , m_taggerE[0]); + if( m_taggerP.size() == 1)m_taggerP = std::vector<std::string>(narea , m_taggerP[0]); + if( m_taggerE.size() != m_detector->numberOfAreas() || m_taggerP.size() != m_detector->numberOfAreas()) + return Error("You must define the tagger for each calo area"); + + using namespace CaloFutureClusterMask; + // == Define Energy tagger per area + m_DBtaggerE=std::vector<std::string>(narea,"unset"); + m_DBtaggerP=std::vector<std::string>(narea,"unset"); + + for( unsigned int area = 0 ; area < narea ; ++area){ + std::string areaName = LHCb::CaloCellID(m_detector->caloName(), area ,0,0).areaName(); + + std::string nameE = m_taggerE[area] ; + if( nameE != "useDB" ){ + m_sourceE=" (from options) "; + std::string taggerE = (m_clusterTaggers.find(nameE) != m_clusterTaggers.end()) ? m_clusterTaggers[nameE] : ""; + if(taggerE == "") + return Error("Cannot find a '"+nameE+"' tagger - You must select or define a known tagging method",StatusCode::FAILURE); + ICaloFutureSubClusterTag* tE = tool<ICaloFutureSubClusterTag>(taggerE,areaName+"EnergyTagger",this); + tE->setMask(m_energyStatus); + m_tagE.push_back( tE ); + m_DBtaggerE[area]=nameE; + } + + std::string nameP = m_taggerP[area] ; + if( nameP != "useDB" ){ + m_sourceP=" (from options) "; + std::string taggerP = (m_clusterTaggers.find(nameP) != m_clusterTaggers.end()) ? m_clusterTaggers[nameP] : ""; + if(taggerP == "") + return Error("Cannot find a '"+nameP+"' tagger - You must select or define a known tagging method",StatusCode::FAILURE); + ICaloFutureSubClusterTag* tP= tool<ICaloFutureSubClusterTag>(taggerP,areaName+"PositionTagger",this); + tP->setMask(m_positionStatus); + m_tagP.push_back( tP ); + m_DBtaggerP[area]=nameP; + } + } + + return StatusCode::SUCCESS; +} + + +StatusCode FutureSubClusterSelectorTool::finalize() { + return GaudiTool::finalize(); // must be called after all other actions +} diff --git a/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h new file mode 100644 index 0000000000000000000000000000000000000000..412e8fce099490fb69a05f106994e107acd55b6b --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/FutureSubClusterSelectorTool.h @@ -0,0 +1,92 @@ +#ifndef SUBCLUSTERSELECTORTOOL_H +#define SUBCLUSTERSELECTORTOOL_H 1 + + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiTool.h" +#include "GaudiKernel/IIncidentListener.h" +#include "GaudiKernel/IIncidentSvc.h" +#include "GaudiKernel/Incident.h" +#include "CaloDet/DeCalorimeter.h" +#include "Event/CaloCluster.h" +#include "CaloFutureCorrectionBase.h" +#include "CaloFutureInterfaces/ICaloFutureSubClusterTag.h" + + +namespace CaloFutureClusterMask { + enum Mask{area3x3 = 0 , // MUST BE 0 FOR BACKWARD COMPATIBILITY + area2x2 = 1 , + SwissCross = 2 , + Last + }; + static const int nMask = Last+1; + static const std::string maskName[nMask] = { "3x3", "2x2","SwissCross","Unknown" }; +} + + + +static const InterfaceID IID_FutureSubClusterSelectorTool ( "FutureSubClusterSelectorTool", 1, 0 ); + +/** @class FutureSubClusterSelectorTool FutureSubClusterSelectorTool.h + * + * + * @author Olivier Deschamps + * @date 2014-06-20 + */ +class FutureSubClusterSelectorTool : public GaudiTool, virtual public IIncidentListener { +public: + + // Return the interface ID + static const InterfaceID& interfaceID() { return IID_FutureSubClusterSelectorTool; } + + /// Standard constructor + FutureSubClusterSelectorTool( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + StatusCode finalize() override; + + void handle(const Incident& ) override { + if( UNLIKELY( msgLevel(MSG::DEBUG) ) )debug() << "IIncident Svc reset" << endmsg; + updateParamsFromDB(); + } + + StatusCode getParamsFromOptions(); + void updateParamsFromDB(); + + StatusCode tag(LHCb::CaloCluster* cluster); + StatusCode tagEnergy(LHCb::CaloCluster* cluster); + StatusCode tagPosition(LHCb::CaloCluster* cluster); + +private: + + std::vector<std::string> m_taggerE ; + std::vector<std::string> m_taggerP ; + std::vector<ICaloFutureSubClusterTag*> m_tagE ; + std::vector<ICaloFutureSubClusterTag*> m_tagP ; + + // associate known cluster mask to tagger tool + Gaudi::Property<std::map<std::string,std::string>> m_clusterTaggers + {this, "ClusterTaggers", { + {"" , "useDB"}, + {"useDB" , "useDB"}, + {"3x3" , "FutureSubClusterSelector3x3"}, + {"2x2" , "FutureSubClusterSelector2x2"}, + {"SwissCross", "FutureSubClusterSelectorSwissCross"}, + }, "associate known cluster mask to tagger tool"}; + + Gaudi::Property<std::string> m_condition {this, "ConditionName", ""}; + Gaudi::Property<std::string> m_det {this, "Detector"}; + + DeCalorimeter* m_detector = nullptr; + CaloFutureCorrectionBase* m_dbAccessor = nullptr; + std::vector<std::string> m_DBtaggerE ; + std::vector<std::string> m_DBtaggerP ; + LHCb::CaloDigitStatus::Status m_energyStatus = LHCb::CaloDigitStatus::UseForEnergy | LHCb::CaloDigitStatus::UseForCovariance; + LHCb::CaloDigitStatus::Status m_positionStatus = LHCb::CaloDigitStatus::UseForPosition | LHCb::CaloDigitStatus::UseForCovariance; + std::string m_sourceE; + std::string m_sourceP; +}; +#endif // SUBCLUSTERSELECTORTOOL_H diff --git a/CaloFuture/CaloFutureReco/src/TaggedCellFunctor.h b/CaloFuture/CaloFutureReco/src/TaggedCellFunctor.h new file mode 100644 index 0000000000000000000000000000000000000000..bc66193c10df17da2a3804169b7fd5ad4ef01c95 --- /dev/null +++ b/CaloFuture/CaloFutureReco/src/TaggedCellFunctor.h @@ -0,0 +1,102 @@ +#ifndef CALOFUTURECA_TAGGEDCELLFUNCTOR_H +#define CALOFUTURECA_TAGGEDCELLFUNCTOR_H 1 +// ============================================================================ +// Include files +// ============================================================================ +// STL +// ============================================================================ +#include <vector> +#include <iostream> +// ============================================================================ +// local +// ============================================================================ +#include "CelAutoTaggedCell.h" +// ============================================================================ +/** @namespace TaggedCellFunctor TaggedCellFunctor.h CaloFutureCA/TaggedCellFunctor.h + * + * Algorithm of clustering + * Contain functors for use with STL algorithms + * for one CaloFutureTaggedCell* + * + * @author Nicole Brun + * @date 27/02/2001 + */ +// ============================================================================ +namespace TaggedCellFunctor +{ + struct isEdge; + struct isClustered; + struct isClusteredOrEdge; + struct isSeed; + class isWithSeed; + struct setStatus; +} +// ============================================================================ +struct TaggedCellFunctor::isEdge final { + // Function + inline bool operator() ( const CelAutoTaggedCell* taggedCell ) const { + return ( ( 0 == taggedCell ) ? false : taggedCell->isEdge() ); + } + + +}; + +struct TaggedCellFunctor::isClustered final { + // Function + + inline bool operator() ( const CelAutoTaggedCell* taggedCell ) const { + return ( ( 0 == taggedCell ) ? false : taggedCell->isClustered() ); + } + +}; + +struct TaggedCellFunctor::isClusteredOrEdge final { + // Function + + inline bool operator() ( const CelAutoTaggedCell* taggedCell ) const { + return ( ( 0 == taggedCell ) ? false : taggedCell->isClustered() || taggedCell->isEdge() ); + } + +}; + + +struct TaggedCellFunctor::isSeed final { + // Function + + inline bool operator() ( const CelAutoTaggedCell* taggedCell ) const { + return ( ( 0 == taggedCell ) ? false : taggedCell->isSeed() ); + } + +}; + +class TaggedCellFunctor::isWithSeed final { + + public: + // Constructor + + isWithSeed( const LHCb::CaloCellID& seed ) : + m_seed ( seed ) {}; + + // Function + + inline bool operator() ( CelAutoTaggedCell* taggedCell ) const { + return ( ( 0 == taggedCell ) ? false : taggedCell->isWithSeed( m_seed ) ); + } + + private: + + LHCb::CaloCellID m_seed; + +}; + +struct TaggedCellFunctor::setStatus final { + + // Function + + inline void operator() ( CelAutoTaggedCell* taggedCell ) const { + taggedCell->setStatus(); + } + +}; + +#endif // CALOFUTURECA_TAGGEDCELLFUNCTOR_H diff --git a/CaloFuture/CaloFutureTools/CMakeLists.txt b/CaloFuture/CaloFutureTools/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..0e6d58a618d67c0fbeee1b41623137abc8499653 --- /dev/null +++ b/CaloFuture/CaloFutureTools/CMakeLists.txt @@ -0,0 +1,27 @@ +################################################################################ +# Package: CaloFutureTools +################################################################################ +gaudi_subdir(CaloFutureTools v6r13) + +gaudi_depends_on_subdirs(CaloFuture/CaloFutureInterfaces + CaloFuture/CaloFutureUtils + CaloFuture/CaloFutureDAQ + Det/CaloDet + Event/LinkerEvent + Event/RecEvent + Event/TrackEvent + GaudiAlg + Kernel/LHCbKernel + Kernel/LHCbMath + Kernel/Relations + Tr/TrackInterfaces) + +find_package(Boost) +find_package(ROOT) +find_package(XGBoost REQUIRED) +include_directories(SYSTEM ${ROOT_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) + +gaudi_add_module(CaloFutureTools + src/*.cpp + INCLUDE_DIRS Tr/TrackInterfaces XGBoost + LINK_LIBRARIES CaloFutureUtils CaloDetLib LinkerEvent RecEvent TrackEvent GaudiAlgLib LHCbKernel LHCbMathLib RelationsLib XGBoost) diff --git a/CaloFuture/CaloFutureTools/doc/release.notes b/CaloFuture/CaloFutureTools/doc/release.notes new file mode 100755 index 0000000000000000000000000000000000000000..17cca1b7a90064436886e76ed45fa32d80d97875 --- /dev/null +++ b/CaloFuture/CaloFutureTools/doc/release.notes @@ -0,0 +1,333 @@ +!------------------------------------------------------------------------------- +! Package : CaloFutureTools +! Responsible : Olivier Deschamps odescham@in2p3.fr +!------------------------------------------------------------------------------- + +! 2016-06-07 - Olivier Deschamps + - CaloFuture2MC tool : fix bug that affect the merged-pi0 matching based on CaloFutureHypo Linker table + +! 2016-09-05 - Olivier Deschamps + - propagate saturation & barycenter information + +! 2016-08-16 - Olivier Deschamps + - new tool : FutureCounterLevel + - implement counter() switch based on FutureCounterLevel tool + +!========================= CaloFutureTools v6r13 2016-03-17 ========================= +! 2016-02-29 - Olivier Deschamps + - fix coverity warning + +! 2016-02-22 - Marco Cattaneo + - Remove unnecessary friend ToolFactory declaration + +!========================= CaloFutureTools v6r12 2016-01-28 ========================= +! 2015-12-19 - O. Deschamps + - CaloFuture2MCTool : change default MC association to rely on CaloFutureHypo->MC Linker. In case the Linker doesn't exist + the chain CaloFutureHypo->CaloFutureCluster->CaloFutureDigit->MC is used (assuming the reconstruction version is consistent with the original CaloFutureHypos) + +! 2015-12-17 - Marco Cattaneo + - CaloFutureHypoEstimator.cpp: reorganise an if clause to avoid an FPE with clang + +!========================= CaloFutureTools v6r11 2015-11-23 ========================= +! 2015-11-06 - O. Deschamps + - fix clang compilation warnings + +!========================= CaloFutureTools v6r10p1 2015-10-13 ========================= +! 2015-08-12 - Gerhard Raven + - remove #include of obsolete Gaudi headers + +!========================= CaloFutureTools v6r10 2014-09-12 ========================= +! 2014-09-12 - O. Deschamps + - CaloFutureHypoEstimator.cpp : implement ClusterCode & ClusterFrac + +!========================= CaloFutureTools v6r9 2014-07-14 ========================= +! 2014-06-30 - Olivier Deschamps + - FutureGammaPi0SeparationTool : improve & speed-up the evaluation of Prs-related variables + protect against unphysical value + +! 2014-06-29 - Olivier Deschamps + - fix FPE's, compilation warnings & verbosity excess + +! 2014-06-27 - Olivier Deschamps + - FutureNeutralIDTool.{cpp,h} : (new) implementation for MLP-based neutralID + - CaloFutureHypoEstimator.h, FutureGammaPi0SeparationTool.h : update against reco changes + + +!========================= CaloFutureTools v6r8 2014-06-10 ========================= +! 2014-05-23 - Olivier Deschamps + - FutureGammaPi0SeparationTool.cpp : fix FPE + +!========================= CaloFutureTools v6r7 2013-10-24 ========================= +! 2013-10-09 - Olivier Deschamps + - CaloFutureGetterTool, CaloFuture2CaloFuture, FutureGammaPi0SeparationTool, CaloFutureHypo2CaloFuture : protect against the upgrade configuration with no Spd/Prs + +! 2013-10-04 - Olivier Deschamps + - Add CaloFutureRelationsGetter implementation + - Instrument CaloFutureHypoEstimator with CaloFutureRelationsGetter to access relations table + +!========================= CaloFutureTools v6r6 2013-07-18 ========================= +! 2013-06-13 - Marco Cattaneo + - Fix Coverity DIVIDE_BY_ZERO and FORWARD_NULL defects + +!========================= CaloFutureTools v6r5p1 2013-06-03 ======================= +! 2013-05-27 - Marco Cattaneo + - Fix clang32 warning + - Remove 'do nothing' finalize methods + +!========================= CaloFutureTools v6r5 2012-11-28 ========================= +! 2012-11-21 - Marco Clemencic + - Added CMake configuration file. + - Fixed a warning (-pedantic). + +! 2012-10-19 - Marco Cattaneo + - Fix gcc -pedantic warnings + - Use getItExists where appropriate + +!========================= CaloFutureTools v6r4 2012-06-25 ========================= +! 2012-05-29 - Marco Cattaneo + - Fix unused variable in previous commit + - Fix UNINIT_CTOR defects + +! 2012-05-22 - Olivier Deschamps for Miriam Calvo + - FutureGammaPi0SeparationTool : new version of the tool (incl. Prs info) + +! 2012-05-14 - Olivier Deschamps + - new algorithm : CheckCaloFutureHypoRef - check CaloFutureHypo->CaloFutureCluster* smart + reference backward compatibility + +! 2012-05-10 - Olivier Deschamps + - L0CaloFuture2CaloFuture tool : default clusterization level set to 2 + (5x5 area for merged pi0) + +!========================= CaloFutureTools v6r3p1 2011-12-14 ========================= +! 2011-11-23 - Marco Cattaneo + - Fix trivial gcc warnings and icc remarks + +!========================= CaloFutureTools v6r3 2011-07-27 ========================= +! 2011-07-22 - Marco Cattaneo + - Create debug() messages only when output level requires it, + also using UNLIKELY macro + - Replace all endreq by endmsg + +! 2011-06-17 - Olivier Deschamps + - fix window compilation warning + +!========================= CaloFutureTools v6r2 2011-06-15 ========================= +! 2011-06-14 - Olivier Deschamps + - extend CaloFutureHypoEstimator : more Prs info + Gamma/pi0 separation info + - new FutureGammaPi0SeparationTool + related MLP files + +! 2011-05-16 - Olivier Deschamps + - L0CaloFuture2CaloFuture tool : clusterize around right seedID + +! 2011-05-13 - Olivier Deschamps + - L0CaloFuture2CaloFuture tool : allow for managing the cluster on TES externally (new default) + +!========================= CaloFutureTools v6r1 2011-02-01 ========================= +! 2011-01-21 - Olivier Deschamps + - Fix CaloFuture2MCTool initialization + +! 2011-01-19 - Marco Cattaneo + - Fix ICC warnings and remarks + +!========================= CaloFutureTools v6r0 2010-10-25 ========================= + +! 2010-10-07 - Dmitry Golubkov + - CaloFutureHypo2CaloFuture: change passing parameteres by value to const references + - increment version to v6r0 due to the change in the interface + +!========================== CaloFutureTools v5r17 2010-09-28 ========================= +! 2010-09-01 - Olivier Deschamps + - fix compilation error on windows + - improve Track2CaloFuture & CaloFutureHypoEstimator + +! 2010-08-31 - Olivier Deschamps + - fix compilation warning on slc4 + +! 2010-08-27 - O. Deschamps + - new tool CaloFutureHypoEstimator + update CaloFutureHypo2CaloFuture + +!========================== CaloFutureTools v5r16p1 2010-06-21 ======================= +! 2010-06-10 - Marco Cattaneo + - Fix Windows compilation warnings + +!========================== CaloFutureTools v5r16 2010-03-18 ========================= +! 2010-03-08 - Olivier Deschamps + - CaloFutureHypoToCaloFuture: Implement new virtual method _setProperty + +!========================== CaloFutureTools v5r15 2010-02-15 ========================= +! 2010-02-13 - Olivier Deschamps + - Track2CaloFuture : switch HeraBExtrapolator to RungeKutta + +!========================== CaloFutureTools v5r14 2009-11-27 ========================= +! 2009-11-17 - Olivier Deschamps + - CaloFuture2MCTool : + - new methods : + isCaloFuture(particle) + isPureNeutralCaloFuture(particle) + findMCOrBest(string/ParticleID,threshold) + - complete the code (still not fully completed) + +!========================== CaloFutureTools v5r13 2009-11-13 ========================= +! 2009-11-05 - Dmitry GOLUBKOV + - L0CaloFuture2CaloFutureTool : bugfix - make storage of all created clusters on TES the + only supported behaviour (therefore remove the 'DuplicateClustersOnTES' property), + use CaloFutureFunctors::neighbours() instead of look_neig() + - cmt/requirements version increment to v5r13 + +!========================== CaloFutureTools v5r12 2009-10-20 ========================= +! 2009-12-21 - Olivier Deschamps + - adapt to change in CaloFutureDAQ + - improve CaloFuture2MCTool.{cpp,h} : not yet complete but usable + +! 2009-09-15 - Olivier Deschamps + - new tool : CaloFuture2MCTool.{cpp,h} : handle CaloFuture object->MC relation + (interface CaloFutureInterfaces/ICaloFuture2MCTool.h) + - preliminary (incomplete) version of the tool + - use Relations in requirements + +! 2009-09-14 - Olivier Deschamps + - adapt to change in CaloFutureDAQ/CaloFutureReadoutTool + (->CaloFutureCosmicsTool & CaloFutureGetterTool & L0CaloFuture2CaloFutureTool) + +! 2009-09-11 - Olivier Deschamps + - CaloFuture2CaloFuture.cpp : + - make use of CaloFutureAlgUtils.h to define context-dependent TES I/O + - caloGetterTool : public -> private tool + - use caloGetterTool in isLocMax(id) method + + +! 2009-09-11 - Olivier Deschamps + - CalOGetterTool.cpp : make use of CaloFutureAlgUtils.h to define context-dependent TES I/O + +! 2009-09-04 - Dmitry Golubkov + - cmt/requirements version increment to v5r12 + - release.notes : fix the order of the comments 2009-08-02 + - L0CaloFuture2CaloFutureTool.cpp: decrease error level for invalid ur/dr/ul cells + +!========================== CaloFutureTools v5r11 2009-09-03 ========================= +! 2009-09-03 - Marco Cattaneo + - Remove obsolete file src/CaloFutureTools_dll.cpp + +! 2009-08-05 - Stephanie Hansmann-Menzemer + - remove filling of track-extra info, according to changes in Track.xml class + +!========================== CaloFutureTools v5r10p1 2009-09-07 ========================= +! 2009-09-04 - Dmitry Golubkov + - L0CaloFuture2CaloFutureTool.cpp: decrease error level for invalid ur/dr/ul cells + +!========================== CaloFutureTools v5r10 2009-08-31 ========================= + +! 2009-12-10 - Olivier Deschamps + - adapt to change in CaloFutureDAQ + +! 2009-08-10 - Vanya BELYAEV + - CaloFuture2CaloFuture & CaloFutureGetter + fix the problem of mandatory "update" + +! 2009-08-05 - Vanya BELYAEV + - fix the signature + +! 2009-08-02 - Dmitry GOLUBKOV + - L0CaloFuture2CaloFutureTool.cpp: method to return CaloFutureClusters around the CaloFutureCellID + +! 2009-07-31 - Dmitry Golubkov + - L0CaloFuture2CaloFutureTool.cpp - fix compilation warnings on slc4 + +! 2009-07-29 - Dmitry GOLUBKOV + - Add a new tool to get a list of CaloFutureClusters for the input L0CaloFutureCandidate(s) + L0CaloFuture2CaloFutureTool.cpp, L0CaloFuture2CaloFutureTool.h + - cmt/requirements verison increment to v5r10 + +!========================== CaloFutureTools v5r9 2009-06-03 ========================= +! 2009-06-03 - Marco Cattaneo + - Add missing CaloFutureTools_dll.cpp file + +! 2009-05-19 - Marco Cattaneo + - Add missing #include "Event/Particle.h" following removal from IPart2CaloFuture.h + - Replace endreq by endmsg + +! 2009-05-10 - Vanya Belyaev + - a bit more statistical prinout + - cmt/requirements + verison increment to v5r9 + +!========================== CaloFutureTools v5r8 2009-05-08 ========================= +! 2008-04-17 - Olivier Deschamps + - new tool CaloFutureGetterTool : helps to speed-up CaloFutureReco processing + - CaloFuture2CaloFuture/CaloFutureHypo2CaloFuture : get digits data via CaloFutureGetterTool + +! 2009-04-16 Olivier Deschamps + - CaloFuture2CaloFuture/CaloFutureHypo2CaloFuture : speed-up processing + new property ('IdealGeometry') + when perfect alignment is assumed + +!========================== CaloFutureTools v5r7 2009-03-10 ========================= +! 2009-03-09 Olivier Deschamps + - Fix bad default setting for CaloFutureHypo2CaloFuture.cpp (Seed=false -> true) + minor bug fix + +! 2009-03-05 Olivier Deschamps + - improve verbosity for CaloFutureCosmics stuff + +!========================== CaloFutureTools v5r6 2009-01-12 ========================= +! 2008-12-10 - Marco Cattaneo + - Fix gcc 4.3 warnings + +! 2008-12-05 - Olivier Deschamps + - CaloFutureCosmicsTrackTool :: fix bug in Hcal timing + +!========================== CaloFutureTools v5r5 2008-10-01 ========================= +! 2008-09-11 - Olivier Deschamps + - CaloFuture2CaloFuture :: add multiplicity method + - new tool : CaloFutureHypo2CaloFuture : specialized version of CaloFuture2CaloFuture + +!========================== CaloFutureTools v5r4 2008-09-04 ========================= +! 2008-08-21 - Olivier Deschamps + - CaloFutureCosmicsTrackAlg : add monitoring histo for cosmics track (theta,phi) parameters + - CaloFutureCosmicsTool : add cellId vector in the output ntuple + +!========================== CaloFutureTools v5r3 2008-07-29 ========================= +! 2008-07-21 - Marco Cattaneo + - Adapt to new location of IEventTimeDecoder.h (needs Gaudi v20r2) + +!========================== CaloFutureTools v5r2 2008-07-02 ========================= +! 2008-06-30 - Olivier Deschamps + - add asymmetry monitoring in CaloFutureCosmicsTrackAlg + - add 'kernel' variable computation in CaloFutureCosmicsTool + +! 2008-06-26 - Juan PALACIOS + - cmt/requirements + . Increase version to v5r2 + - src/CaloFutureCosmicsTool.cpp + - src/CaloFutureCosmicsTrackTool.cpp + - src/Track2CaloFuture.cpp + . Change all Gaudi::XYZLine and Gaudi::Line for Gaudi::Math::XYZLine and + Gaudi::Math::XYZLine respectively (adapting to Kernel/LHCbMath v3) + +!========================== CaloFutureTools v5r1 2008-06-05 ========================= +! 2008-06-05 - Marco Cattaneo + - Fix acos() for windows (cannot take an int argument) + +! 2008-06-04 - Deschamps Olivier + - tune the verbosity + +! 2008-06-03 - Marco Cattaneo + - In CaloFutureCosmicsTool.cpp: fix compiler warning, add missing include + - In CaloFutureCosmicsTrackTool.cpp, CaloFutureCosmicsTrackAlg.cpp: add missing includes + +! 2008-05-29 - Deschamps Olivier + - use dedicated TrackEvent/Track flags + +! 2008-05-29 - Deschamps Olivier + - add more monitoring histo (split monitoring according to forward/backward cosmics tracks) + +! 2008-05-27 - Deschamps Olivier + - fix bug in CaloFutureCosmicsTrackTool.cpp (Hcal state replicated Ecal state) + +! 2008-05-22 - Deschamps Olivier + - Add new tools and alg for cosmics track reconstruction in calorimeter : + CaloFutureCosmicsTool, CaloFutureCosmicsTrackTool, CaloFutureCosmicsTrackAlg + +!========================== CaloFutureTools v5r0 2008-05-08 ========================= +! 2008-05-08 - Marco Cattaneo + - Resurrect CaloFutureTools package (declared obsolete in 2002). It is now a + component library for CaloFuturerimeter Tools, previously in CaloFutureUtils link library diff --git a/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.cpp b/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..593bb857fb18cfd4ccf7b000dfe2353143679c27 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.cpp @@ -0,0 +1,295 @@ +// ============================================================================ +// Include files +// ============================================================================ +#include "Kernel/CaloCellCode.h" +// ============================================================================ +// CaloFutureUtils +// ============================================================================ +#include "CaloFutureUtils/CaloFutureDataFunctor.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +// ============================================================================ +// local +// ============================================================================ +#include "CaloFuture2CaloFuture.h" +// ============================================================================ +/** @file + * Implementation file for class : CaloFuture2CaloFuture + * @date 2007-05-29 + * @author Olivier Deschamps + */ +// ============================================================================ +// Declaration of the Tool Factory +DECLARE_COMPONENT( CaloFuture2CaloFuture ) +// ============================================================================ + + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +CaloFuture2CaloFuture::CaloFuture2CaloFuture( const std::string& type, + const std::string& name, + const IInterface* parent ) + : base_class ( type, name , parent ) +{ + declareInterface<ICaloFuture2CaloFuture>(this); +} +//============================================================================= +StatusCode CaloFuture2CaloFuture::initialize() +{ + StatusCode sc = base_class::initialize(); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Initialize CaloFuture2CaloFuture tool " << endmsg; + + // get getter tool : public tool + m_getter = tool<ICaloFutureGetterTool>("CaloFutureGetterTool",m_getterName); + + // CaloDigit locations + m_loc["Ecal"]= LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation( "Ecal" , context() ); + m_loc["Hcal"]= LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation( "Hcal" , context() ); + m_loc["Prs"] = LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation( "Prs" , context() ); + m_loc["Spd"] = LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation( "Spd" , context() ); + // DeCalorimeter* pointers + int mask=m_getter->detectorsMask(); + m_det["Ecal"]=getDet<DeCalorimeter>( DeCalorimeterLocation::Ecal ); + m_det["Hcal"]=getDet<DeCalorimeter>( DeCalorimeterLocation::Hcal ); + m_det["Prs"]=((mask&2)==0) ? NULL : getDetIfExists<DeCalorimeter>( DeCalorimeterLocation::Prs ); + m_det["Spd"]=((mask&1)==0) ? NULL : getDetIfExists<DeCalorimeter>( DeCalorimeterLocation::Spd ); + // CellSize reference (outer section) Warning : factor 2 for Hcal + m_refSize["Hcal"] = (*(m_det["Hcal"]->cellParams().begin())).size()/2.; + m_refSize["Ecal"] = (*(m_det["Ecal"]->cellParams().begin())).size(); + if(NULL != m_det["Prs"])m_refSize["Prs"] = (*(m_det["Prs"]->cellParams().begin())).size(); + if(NULL != m_det["Spd"])m_refSize["Spd"] = (*(m_det["Spd"]->cellParams().begin())).size(); + // CaloPlanes + m_plane["Hcal"] = m_det["Hcal"]->plane(CaloPlane::ShowerMax ); + m_plane["Ecal"] = m_det["Ecal"]->plane(CaloPlane::ShowerMax ); + if(NULL != m_det["Prs"])m_plane["Prs"] = m_det["Prs"]->plane(CaloPlane::ShowerMax ); + if(NULL != m_det["Spd"])m_plane["Spd"] = m_det["Spd"]->plane(CaloPlane::ShowerMax ); + + reset(); + + if((m_fromCaloFuture == "Hcal" || m_fromCaloFuture == "Ecal" || m_fromCaloFuture == "Prs" || m_fromCaloFuture == "Spd" ) && + (m_toCaloFuture == "Hcal" || m_toCaloFuture == "Ecal" || m_toCaloFuture == "Prs" || m_toCaloFuture == "Spd" ) )setCalos(m_fromCaloFuture,m_toCaloFuture); + // + + if( UNLIKELY( msgLevel(MSG::DEBUG) )){ + if( NULL == m_det["Prs"] && (m_fromCaloFuture=="Prs" || m_toCaloFuture=="Prs")) + debug() << "Try to access non-existing Prs DetectorElement" << endmsg; + if( NULL == m_det["Spd"] && (m_fromCaloFuture=="Spd" || m_toCaloFuture=="Spd")) + debug() << "Try to access non-existing Spd DetectorElement" << endmsg; + } + return sc; +} + +void CaloFuture2CaloFuture::reset(){ + m_digits.clear(); + m_cells.clear(); + m_energy = 0; + m_count = 0; +} + +void CaloFuture2CaloFuture::setCalos +( const std::string& fromCaloFuture , + const std::string& toCaloFuture ) +{ + + m_ok = true; + if( NULL == m_det["Prs"] && (fromCaloFuture=="Prs" || toCaloFuture=="Prs")){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) )debug() <<"Try to access non-existing Prs DetectorElement"<<endmsg; + m_ok = false; + return; + } + + if( NULL == m_det["Spd"] && (fromCaloFuture=="Spd" || toCaloFuture=="Spd")){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) )debug() <<"Try to access non-existing Spd DetectorElement"<<endmsg; + m_ok=false; + return; + } + + m_fromCaloFuture = fromCaloFuture; + m_toCaloFuture = toCaloFuture; + m_fromDet = m_det[m_fromCaloFuture]; + m_fromSize = m_refSize[m_fromCaloFuture]; + m_toDet = m_det[m_toCaloFuture]; + m_toPlane = m_plane[m_toCaloFuture]; + m_toSize = m_refSize[m_toCaloFuture]; + m_toLoc = m_loc[ m_toCaloFuture ]; + + + + + } +//======================================================================================================= +const std::vector<LHCb::CaloCellID>& CaloFuture2CaloFuture::cellIDs ( const LHCb::CaloCluster& fromCluster , + const std::string& toCaloFuture ){ + + reset(); + LHCb::CaloCellID seedID = fromCluster.seed(); + std::string fromCaloFuture = CaloCellCode::CaloNameFromNum( seedID.calo() ); + if( toCaloFuture != m_toCaloFuture || fromCaloFuture != m_fromCaloFuture)setCalos(fromCaloFuture,toCaloFuture); + if( !m_ok )return m_cells; + + for(const auto& ent : fromCluster.entries() ) { + const LHCb::CaloDigit* digit = ent.digit(); + if ( digit ) cellIDs( digit->cellID() , toCaloFuture, false ); + } + return m_cells; +} +//======================================================================================================= +const std::vector<LHCb::CaloCellID>& CaloFuture2CaloFuture::addCell( const LHCb::CaloCellID& id , + const std::string& toCaloFuture ){ + + if( !m_ok )return m_cells; + // consistency check + if( CaloCellCode::CaloNameFromNum(id.calo()) != m_toCaloFuture || toCaloFuture != m_toCaloFuture ){ + Warning("CellID is not consistent with CaloFuture setting").ignore(); + return m_cells; + } + // check duplicate + if ( m_cells.end() != std::find ( m_cells.begin() , m_cells.end() , id ) ) { return m_cells ; } + + // add the cells + m_cells.push_back( id ); + + // added by VB. + if ( 0 == m_digs ) + { + Error ( "Digits* points to NULL") ; + return m_cells ; + } + + LHCb::CaloDigit* digit = m_digs->object( id ); + if( NULL != digit ) { + m_digits.push_back( digit ); + m_energy += digit->e(); + m_count++; + } + return m_cells; +} + + +//======================================================================================================= +const std::vector<LHCb::CaloCellID>& +CaloFuture2CaloFuture::cellIDs ( const LHCb::CaloCellID& fromId , + const std::string& toCaloFuture , bool init ){ + + if( init )reset(); + std::string fromCaloFuture = CaloCellCode::CaloNameFromNum( fromId.calo() ); + if( toCaloFuture != m_toCaloFuture || fromCaloFuture != m_fromCaloFuture)setCalos(fromCaloFuture,toCaloFuture); + if( !m_ok )return m_cells; + + LHCb::CaloCellID toId = fromId; + // ---- Assume ideal geometry : trivial mapping for detectors having the same granularity (Prs/Spd/Ecal) + if( ( m_geo && (m_fromCaloFuture == "Ecal" || m_fromCaloFuture == "Prs" || m_fromCaloFuture == "Spd") + && (m_toCaloFuture == "Ecal" || m_toCaloFuture == "Prs" || m_toCaloFuture == "Spd") ) + || m_fromCaloFuture.value() == m_toCaloFuture.value() ){ + toId.setCalo( CaloCellCode::CaloNumFromName( m_toCaloFuture )); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Add cell from trivial mapping" << endmsg; + return addCell( toId , m_toCaloFuture); + } + + // ---- Else use the actual geometry to connet detectors + double scale = 1.; + Gaudi::XYZPoint center = m_fromDet->cellCenter( fromId ); + if( m_fromCaloFuture.value() != m_toCaloFuture.value() ){ + // z-scaling + scale = m_toSize / m_fromSize ; + center = m_toPlane.ProjectOntoPlane( m_fromDet->cellCenter( fromId )*scale ); + // connect + toId = m_toDet->Cell( center ); + } + double fromSize = m_fromDet->cellSize( fromId )*scale; + //cell-center is outside 'toCaloFuture' - check corners + if( LHCb::CaloCellID() == toId){ + for( int i = 0 ; i != 2; ++i){ + for( int j = 0 ; j != 2; ++j){ + double x = m_fromDet->cellCenter( fromId ).X() + (i*2-1) * fromSize; + double y = m_fromDet->cellCenter( fromId ).Y() + (j*2-1) * fromSize; + Gaudi::XYZPoint corner = Gaudi::XYZPoint(x,y,center.Z()); + LHCb::CaloCellID cornerId = m_toDet->Cell( corner ); + if( LHCb::CaloCellID() == cornerId)continue; + toId=cornerId; + } + } + } + if( LHCb::CaloCellID() == toId)return m_cells; + int pad = 1; + double x0 = center.X(); + double y0 = center.Y(); + if( m_fromDet != m_toDet ){ + double toSize = m_toDet->cellSize( toId ) ; + pad = (int) floor( fromSize / toSize + 0.25); // warning int precision + if(pad < 1)pad=1; + x0 = center.X() - (pad-1)*fromSize/2./pad; + y0 = center.Y() - (pad-1)*fromSize/2./pad; + } + for( int i = 0 ; i != pad; ++i){ + for( int j = 0 ; j != pad; ++j){ + double x = x0 + i * fromSize/pad; + double y = y0 + j * fromSize/pad; + Gaudi::XYZPoint pos(x,y,center.Z()); + if( m_fromDet != m_toDet ) toId = m_toDet->Cell( pos ) ; + if( LHCb::CaloCellID() == toId)continue; + addCell( toId, m_toCaloFuture); + } + } + return m_cells; +} + + +// Digits +const std::vector<LHCb::CaloDigit*>& CaloFuture2CaloFuture::digits( const LHCb::CaloCellID& fromId , + const std::string& toCaloFuture ){ + m_digs = m_getter->digits( m_toLoc ); + cellIDs( fromId, toCaloFuture ) ; + return m_digits; +} + +const std::vector<LHCb::CaloDigit*>& CaloFuture2CaloFuture::digits( const LHCb::CaloCluster& fromCluster , + const std::string& toCaloFuture ){ + m_digs = m_getter->digits( m_toLoc ); + cellIDs( fromCluster, toCaloFuture); + return m_digits; +} + +// Energy +double CaloFuture2CaloFuture::energy( const LHCb::CaloCellID& fromId , + const std::string& toCaloFuture ){ + m_digs = m_getter->digits( m_toLoc ); + cellIDs ( fromId , toCaloFuture ); + return m_energy; +} + + +int CaloFuture2CaloFuture::multiplicity( const LHCb::CaloCellID& fromId , + const std::string& toCaloFuture ){ + m_digs = m_getter->digits( m_toLoc ); + cellIDs(fromId, toCaloFuture); + return m_count; +} + +double CaloFuture2CaloFuture::energy( const LHCb::CaloCluster& fromCluster , + const std::string& toCaloFuture ){ + m_digs = m_getter->digits( m_toLoc ); + cellIDs(fromCluster, toCaloFuture); + return m_energy; +} + + +int CaloFuture2CaloFuture::multiplicity( const LHCb::CaloCluster& fromCluster , + const std::string& toCaloFuture ){ + m_digs = m_getter->digits( m_toLoc ); + cellIDs(fromCluster, toCaloFuture); + return m_count; +} + +// ============================================================================ +// Additional method : isLocalMax +bool CaloFuture2CaloFuture::isLocalMax ( const LHCb::CaloDigit& digit){ + const LHCb::CaloCellID& id = digit.cellID(); + std::string calo = CaloCellCode::CaloNameFromNum( id.calo() ); + DeCalorimeter* det = m_det[ calo ]; + const LHCb::CaloDigits* digits = m_getter->digits( m_loc[ calo ] ); + // + return LHCb::CaloFutureDataFunctor::isLocalMax ( &digit , det , digits ) ; +} diff --git a/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.h b/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.h new file mode 100644 index 0000000000000000000000000000000000000000..4396771bc034b7832afce97bca0d8920afd1ba3c --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFuture2CaloFuture.h @@ -0,0 +1,90 @@ +#ifndef CALOFUTURE2CALOFUTURE_H +#define CALOFUTURE2CALOFUTURE_H 1 + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiTool.h" +#include "CaloFutureInterfaces/ICaloFuture2CaloFuture.h" // Interface +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureInterfaces/ICaloFutureGetterTool.h" +/** @class CaloFuture2CaloFuture CaloFuture2CaloFuture.h + * + * + * @author Olivier Deschamps + * @date 2007-05-29 + */ + +class CaloFuture2CaloFuture : public extends<GaudiTool, ICaloFuture2CaloFuture> { +public: + /// Standard constructor + CaloFuture2CaloFuture( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + // setting + void setCalos ( const std::string& fromCaloFuture , + const std::string& toCaloFuture ) override; + // CaloCellIDs + const std::vector<LHCb::CaloCellID>& + cellIDs ( const LHCb::CaloCluster& fromCluster , + const std::string& toCaloFuture ) override; + const std::vector<LHCb::CaloCellID>& + cellIDs ( const LHCb::CaloCellID& fromId , + const std::string& toCaloFuture, bool init=true) override; + const std::vector<LHCb::CaloCellID>& cellIDs() override {return m_cells;}; + // Digits + const std::vector<LHCb::CaloDigit*>& digits + ( const LHCb::CaloCellID& fromId , + const std::string& toCaloFuture ) override; + const std::vector<LHCb::CaloDigit*>& digits + ( const LHCb::CaloCluster& fromCluster , + const std::string& toCaloFuture ) override; + const std::vector<LHCb::CaloDigit*>& digits() override {return m_digits;}; + // Energy + double energy ( const LHCb::CaloCellID& fromId , + const std::string& toCaloFuture ) override; + double energy ( const LHCb::CaloCluster& fromCluster , + const std::string& toCaloFuture ) override; + double energy () override {return m_energy;}; + // multiplicity + int multiplicity( const LHCb::CaloCellID& fromId , + const std::string& toCaloFuture ) override; + int multiplicity( const LHCb::CaloCluster& fromCluster , + const std::string& toCaloFuture ) override; + int multiplicity() override {return m_count;}; + // Additional + bool isLocalMax ( const LHCb::CaloDigit& digit) override; + +protected: + // + void reset(); + const std::vector<LHCb::CaloCellID>& addCell + ( const LHCb::CaloCellID& id, const std::string& toCaloFuture); + // CaloFuture Maps + std::map<std::string,DeCalorimeter*> m_det; + std::map<std::string,std::string> m_loc; + std::map<std::string,double>m_refSize; + std::map<std::string,Gaudi::Plane3D> m_plane; + // + Gaudi::Property<std::string> m_fromCaloFuture {this, "FromCaloFuture", "??"}; + Gaudi::Property<std::string> m_toCaloFuture {this, "ToCaloFuture", "??"}; + std::vector<LHCb::CaloCellID> m_cells; + std::vector<LHCb::CaloDigit*> m_digits; + double m_energy = 0.; + int m_count = 0; + DeCalorimeter* m_fromDet = nullptr; + DeCalorimeter* m_toDet = nullptr; + double m_fromSize = 0.; + double m_toSize = 0.; + std::string m_toLoc; + Gaudi::Plane3D m_toPlane; + LHCb::CaloDigits* m_digs = nullptr; + ICaloFutureGetterTool* m_getter = nullptr; + bool m_ok = true; +private: + Gaudi::Property<bool> m_geo {this, "IdealGeometry", true}; + Gaudi::Property<std::string> m_getterName {this, "GetterName", "CaloFutureGetter"}; + +}; +#endif // CALOFUTURE2CALOFUTURE_H diff --git a/CaloFuture/CaloFutureTools/src/CaloFuture2MCTool.cpp b/CaloFuture/CaloFutureTools/src/CaloFuture2MCTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7f31d715d0d8a60a842277fca1a402ce0dbcf651 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFuture2MCTool.cpp @@ -0,0 +1,559 @@ +// Include files +#include "boost/algorithm/string.hpp" + +// from LHCb +#include "Relations/RelationWeighted1D.h" +#include "CaloFutureUtils/CaloFutureParticle.h" +#include "CaloFutureUtils/CaloFuture2MC.h" +#include "GaudiKernel/IRegistry.h" +#include "Linker/LinkedTo.h" +#include "Linker/LinkedFrom.h" + +// local +#include "CaloFuture2MCTool.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : CaloFuture2MCTool +// +// 2009-07-27 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( CaloFuture2MCTool ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +CaloFuture2MCTool::CaloFuture2MCTool( const std::string& type, + const std::string& name, + const IInterface* parent ) + : base_class ( type, name , parent ) +{ + declareInterface<ICaloFuture2MCTool>(this); + m_cluster2MCLoc = "Relations/" + ( boost::iequals( context(), "HLT") + ? LHCb::CaloClusterLocation::DefaultHlt + : LHCb::CaloClusterLocation::Default ); +} + +//============================================================================= + + +StatusCode CaloFuture2MCTool::initialize(){ + StatusCode sc = base_class::initialize(); + if (sc.isFailure()) return Error("Failed to initialize", sc); + m_ppsvc = service( "LHCb::ParticlePropertySvc", true); + if( !m_ppsvc )return StatusCode::FAILURE; + + // incidentSvc + IIncidentSvc* inc = incSvc() ; + if ( 0 != inc )inc -> addListener ( this , IncidentType::BeginEvent ) ; + + + // init + counterStat = tool<IFutureCounterLevel>("FutureCounterLevel"); + m_digit = nullptr; + m_cluster = nullptr; + m_hypo = nullptr; + m_proto = nullptr; + m_part = nullptr; + m_digit2MC= nullptr; + m_cluster2MC=nullptr; + m_category = 0 ; + m_depth = -1 ; + //m_hypo2MC = nullptr; + // get fragment tool and propagate properties + m_tool = tool<ICaloFuture2MCTool>("CaloFuture2MCTool/CaloFutureFragment2MCTool"); // CAUTION : THE TOOL CANNOT BE PRIVATE !! + //@TODO: dynamic_cast to IProperty... remove IProperty from ICaloFuture2MCTool... + m_tool->setProperty ( "Cluster2MCTable" , m_cluster2MCLoc ) ; + m_tool->setProperty ( "Digit2MCTable" , m_digit2MCLoc ) ; + m_tool->setProperty ( "Cluster2Digits" , Gaudi::Utils::toString( m_cluster2Digit.value() ) ); + m_tool->setProperty ( "Hypo2Cluster" , Gaudi::Utils::toString( m_hypo2Cluster.value() ) ); + m_tool->setProperty ( "Merged2Split" , Gaudi::Utils::toString( m_merged2Split.value() ) ); + m_tool->setProperty ( "DigitStatusFilter" , Gaudi::Utils::toString( m_sFilter.value() ) ); + + m_sum = 0.; + m_maxMC = nullptr ; + m_bestMC = nullptr ; + + // + if( m_hypo2Cluster) { + Warning(" ... Hypo->Cluster reference is used in CaloFuture2MC ", StatusCode::SUCCESS).ignore(); + Warning(" ... CaloFutureCluster will be re-processed (require full DST)", StatusCode::SUCCESS).ignore(); + Warning(" ... assume an identical reconstruction version ", StatusCode::SUCCESS).ignore(); + } + // + clear(); + return StatusCode::SUCCESS; +} + + + + +/*-------------------------- from Part to MC ------------------------*/ +// associate single particle +ICaloFuture2MCTool* CaloFuture2MCTool::from(const LHCb::Particle* part ){ + if( part == m_part)return this; // process only if needed + + clear(); + m_depth = 4; // particle level + if( !part )return this; + + // check the particle is full calorimetric (using caloParticle functionalities) + LHCb::CaloFutureParticle cPart = LHCb::CaloFutureParticle( (LHCb::Particle*) part ); + if( !cPart.isCaloFuture() ){ + Warning("Cannot associate non-pure calorimetric particle to MC").ignore(); + return this; + } + + + // register final state particles + m_parts = cPart.caloEndTree(); + m_part = const_cast<LHCb::Particle*>(part); + if( m_parts.empty())m_parts.push_back( part ); + + + + // particle->protoparticle cascade (mandatory) + m_depth=3; // protoparticle level + for(const auto& fs : m_parts ) { + const LHCb::ProtoParticle* proto = fs->proto(); + if( !proto){ + Warning("ProtoParticle point to NULL (should not)").ignore(); + continue; + } + addProto( proto , fs ); + } + StatusCode sc = process(); + if ( sc.isFailure() )Warning("Processing CaloFuture2MCTool from Particle failed").ignore(); + return this; +} + + +/*-------------------------- from Proto to MC ------------------------*/ +// Accumulate protos->hypo()s [->clusters] +void CaloFuture2MCTool::addProto(const LHCb::ProtoParticle* proto, const LHCb::Particle* parent ){ + if( !proto)return; + + // register proto if not yet done + bool ok = std::none_of( m_protos.begin(), m_protos.end(), + [&](const LHCb::ProtoParticle* p) { return p == proto; } ); + if(!ok){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "ProtoParticle appears twice in the same decay chain" << endmsg; + if(counterStat->isQuiet())counter("ProtoParticle appears twice in the same decay chain" ) += 1.; + return; + } + m_protos.push_back( proto ) ; + + + // proto->hypo cascade (mandatory) + m_depth = 2; // hypo level + const auto& hypos = proto->calo(); + if( hypos.empty() )return; + + // special treatment for Bremstrahlung electrons + bool charged = ( proto->track() );/* charged part->proto */ + if (!charged) { + for( const auto& hypo : hypos ) addHypo( hypo ); + } else { + bool brem = ( parent && ( std::abs(parent->momentum().P() - proto->track()->firstState().p())> 1E-4 ) );/* bremstrahlung corrected particle */ + for( const auto& hypo : hypos ) { + if ( hypo->hypothesis() == LHCb::CaloHypo::Hypothesis::EmCharged || + ( brem && hypo->hypothesis() == LHCb::CaloHypo::Hypothesis::Photon ) ) addHypo(hypo); + } + } +} + +// associate single protoParticle +ICaloFuture2MCTool* CaloFuture2MCTool::from(const LHCb::ProtoParticle* proto ){ + if( proto == m_proto)return this; // process only if needed + clear(); + m_depth = 3; // proto level + if( !proto )return this; + m_proto = const_cast<LHCb::ProtoParticle*>(proto); + addProto( proto ); + StatusCode sc = process(); + if ( sc.isFailure() )Warning("Processing CaloFuture2MCTool from ProtoParticle failed").ignore(); + return this; +} + + +/*-------------------------- from Hypo to MC ------------------------*/ +// Accumulate hypos [->clusters] +void CaloFuture2MCTool::addHypo(const LHCb::CaloHypo* hypo){ + if( !hypo )return; + // register hypo if not yet done + bool ok = std::none_of( m_hypos.begin(), m_hypos.end(), + [&](const auto& h) { return h==hypo; } ); + if(!ok){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "CaloFutureHypo appears twice in the same decay chain" << endmsg; + if(counterStat->isQuiet())counter("CaloFutureHypo appears twice in the same decay chain" )+=1; + return; + } + m_hypos.push_back( hypo ) ; + m_depth=2; + + // ----- hypo->MC association : + if( ! m_hypo2Cluster ){ + // 2 - get the relevant linker + std::string loc = ( hypo->parent() && hypo->parent()->registry() ) ? hypo->parent()->registry()->identifier() : ""; + LHCb::CaloFuture2MC::HypoLinkTo linker( evtSvc() , msgSvc() , loc ) ; + if ( linker.notFound() ){ + Warning( "No Hypo2MC link at '" + loc + "' ",StatusCode::SUCCESS,1 ).ignore() ; + Warning(" ... try using Hypo->Cluster reference ", StatusCode::SUCCESS,1).ignore(); + Warning(" ... CaloFutureCluster will be re-processed (require full DST)", StatusCode::SUCCESS,1).ignore(); + Warning(" ... assume an identical reconstruction version ", StatusCode::SUCCESS,1).ignore(); + if(counterStat->isQuiet())counter("!! Hypo->Cluster")+=1; + m_hypo2Cluster=true; + } // ===> force hypo->cluster cascade + else{ + //debug() << "Linker found at " << loc << endmsg; + // - built (particle,weight) map + for ( const LHCb::MCParticle* particle = linker.first( hypo ) ; particle; particle = linker.next() ) { + m_mcMap[particle] += linker.weight(); + } + if( hypo->hypothesis() == LHCb::CaloHypo::Hypothesis::Pi0Merged ) + m_sum+=LHCb::CaloMomentum(hypo).e(); + else + m_sum += hypo->e(); + if(counterStat->isQuiet())counter("CaloFutureHypo->MC matching") += 1; + } + } + + // hypo->cluster->MC cascade if requested/needed + if( m_hypo2Cluster ){ + m_depth = 1; // cluster level + const SmartRefVector<LHCb::CaloCluster> clusters = hypo->clusters(); + if( clusters.empty() )return; + const LHCb::CaloCluster* cluster = + ( clusters.size() > 1 && hypo->hypothesis() == LHCb::CaloHypo::Hypothesis::PhotonFromMergedPi0 ) ? + *(clusters.begin() + 1 ) : *(clusters.begin()); //@ToDO use cluster::Type (when defined) + if( !cluster )return ; + if( counterStat->isQuiet() && + clusters.size() !=1 && hypo->hypothesis() != LHCb::CaloHypo::Hypothesis::PhotonFromMergedPi0 )counter("ill-defined CaloFutureHypo") += 1; + addCluster( cluster ); + } + return; +} +// associate single hypo +ICaloFuture2MCTool* CaloFuture2MCTool::from(const LHCb::CaloHypo* hypo ){ + if( hypo == m_hypo)return this; // process only if needed + clear(); + m_depth = 2; // hypo level + if( !hypo )return this; + m_hypo = const_cast<LHCb::CaloHypo*>(hypo); + // special case for MergedPi0 + if( hypo->hypothesis() == LHCb::CaloHypo::Hypothesis::Pi0Merged&& m_merged2Split){ + const auto& hyps = hypo->hypos(); + if( hyps.empty() )return this; + addHypo( hyps.front() ); // splitPhoton1 + addHypo( *std::next(hyps.begin()) ); // splitPhoton2 + } else{ + addHypo( hypo ); // mother CaloFutureHypo + } + StatusCode sc = process(); + if ( sc.isFailure() )Warning("Processing CaloFuture2MCTool from CaloFutureHypo failed").ignore(); + return this; +} + +/*-------------------------- from Cluster to MC ------------------------*/ +// Accumulate clusters [->digits] +void CaloFuture2MCTool::addCluster(const LHCb::CaloCluster* cluster ){ + if( !cluster )return; + + // register cluster (if not yet done) + bool ok = std::none_of( m_clusters.begin(), m_clusters.end(), + [&](const auto& c) { return c == cluster; } ); + if(!ok){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) )debug() << "Warning : CaloFutureCluster appears twice in the same decay chain" << endmsg; + if(counterStat->isQuiet())counter( "Warning : CaloFutureCluster appears twice in the same decay chain" )+=1; + return; + } + m_clusters.push_back( cluster ) ; + + m_depth=1; + // -- Cluster->MC mapping + if( ! m_cluster2Digit ){ + if( exist<LHCb::CaloFuture2MC::IClusterTable>(m_cluster2MCLoc ) )m_cluster2MC = get<LHCb::CaloFuture2MC::IClusterTable>( m_cluster2MCLoc ); + if( !m_cluster2MC ){ + Warning("No Cluster2MC table at " + m_cluster2MCLoc , StatusCode::SUCCESS,1); + if(counterStat->isQuiet())counter("!! Cluster->Digit")+=1; + m_cluster2Digit = true; + } // ===> force clsuter->digit cascade + else{ + // - built (particle,weight) map + for( const auto& ir : m_cluster2MC->relations( cluster )) { + m_mcMap[ir.to()] += ir.weight(); + } + m_sum += cluster->e(); + if(counterStat->isQuiet())counter("CaloFutureCluster->MC matching") += 1; + } + } + + // cluster->digit cascade if requested + if(m_cluster2Digit){ + m_depth = 0; + for( const auto& entry : cluster->entries() ) { + if ( m_sFilter >= 0 && ( entry.status() & m_sFilter) == 0 ){ continue ; } + const LHCb::CaloDigit* digit = entry.digit(); + if( !digit )continue; + // check digit is not yet registered + ok = std::none_of( m_digits.begin(), m_digits.end(), + [&](const auto& d) { return d == digit; } ); + if(ok)addDigit(digit); + } + } + return; +} +// associate single cluster +ICaloFuture2MCTool* CaloFuture2MCTool::from(const LHCb::CaloCluster* cluster ){ + if( cluster == m_cluster)return this; // process only if needed + clear(); + m_depth = 1;// cluster level + if( !cluster )return this; + m_cluster = (LHCb::CaloCluster*) cluster; + // + addCluster( cluster ); + // + StatusCode sc = process(); + if ( sc.isFailure() )Warning("Processing CaloFuture2MCTool from CaloFutureCluster failed").ignore(); + return this; +} + +/*-------------------------- from Digit to MC ------------------------*/ +void CaloFuture2MCTool::addDigit(const LHCb::CaloDigit* digit ){ + if( !digit )return; + m_digits.push_back( digit ); + // -- CaloDigit->MC association + m_digit2MC = getIfExists<LHCb::CaloFuture2MC::DigitTable>( m_digit2MCLoc ); + if( !m_digit2MC ){ + Warning(" Digit <-> MC relation table not found at " + m_digit2MCLoc , StatusCode::FAILURE,10).ignore(); + return; + } + // - built (particle,weight) map + for( const auto& ir : m_digit2MC->relations( digit ) ){ + m_mcMap[ir.to()] += ir.weight(); + } + m_sum += digit->e(); +} + + +// associate single digit +ICaloFuture2MCTool* CaloFuture2MCTool::from(const LHCb::CaloDigit* digit ){ + if( digit == m_digit)return this; // process only if needed + clear(); + m_depth = 0; // digit level + if( !digit )return this; + m_digit = const_cast<LHCb::CaloDigit*>(digit); + m_digits.push_back( digit ) ; + StatusCode sc = process(); + if ( sc.isFailure() )Warning("Processing CaloFuture2MCTool from CaloDigit failed").ignore(); + return this; +} + +/*-------------------------- Generic processing ------------------------*/ +StatusCode CaloFuture2MCTool::process(){ + mcDigest(); + verbose() << " Processing CaloFuture2MCTool " << std::endl << descriptor() << endmsg; + return StatusCode::SUCCESS; +} + +void CaloFuture2MCTool::clear(){ + m_mcMap.clear(); + m_treeMap.clear(); + m_digits.clear(); + m_clusters.clear(); + m_hypos.clear(); + m_protos.clear(); + m_parts.clear(); + m_nFrag = 0; + m_sum = 0.; + m_maxMC = nullptr ; + m_bestMC = nullptr ; + m_digit = nullptr; + m_cluster = nullptr; + m_hypo = nullptr; + m_proto = nullptr; + m_part = nullptr; + m_digit2MC= nullptr; + m_cluster2MC=nullptr; + m_category = 0 ; + m_depth = -1 ; +} + + +void CaloFuture2MCTool::mcDigest(){ + + double mcMax = 0.; + double mcBest = 0.; + m_maxMC = nullptr ; + m_bestMC = nullptr ; + + if( m_sum <= 0 ) return; + // loop over contributing particle : + for( const auto& imap : m_mcMap ) { + const LHCb::MCParticle* mcPart = imap.first; + double w = weight( mcPart ); + double q = quality( mcPart ); + double m = mcPart->momentum().M(); + // the most contributing MCParticle (with smallest mass when several MCPart with same weight) + if( w >= mcMax ){ + bool ok = true; + if( m_maxMC && w == mcMax && m > m_maxMC->momentum().M() )ok= false; + if(ok){ + mcMax = w; + m_maxMC = mcPart ; + } + } + // the best matching MCParticle + if( q >= mcBest ){ + mcBest = q; + m_bestMC = mcPart; + } + + } // end loop over MCParticles + // build MC tree + // 1- get related MC particle (seed) without any descendant listed in the related mcParticles + std::vector<const LHCb::MCParticle*> seeds; + for( const auto& imap : m_mcMap ) { + const LHCb::MCParticle* mcPart = imap.first; + int _pID = mcPart->particleID().abspid() ; + + auto hasProd = [&]( const LHCb::MCParticle* mcp ) { + const auto& vertices = mcp->endVertices(); + return std::any_of( vertices.begin(), vertices.end(), + [&](const auto& v) { + return std::any_of( v->products().begin(), v->products().end(), + [&](const auto& p) + { return m_mcMap.find(p)!=m_mcMap.end(); } ); + }); + }; + + // include electron with brems and converted photons as seeds + if ( _pID == 11 || _pID == 22 || !hasProd(mcPart) ) seeds.push_back( mcPart ); + } + + // 2- build the seed upstream tree + for( const LHCb::MCParticle* seed : seeds ) { + std::vector<const LHCb::MCParticle*> tree; + std::string sTree ; + mcTree( seed , tree, sTree); + std::stringstream ss; + ss << format(" %6.1f %% from : ", weight( seed ) *100. ) + << sTree + << " ( " << format(" %6.1f %% of the MC particle energy contributing", + (weight( seed ) == 0)?0: quality(seed) /weight( seed )*100.) << " )"; + m_treeMap[ ss.str() ] = std::move(tree); + } +} + +void CaloFuture2MCTool::mcTree(const LHCb::MCParticle* part, std::vector<const LHCb::MCParticle*>& tree , std::string& sTree){ + if( !part ) return; + tree.push_back( part ); + const LHCb::ParticleProperty* prop = m_ppsvc->find( part->particleID() ); + sTree = ( prop ? prop->name() : "??" ) + sTree; + if( part->mother() ){ + sTree = " -> " + sTree; + mcTree( part->mother() , tree, sTree ); + } +} + +double CaloFuture2MCTool::weight(const LHCb::MCParticle* part) const { + return ( part && m_sum>0 ) ? m_mcMap[part]/m_sum : 0.; +} + +double CaloFuture2MCTool::quality(const LHCb::MCParticle* part) const { + return ( part && part->momentum().E() != 0) ? weight(part) * m_mcMap[part]/part->momentum().E() : 0.; +} + + +std::string CaloFuture2MCTool::descriptor() const { + std::stringstream ss; + ss << "\n ---------- CaloFuture MC contribution " ; + if( m_part ) ss << "to particle (pid = " << m_part->particleID().pid() << ")\n" ; + if( m_parts.size() > 1 ) ss << " -> to " << m_parts.size() << " particle(s) -------- \n" ; + if( !m_protos.empty() ) ss << "to " << m_protos.size() << " protoParticle(s) -------- \n" ; + if( !m_hypos.empty() ) ss << "to " << m_hypos.size() << " hypo(s) -------- \n" ; + if( !m_digits.empty() ) ss << "to " << m_digits.size() << " digit(s) -------- \n" ; + if( !m_clusters.empty() ) ss << "to " << m_clusters.size() << " cluster(s) ------- \n" ; + ss << " ---- Total calo energy deposit : " << m_sum << " MeV \n" ; + for( const auto& im : m_treeMap ) ss << " -- " << im.first << '\n'; + + if( bestMC() ){ + const LHCb::ParticleProperty* prop = m_ppsvc->find( bestMC()->particleID() ); + std::string p = ( prop ? prop->name() : "??" ); + ss << " --> Best matching MCParticle : [" << p << "] == (Quality/Weight : " + << quality( bestMC() ) <<" / " << weight( bestMC() )<< ")\n" ; + } + + if( maxMC() ){ + const LHCb::ParticleProperty* prop = m_ppsvc->find( maxMC()->particleID() ); + std::string p = ( prop ? prop->name() : "??" ); + ss << " --> Maximum weight MCParticle : [" << p << "] == (Quality/Weight : " + << quality( maxMC() ) <<" / " << weight( maxMC() )<<")\n" ; + } + + ss << " -------------------------------- "; + return ss.str(); +} + + +const LHCb::MCParticle* CaloFuture2MCTool::findMCOrBest(LHCb::ParticleID id, double threshold ) const { + const LHCb::MCParticle* found = findMC(id,threshold); + return found ? found : bestMC(); +} +const LHCb::MCParticle* CaloFuture2MCTool::findMCOrBest(std::string name, double threshold ) const { + const LHCb::MCParticle* found = findMC(name,threshold); + return found ? found : bestMC(); +} +const LHCb::MCParticle* CaloFuture2MCTool::findMC(std::string name, double threshold ) const{ + const LHCb::ParticleProperty* prop = m_ppsvc->find( name ); + return prop ? findMC( prop->particleID() , threshold) : nullptr; +} +const LHCb::MCParticle* CaloFuture2MCTool::findMC(LHCb::ParticleID id, double threshold ) const { + double t = threshold; + const LHCb::MCParticle* best = nullptr; + for( const auto& imap : m_mcMap ) { + const LHCb::MCParticle* mcPart = imap.first; + if( mcPart->particleID().abspid() != id.abspid() )continue; + double q = quality( mcPart ); + if( q < t )continue; + t = q; + best = mcPart; + } + return best; +} +const LHCb::MCParticle* CaloFuture2MCTool::bestMC() const { + return m_bestMC; +} +const LHCb::MCParticle* CaloFuture2MCTool::maxMC() const { + return m_maxMC; +} + + +ICaloFuture2MCTool* CaloFuture2MCTool::fragment(unsigned int i){ + m_nFrag = 0; + /* CaloFutureHypo level */ + if( m_depth == 2 ){ + m_nFrag = m_hypos.size(); + if( i >= m_nFrag)return nullptr; + if(m_nFrag == 1)return this; + return m_tool->from( m_hypos[i] ); + } + /* CaloFutureCluster level */ + if( m_depth == 1 ){ + m_nFrag = m_clusters.size(); + if( i >= m_nFrag)return nullptr; + if(m_nFrag == 1)return this; + return m_tool->from( m_clusters[i] ); + } + /* CaloDigit level */ + if( m_depth == 0 ){ + m_nFrag = m_digits.size(); + if( i >= m_nFrag)return nullptr; + if(m_nFrag == 1)return this; + return m_tool->from( m_digits[i] ); + } + return nullptr; +} diff --git a/CaloFuture/CaloFutureTools/src/CaloFuture2MCTool.h b/CaloFuture/CaloFutureTools/src/CaloFuture2MCTool.h new file mode 100644 index 0000000000000000000000000000000000000000..afc9e6e446a4a16e19f5626c099accdd1ce92b83 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFuture2MCTool.h @@ -0,0 +1,155 @@ +#ifndef CALOFUTURE2MCTOOL_H +#define CALOFUTURE2MCTOOL_H 1 + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiTool.h" +#include "CaloFutureInterfaces/ICaloFuture2MCTool.h" // Interface +#include "CaloFutureInterfaces/IFutureCounterLevel.h" +#include "GaudiKernel/IIncidentListener.h" +#include "GaudiKernel/IIncidentSvc.h" +#include "GaudiKernel/Incident.h" +// from LHCb : the calo->particle stream +#include "Event/CaloDigit.h" +#include "Event/CaloCluster.h" +#include "Event/CaloHypo.h" +#include "Event/ProtoParticle.h" +#include "Event/Particle.h" +#include "Event/MCParticle.h" +#include "Kernel/IParticlePropertySvc.h" +#include "Kernel/ParticleProperty.h" +#include "CaloFutureUtils/CaloMomentum.h" +// from LHCb : some typedef and utilities +#include "CaloFutureUtils/CaloFuture2MC.h" +#include "CaloFutureUtils/CaloFutureMCTools.h" + + + +/** @class CaloFuture2MCTool CaloFuture2MCTool.h + * + * + * @author Olivier Deschamps + * @date 2009-07-27 + */ +class CaloFuture2MCTool : public extends<GaudiTool , ICaloFuture2MCTool , IIncidentListener > { + +public: + // category enum + + enum MCCategory { + /* Single cluster/hypo categories */ + UnMatched = 0, + Photon = 1, + BremStrahlung = 2, + Electron = 3, + ConvertedPhoton = 4, + MergedPi0 = 5, + ChargedHadron = 6, + NeutralHadron = 7, + Spillover = 8 + }; + + + /// Standard constructor + CaloFuture2MCTool( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize( ) override; + + // + ICaloFuture2MCTool* from(const LHCb::CaloDigit* digit ) override; + ICaloFuture2MCTool* from(const LHCb::CaloCluster* cluster ) override; + ICaloFuture2MCTool* from(const LHCb::CaloHypo* hypo ) override; + ICaloFuture2MCTool* from(const LHCb::ProtoParticle* proto ) override; + ICaloFuture2MCTool* from(const LHCb::Particle* particle ) override; + const LHCb::MCParticle* bestMC() const override; + const LHCb::MCParticle* maxMC() const override; + double weight(const LHCb::MCParticle*) const override; + const LHCb::MCParticle* findMC(LHCb::ParticleID id, double threshold = 0 ) const override; + const LHCb::MCParticle* findMCOrBest(LHCb::ParticleID id, double threshold = 0 ) const override; + const LHCb::MCParticle* findMC(std::string name, double threshold = 0 ) const override; + const LHCb::MCParticle* findMCOrBest(std::string name, double threshold = 0 ) const override; + double quality(const LHCb::MCParticle*) const override; + std::string descriptor() const override; + bool isCaloFuture(LHCb::Particle* particle) const override { + return particle && LHCb::CaloFutureParticle( particle ).isCaloFuture(); + } + bool isPureNeutralCaloFuture(const LHCb::Particle* particle) const override { // SHOULD BE IN CALOFUTUREPARTICLE + return particle && LHCb::CaloFutureParticle( const_cast<LHCb::Particle*>(particle) ).isPureNeutralCaloFuture();// non pure calorimetric object + } + + + + /// Inform that a new incident has occurred + void handle(const Incident& /* inc */ ) override { clear();} + + + // TO BE INTERFACED : + int MCCategory(){return m_category;}; + ICaloFuture2MCTool* fragment(unsigned int i); + unsigned int numberOfFragments(){return m_nFrag;} + //ostream << category + // clusters() + // hypos() + // protos() + +private: + IFutureCounterLevel* counterStat = nullptr; + StatusCode process(); + void addDigit (const LHCb::CaloDigit* digit); + void addCluster (const LHCb::CaloCluster* cluster); + void addHypo (const LHCb::CaloHypo* hypo); + void addProto (const LHCb::ProtoParticle* proto, const LHCb::Particle* parent = NULL); + void clear(); + void mcDigest(); + void mcTree(const LHCb::MCParticle* part, std::vector<const LHCb::MCParticle*>& tree , std::string& sTree); + + + std::vector<const LHCb::CaloDigit*> m_digits; + std::vector<const LHCb::CaloCluster*> m_clusters; + std::vector<const LHCb::CaloHypo*> m_hypos; + std::vector<const LHCb::ProtoParticle*> m_protos; + std::vector<const LHCb::Particle*> m_parts; + LHCb::CaloDigit* m_digit = nullptr; + LHCb::CaloCluster* m_cluster = nullptr; + LHCb::CaloHypo* m_hypo = nullptr; + LHCb::ProtoParticle* m_proto = nullptr; + LHCb::Particle* m_part = nullptr; + CaloFutureMCTools::CaloFutureMCMap m_mcMap; + // + Gaudi::Property<std::string> m_cluster2MCLoc + {this, "Cluster2MCTable", "", "Cluster->MC relation table location"}; + + Gaudi::Property<std::string> m_digit2MCLoc + {this, "Digit2MCTable", "Relations/" + LHCb::CaloDigitLocation::Default, + "Digit->MC relation table location"}; + + LHCb::CaloFuture2MC::IClusterTable* m_cluster2MC = nullptr; + LHCb::CaloFuture2MC::IDigitTable* m_digit2MC = nullptr; + double m_sum = 0.; + const LHCb::MCParticle* m_maxMC = nullptr; + const LHCb::MCParticle* m_bestMC = nullptr; + std::map<std::string,std::vector<const LHCb::MCParticle*> > m_treeMap; + SmartIF<LHCb::IParticlePropertySvc> m_ppsvc; + + // + Gaudi::Property<bool> m_hypo2Cluster + {this, "Hypo2Cluster", false, "(part->protoP)->hypo->cluster cascade ( or use hypo->MC linker tables)"}; + + Gaudi::Property<bool> m_cluster2Digit + {this, "Cluster2Digits", false, "(part->protoP)->hypo->cluster->digit cascade ( or use cluster->MC relation tables)"}; + + Gaudi::Property<bool> m_merged2Split + {this, "Merged2Split", false, "expert usage (merged->split->cluster - NOT IMPLEMENTED so far)"}; + + Gaudi::Property<int> m_sFilter + {this, "DigitStatusFilter", LHCb::CaloDigitStatus::UseForEnergy, + "digit filter in case of ..->digit->MC table is used"}; + + int m_category = 0; + int m_depth = -1; + unsigned int m_nFrag = 0; + ICaloFuture2MCTool* m_tool = nullptr; +}; +#endif // CALOFUTURE2MCTOOL_H diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureCosmicsTool.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureCosmicsTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1de94112f7f721a91e950aecd10be0e42c12c402 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFutureCosmicsTool.cpp @@ -0,0 +1,591 @@ +// Include files + +// from LHCb +#include "GaudiKernel/Plane3DTypes.h" +#include "LHCbMath/LineTypes.h" +#include "LHCbMath/GeomFun.h" +#include "CaloDet/DeCalorimeter.h" + +// local +#include "CaloFutureCosmicsTool.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : CaloFutureCosmicsTool +// +// 2008-04-02 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( CaloFutureCosmicsTool ) + + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +CaloFutureCosmicsTool::CaloFutureCosmicsTool( const std::string& type, + const std::string& name, + const IInterface* parent ) +: base_class ( type, name , parent ) +{ + declareInterface<ICaloFutureCosmicsTool>(this); + + // set default detectorName + int index = name.find_last_of(".") +1 ; // return 0 if '.' not found --> OK !! + m_det = name.substr( index, 4 ); + if ( name.substr(index,3) == "Prs" ) m_det = "Prs"; + if ( name.substr(index,3) == "Spd" ) m_det = "Spd"; + + // + if(m_det == "Ecal"){ m_zSup = 100;} + else if(m_det == "Hcal"){ m_zSup = 10; } + else { m_zSup = 0; } +} + +//============================================================================= +StatusCode CaloFutureCosmicsTool::initialize(){ + StatusCode sc = base_class::initialize(); + if (sc.isFailure()) return Error("Failed to initialize", sc); + + + + // Fill vector with requested time slots from sequence and asymmetry settings + for(std::vector<std::string>::iterator iseq = m_seq.begin(); iseq != m_seq.end() ; ++iseq){ + m_slots.push_back( *iseq ); + } + int k =0; + for(std::map<std::string,std::vector<std::string> >::iterator iasy = m_asy.begin();m_asy.end() != iasy ; iasy++){ + std::vector<std::string> asy = (*iasy).second; + if( asy.size() != 2){ + Error("AsymmetrySlot must be a vector of pairs of entries").ignore(); + return StatusCode::FAILURE; + }else{ + std::string a = *(asy.begin()); + std::string b = *(asy.begin()+1); + + std::stringstream str(""); + str << (*iasy).first; + double offset; + str>> offset; + + info() << "Asymmetry ( id = '" << (*iasy).first + << "') is define as R = [ADC("<< a <<")-ADC("<< b <<")]/[ADC("<< a <<")+ADC("<< b <<")]"<<endmsg; + info() << "Corresponding Time offset : "<< offset << " ns" << endmsg; + } + for(std::vector<std::string>::iterator islot = asy.begin(); islot != asy.end();islot++){ + bool isReg = false; + for(std::vector<std::string>::iterator is = m_slots.begin(); is != m_slots.end() ; ++is){ + if( *is == *islot){ + isReg = true; + continue; + } + } + if( !isReg )m_slots.push_back( *islot ); + } + k++; + } + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Requested time slots : " << m_slots << endmsg; + + + // get detector element + if ( "Ecal" == m_det ) { + m_calo = getDet<DeCalorimeter>( DeCalorimeterLocation::Ecal ); + } else if ( "Hcal" == m_det ) { + m_calo = getDet<DeCalorimeter>( DeCalorimeterLocation::Hcal ); + } else if ( "Prs" == m_det ) { + m_calo = getDet<DeCalorimeter>( DeCalorimeterLocation::Prs ); + } else { + error() << "Unknown detector name " << m_det << endmsg; + return StatusCode::FAILURE; + } + + // some detector geometry + m_plane = m_calo->plane(CaloPlane::Middle); + m_delta = m_calo->plane(CaloPlane::Front).HesseDistance()- + m_calo->plane(CaloPlane::Back).HesseDistance(); + m_delta *= m_calo->plane(CaloPlane::Front).Normal().Z(); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " m_det : " << m_det << " m_delta = " << m_delta << " cos(tilt) = " + << m_calo->plane(CaloPlane::Front).Normal().Z() << endmsg; + + // get the decoding tool for each time slot + for(std::vector<std::string>::iterator islot = m_slots.begin(); islot != m_slots.end() ; ++islot){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Loading : decoding tool for slot " << *islot << " : '" + << m_det << "ReadoutTool" << *islot << "'" <<endmsg; + this->setProperty("RootInTES",""); + if(*islot != "T0")this->setProperty("RootInTES",*islot); + m_daqs[*islot] = tool<ICaloFutureDataProvider>( m_readoutTool , m_det + "ReadoutTool" + *islot , this ); + } + this->setProperty("RootInTES","");// reset + + // + return StatusCode::SUCCESS; +} + +//============================================================================= +StatusCode CaloFutureCosmicsTool::processing(){ + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " Process " << name() << endmsg; + + // default + m_phi = -999; + m_sPhi = 999; + m_refPoint = Gaudi::XYZPoint(); + m_eRefPoint = Gaudi::XYZPoint(); + m_cosmicsADCs.clear(); + m_zsupADCs.clear(); + m_maxLoc = "none"; + m_offset = -99999; + m_bound = std::make_pair(Gaudi::XYZPoint(),Gaudi::XYZPoint()); + m_time = -999; + m_stime = -999; + m_timed = false; + m_tracked = false; + for(std::map<std::string,std::vector<std::string> >::iterator iasy = m_asy.begin(); iasy != m_asy.end() ; iasy++){ + std::string id = (*iasy).first; + m_Rmean[id] = -999.; + m_Rmean2[id] = -999.; + m_R[id] = -999.; + m_slotSum[id] = -999.; + m_td[id] = -999.; + } + m_kernel = -1.; + + // 1) get banks + if( getBanks().isFailure() )return StatusCode::FAILURE; + + // 2) apply 0-suppression + if( zSup().isFailure() )return StatusCode::SUCCESS; + + // 3) reconstruct 2D trajectory + if( fit2D().isFailure() )return StatusCode::SUCCESS; + + // 4) reconstruct time + if( timing().isFailure() )return StatusCode::SUCCESS; + + // 5) produce ntuple + if(m_tuple){ + + unsigned int unit=100; + if(m_det == "Prs")unit = 100; + else if(m_det == "Ecal")unit = 200; + else if(m_det == "Hcal")unit = 300; + if( tupling(unit).isFailure())return StatusCode::FAILURE; + } + return StatusCode::SUCCESS; +} + + +//============================================================================= +StatusCode CaloFutureCosmicsTool::getBanks(){ + + // get rawBank from TES + for(std::vector<std::string>::iterator islot = m_slots.begin(); islot != m_slots.end() ; ++islot){ + if(!m_daqs[*islot]->ok()) return StatusCode::FAILURE; + } + return StatusCode::SUCCESS; +} +//============================================================================= +StatusCode CaloFutureCosmicsTool::zSup(){ + + // apply 0-suppression + + m_max = LHCb::CaloAdc(LHCb::CaloCellID(), -9999 ); + m_zsupADCs.clear(); + + std::string slot = *(m_slots.begin()); + const CaloVector<LHCb::CaloAdc>& adcs = m_daqs[slot]->adcs() ; + for(CaloVector<LHCb::CaloAdc>::const_iterator iadc = adcs.begin(); iadc!= adcs.end(); ++iadc){ + long sum = 0; + LHCb::CaloCellID cell = (*iadc).cellID(); + if(cell.area() == m_calo->pinArea())continue; + for(std::vector<std::string>::iterator islot = m_seq.begin(); islot != m_seq.end() ; ++islot){ + int adc = m_daqs[*islot]->adc(cell); + if(adc>0)sum += adc; + } + if( sum <= m_zSup )continue; + + // Collect 0-suppresed data + LHCb::CaloAdc sumADC(cell , sum); + m_zsupADCs.push_back( sumADC ); // vector of ADC sum over consecutive BX (after Z-sup) + if( sum > m_max.adc() )m_max = sumADC; // maximal ADC + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << name() + << " : cell = " << sumADC.cellID() + << " ADCsum = " << sumADC.adc() + << " max = " << m_max.adc() + << endmsg; + + } + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Zero suppression : " << m_zsupADCs.size() << " among " + << adcs.size() << " digits " << endmsg; + + if( m_zsupADCs.size() == 0){ + info() << "No digit left after Zero-suppression" <<endmsg; + return StatusCode::FAILURE; + } + + return StatusCode::SUCCESS; +} +//============================================================================= +StatusCode CaloFutureCosmicsTool::fit2D(){ + + m_refPoint = Gaudi::XYZPoint(0.,0.,-999); + m_eRefPoint = Gaudi::XYZVector(); + m_cosmicsADCs.clear(); + + // get the position of highest deposit + Gaudi::XYZPoint ref = m_calo->cellCenter( m_max.cellID() ); + + // Best 2D slope fit (minimize Chi2 = Sum_i [ADC_i (phi_i - phi)^2/sigma_i^2) + double swa = 0; + double sw = 0; + {for(std::vector<LHCb::CaloAdc>::iterator id = m_zsupADCs.begin(); id != m_zsupADCs.end(); ++id){ + LHCb::CaloCellID cell = (*id).cellID(); + if( m_max.cellID() == cell)continue; + Gaudi::XYZPoint pos = m_calo->cellCenter( cell ); + double size = m_calo->cellSize( cell ); + double sx2 = size*size/12; + double dx = pos.X()-ref.X(); + double dy = pos.Y()-ref.Y(); + double a = acos(0.); // a = pi/2 + if(dx != 0 )a = atan(dy/dx) ; // tan( phi_i )= y_i/x_i + if(a<0)a += acos(-1.); + double s2 = sx2; + ///(dx*dx + dy*dy); // sigma(phi_i) + int val = (*id).adc(); + if( val < 0)val = 0; + s2 = 1; + Gaudi::XYZVector vec = pos-ref; + double adc = (double) val/vec.rho() ; + double w = adc / s2; // weight = ADC_i/sigma_i^2 + sw += w; + swa += w*a; + }} + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Point : " << ref.X() << " " << ref.Y() << endmsg; + + + if( sw<=0 ){ + Warning( "Weight = 0 - fit failed ").ignore(); + return StatusCode::FAILURE; + } + else{ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "1st pass " << swa/sw << endmsg; + } + + // Built the 2D line + // best phi = swa/sw (assuming the 2D line passing through the highest deposit) + double norm = sqrt(1.+tan(swa/sw)*tan(swa/sw)); + Gaudi::XYZVector vec(1./norm, tan(swa/sw)/norm , 0.); + Gaudi::Math::XYZLine line(ref, vec); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Line parameters " << vec.X() << " " << vec.Y() << " " << vec.Z() << endmsg; + // Collect data along the 2D cosmics line (+- tolerance) + double x = 0; + double y = 0; + double ssx2= 0; + m_adcSum = 0; + double kernel = 0.; + {for(std::vector<LHCb::CaloAdc>::iterator id =m_zsupADCs.begin(); id != m_zsupADCs.end(); ++id){ + LHCb::CaloCellID cell = (*id).cellID(); + double size = m_calo->cellSize( cell ); + double sx2 = size*size/12; + Gaudi::XYZPoint pos = m_calo->cellCenter( cell ); + pos.SetZ( ref.Z() ); + double ip = Gaudi::Math::impactParameter<Gaudi::XYZPoint, Gaudi::Math::XYZLine>(pos, line)/size; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "--> " << cell << " ip = " << ip << " x = "<< pos.X() + << " y = " << pos.Y() << " z= " << pos.Z() << endmsg; + if(fabs(ip) < m_tol){ + m_cosmicsADCs.push_back( *id ); + m_adcSum += (*id).adc(); + kernel+= (*id).adc(); + for(std::vector<std::string>::iterator ik = m_kern.begin();ik!=m_kern.end();++ik){ + kernel -= m_daqs[*ik]->adc( cell ); + } + x += pos.X(); + y += pos.Y(); + ssx2 += sx2; + } + }} + + if( 0 == m_adcSum ) { + m_kernel = 0; + } + else { + m_kernel = kernel / (double) m_adcSum; + } + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " m_cosmicsADCs.size() " << m_cosmicsADCs.size() << endmsg; + if(m_cosmicsADCs.size()== 0){ + return Warning( "Empty 2D segment - fit failed", StatusCode::FAILURE ); + } + + // ADC sum thresholds + if( m_adcSum < m_minD || m_adcSum > m_maxD){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "ADC sum " << m_adcSum << " outside the requested range [" + << m_minD << "," << m_maxD <<"]" <<endmsg; + return StatusCode::FAILURE; + } + + // Multiplicity thresholds + if( (int) m_cosmicsADCs.size() < m_minM || (int) m_cosmicsADCs.size() > m_maxM ){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Segment #digits " << m_cosmicsADCs.size() + << " outside the requested range " + << m_minM << "," << m_maxM << "]" << endmsg; + return StatusCode::FAILURE; + } + + // average position + double N = (double) m_cosmicsADCs.size(); + x /= N; + y /= N; + // Z (middle of active area) - take the tilt into account for the fun + double z = ( -m_plane.Normal().X()*x -m_plane.Normal().Y()*y - m_plane.HesseDistance() )/m_plane.Normal().Z(); + double ex = ssx2/N/N; // error on x + double ey = ssx2/N/N; // error on y + double ez = m_delta*m_delta/12./N; // error on z + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) { + debug() << "Delta = " << m_delta << " z = " << z << "+-" << sqrt(ez) << endmsg; + debug() << "x = " << x << " +- " << sqrt(ex) << endmsg; + debug() << "y = " << y << " +- " << sqrt(ey) << endmsg; + } + + m_refPoint.SetX(x); + m_refPoint.SetY(y); + m_refPoint.SetZ(z); + m_eRefPoint.SetX(ex); + m_eRefPoint.SetY(ey); + m_eRefPoint.SetZ(ez); + + + // (re-)Evaluate the parameters wrt the average (x,y) + swa = 0; + sw = 0; + double sws2 = 0; + std::vector<LHCb::CaloAdc>::iterator id = m_cosmicsADCs.begin(); + LHCb::CaloCellID idMin = (*id).cellID(); + LHCb::CaloCellID idMax = (*id).cellID(); + for(id = m_cosmicsADCs.begin() ; id != m_cosmicsADCs.end(); ++id){ + LHCb::CaloCellID cell = (*id).cellID(); + Gaudi::XYZPoint pos = m_calo->cellCenter( cell ); + if( pos.Y() < m_calo->cellCenter( idMin ).Y() )idMin = cell; + if( pos.Y() > m_calo->cellCenter( idMax ).Y() )idMax = cell; + double adc = (double) (*id).adc(); + if(adc<0)adc = 0; + vec = pos-m_refPoint; + if(vec.rho()!=0)adc /= vec.rho(); + double size = m_calo->cellSize( cell ); + double sx2 = size*size/12; + double dx = pos.X()-m_refPoint.X(); + double dy = pos.Y()-m_refPoint.Y(); + double a = acos(0.); + if(dx != 0 )a = atan(dy/dx) ; // tan( phi_i )= y_i/x_i + double s2; + if(dx*dx+dy*dy != 0){ + s2 = sx2/(dx*dx + dy*dy); // sigma(phi_i) + }else{ + a = 0; + s2= acos(-1.); + } + if(a<0)a += acos(-1.); + double w = adc / s2; + sw += w; + swa += w*a; + sws2 += w*w*s2; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "a = " << a << " w = " << w << " sw = " << sw << " swa = " << swa << endmsg; + } + m_phi = swa / sw; // best phi + if(m_phi<0)m_phi += acos(-1.); + m_sPhi = sws2 /sw/sw; // phi variance + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "2nd pass " << m_phi << " +- " << sqrt(m_sPhi) << endmsg; + m_bound = std::make_pair(m_calo->cellCenter( idMin), m_calo->cellCenter( idMax) ); // extrema of the track segment + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "END OF TRAJECTORY RECONSTRUCTION" << endmsg; + m_tracked = true; + return StatusCode::SUCCESS; +} + + + + + + +//============================================================================= +StatusCode CaloFutureCosmicsTool::timing(){ + + // Compute the asymmetries + double maxSum = -99999; + m_maxLoc = "none"; + + + // compute asymmetries + + for(std::map<std::string,std::vector<std::string> >::iterator iasy = m_asy.begin(); iasy != m_asy.end() ; iasy++){ + std::vector<std::string> asym = (*iasy).second; + std::string id = (*iasy).first; + std::string a1 = *(asym.begin()); + std::string a2 = *(asym.begin()+1); + double sb1 = 0; + double sb2 = 0; + double rm = 0; + double rm2 = 0; + double td = 0; + double tdm = 0; + double dl = 0; + int N = 0; + for(std::vector<LHCb::CaloAdc>::iterator it = m_cosmicsADCs.begin();it!=m_cosmicsADCs.end();it++){ + LHCb::CaloCellID cell = (*it).cellID(); + double b1 = (double) m_daqs[a1]->adc( cell ); + double b2 = (double) m_daqs[a2]->adc( cell ); + if(b1<0)b1=0; + if(b2<0)b2=0; + if(b1+b2 == 0 )continue; + N++; + double asy = ( b1 - b2 ) / ( b1 + b2 ); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "R = " << asy << " b1 = " << b1 << "b2 = " << b2 << endmsg; + sb1 += b1; + sb2 += b2; + rm += asy; + rm2 += asy*asy; + // timing dispersion + Gaudi::XYZPoint pos = m_calo->cellCenter( cell ); + Gaudi::XYZVector vec = pos - m_refPoint; + double sign = 0; + if(vec.Y() != 0)sign = vec.Y()/fabs(vec.Y()); + td += asy * vec.rho() * sign; + tdm+= vec.rho() * sign; + dl += vec.Perp2(); + } + + if( N != 0) m_Rmean[id] = rm / (double) N; + if( N != 0) m_Rmean2[id] = rm2 / (double) N; + + tdm *= m_Rmean[id]; + m_td[id] = (dl>0) ? (td-tdm)/dl : 0.; + m_Rmean2[id] -= m_Rmean[id]*m_Rmean[id]; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) { + debug() << "<R>( " << id << ") = "<< m_Rmean[id] << endmsg; + debug() << "sigma(R)^2("<< id << ") = " << m_Rmean2[id] << endmsg; + } + if(sb1+sb2!=0)m_R[id] = (sb1-sb2)/(sb1+sb2) ; // asymmetry of the average + m_slotSum[id] = sb1+sb2; + if( sb1+sb2 >= maxSum){ + maxSum=sb1+sb2; + m_maxLoc = id; + } + } + + + // convert asymmetry into time (@todo - apply Yasmine's method) + m_time = -999; + if(m_maxLoc == "none")return StatusCode::SUCCESS; + std::stringstream str(""); + str << m_maxLoc; + double offset; + str>> offset; + m_offset = offset; + if(fabs(offset)>999.)return StatusCode::SUCCESS; + double R = m_Rmean[m_maxLoc]; + if(fabs(R) > m_minR && fabs(R) < m_maxR ){ + m_timed = true; + double u = R / ( 1+ m_par[3]*sqrt(1-R*R)); + m_time = m_offset + m_par[0] + m_par[1]*R*R + m_par[2]/acos(-1.) * acos( u ); + // double d = -2*m_par[1] + m_par[2]/acos(-1.) + // * ( - 1/sqrt(1-u*u) * ( 1+ m_par[3]*sqrt(1-R*R) - R * 0.5 * m_par[3] / sqrt(1-R*R)))*u*u/R/R; + //m_stime = d*d* m_Rmean2[m_maxLoc] + m_tRes*m_tRes; + } + return StatusCode::SUCCESS; +} + + + +//============================================================================= +StatusCode CaloFutureCosmicsTool::tupling(unsigned int unit){ + + + Tuple ntp = nTuple(unit, m_det + "Cosmics" ,CLID_ColumnWiseTuple); + StatusCode sc; + // Ecal + sc = ntp->column("deposit" , deposit() ); + sc = ntp->column("phi" , phi() ); + sc = ntp->column("phiVar" , phiVariance() ); + sc = ntp->column("refX" , referencePoint().X() ); + sc = ntp->column("refY" , referencePoint().Y() ); + std::vector<LHCb::CaloAdc>& eAdcs = m_cosmicsADCs; + if(m_full) eAdcs = m_zsupADCs; + std::vector<float> x; + std::vector<float> y; + std::vector<int> a; + std::vector<int> ids; + for(auto iadc = eAdcs.begin();iadc!=eAdcs.end();iadc++){ + if(iadc-eAdcs.begin() > m_maxAdc){ + Warning("Ntupling : digits vector too large - will be truncated").ignore(); + break; + } + + LHCb::CaloCellID id = (*iadc).cellID(); + ids.push_back( id.all() ); + x.push_back( det()->cellCenter( id ).X() ); + y.push_back( det()->cellCenter( id ).Y() ); + a.push_back( (*iadc).adc() ); + } + sc = ntp->farray("id" , ids ,"NAdcs", m_maxAdc); + sc = ntp->farray("x" , x ,"NAdcs", m_maxAdc); + sc = ntp->farray("y" , y ,"NAdcs", m_maxAdc); + sc = ntp->farray("adc" , a ,"NAdcs", m_maxAdc); + + std::vector<double> rMean; + std::vector<double> rSig; + std::vector<double> rGlob; + std::vector<double> sSum; + std::vector<double> td; + for(const auto& iasy : m_asy ) { + const auto& id = iasy.first; + rMean.push_back( m_Rmean[id] ); + rSig.push_back( m_Rmean2[id] ); + rGlob.push_back( m_R[id] ); + sSum.push_back( m_slotSum[id] ); + td.push_back(m_td[id]); + } + sc = ntp->farray("RMean" , rMean , "NAsymmetries" , m_Rmean.size() ); + sc = ntp->farray("RVar" , rSig , "NAsymmetries" , m_Rmean.size() ); + sc = ntp->farray("RGlob" , rGlob , "NAsymmetries" , m_Rmean.size() ); + sc = ntp->farray("Sum" , sSum , "NAsymmetries" , m_Rmean.size() ); + sc = ntp->farray("dTime" , td , "NAsymmetries" , m_Rmean.size() ); + + + std::stringstream str(""); + double offset = -9999.; + if(m_maxLoc != "none"){ + str << m_maxLoc; + double off; + str>> off; + offset = off; + } + + sc = ntp->column("slot" , offset); + sc = ntp->column("time" , m_time); + sc = ntp->column("timeVariance" , m_stime); + sc = ntp->column("istimed" , (int)m_timed); + sc = ntp->column("istracked" , (int)m_tracked); + + sc=ntp->write(); + if(sc.isFailure())Warning( name() + " Ntupling failed").ignore(); + return StatusCode::SUCCESS; +} + diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureCosmicsTool.h b/CaloFuture/CaloFutureTools/src/CaloFutureCosmicsTool.h new file mode 100644 index 0000000000000000000000000000000000000000..77172cc8b32d2ebc60b1062ab5c8da519e503e0e --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFutureCosmicsTool.h @@ -0,0 +1,130 @@ +#ifndef CALOFUTURECOSMICSTOOL_H +#define CALOFUTURECOSMICSTOOL_H 1 + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiTupleTool.h" +// from LHCb +#include "CaloFutureInterfaces/ICaloFutureCosmicsTool.h" // Interface +#include "CaloFutureDAQ/ICaloFutureDataProvider.h" +#include "CaloKernel/CaloVector.h" + + +/** @class CaloFutureCosmicsTool CaloFutureCosmicsTool.h + * + * + * @author Olivier Deschamps + * @date 2008-04-07 + */ +class CaloFutureCosmicsTool : public extends<GaudiTupleTool, ICaloFutureCosmicsTool> { +public: + /// Standard constructor + CaloFutureCosmicsTool( const std::string& type, + const std::string& name, + const IInterface* parent); + + + StatusCode initialize() override; + + Gaudi::XYZPoint referencePoint() override {return m_refPoint;} + Gaudi::XYZPoint referencePointVariance() override {return m_eRefPoint;} + const std::pair<Gaudi::XYZPoint,Gaudi::XYZPoint>& extrema() override {return m_bound;} + double deposit() override {return m_adcSum;} + double phi() override {return m_phi;} + double phiVariance() override {return m_sPhi;} + double asymmetry() override {return (m_maxLoc != "none") ? m_Rmean[m_maxLoc] : -99.;} + double asymmetryVariance() override {return (m_maxLoc !="none") ? m_Rmean2[m_maxLoc] : -99.;} + double slot() override {return m_offset;} + double time() override {return m_time;} + double timeVariance() override {return m_stime;} + double timeDispersion() override {return (m_maxLoc !="none") ? m_td[m_maxLoc] : -99.;;} + DeCalorimeter* det() override {return m_calo;} + StatusCode processing() override; + StatusCode tupling(unsigned int unit) override; + bool tracked() override {return m_tracked;} + bool timed() override {return m_timed;} + double kernel() override {return m_kernel;}; + + +protected: + +private: + // private methods + StatusCode getBanks(); + StatusCode zSup(); + StatusCode fit2D(); + StatusCode timing(); + // + DeCalorimeter* m_calo = nullptr; + Gaudi::Plane3D m_plane; + double m_delta; + std::map<std::string, ICaloFutureDataProvider*> m_daqs; // decoding tool per time-slot + LHCb::CaloAdc m_max; // highest deposit (sum over time-slots) + std::vector<LHCb::CaloAdc> m_zsupADCs; // vector of ADC sum over time-slots (after Zsup) + std::vector<LHCb::CaloAdc> m_cosmicsADCs; // vector of cellID associated to cosmics 2D track + + std::map<std::string,double> m_Rmean; // mean asymmetry + std::map<std::string,double> m_Rmean2;// dispersion of the asymmetry + std::map<std::string,double> m_R; // global asymetry + std::map<std::string,double> m_slotSum; + std::map<std::string,double> m_td; + + + double m_time = -999; // m_Rmean converted to time + double m_stime = -999; + Gaudi::XYZPoint m_refPoint; // reference point on the cosmics 2D track + Gaudi::XYZPoint m_eRefPoint; // error on reference point + std::pair<Gaudi::XYZPoint,Gaudi::XYZPoint> m_bound; // extrema of the 2D track segment + double m_phi = -999; + double m_sPhi = 999; + bool m_timed = false; + bool m_tracked = false; + long m_adcSum; + std::vector<std::string> m_slots; // full list of requested time slots + std::string m_maxLoc; + double m_offset = -99999; + double m_kernel = -1.; + + // properties + Gaudi::Property<std::string> m_det {this, "Detector"}; + + Gaudi::Property<std::string> m_readoutTool + {this, "ReadoutTool", "CaloFutureDataProvider", "Name of the readout tool"}; + + Gaudi::Property<std::vector<std::string>> m_seq + {this, "TrajectorySlots", {"Prev1", "T0", "Next1"}, + "sequence of time-slots to be used for trajectory computation"}; + + Gaudi::Property<std::vector<std::string>> m_kern + {this, "RemoveSlotForKernel", {"T0"}, + "sequence of time-slots to be removed from kernel"}; + + Gaudi::Property<std::map<std::string, std::vector<std::string> >> m_asy + {this, "AsymmetrySlots", + { + {"-25.", {"Prev1", "T0"}}, + {"0.", {"T0", "Next1"}} + }, + "pairs of time-slots to be used for asymmetry computation"}; + + // + Gaudi::Property<long> m_zSup {this, "ZeroSuppression", 0, "Zero suppression threshold for hits ADC (sum over BX)"}; + Gaudi::Property<long> m_zInf {this, "MaxSuppression", 99999, "Remove largest ADC"}; + Gaudi::Property<long> m_minD {this, "MinCosmicsDeposit", 0, "minimal ADC sum over hits in cosmics track"}; + Gaudi::Property<long> m_maxD {this, "MaxCosmicsDeposit", 99999, "maximal ADC sum over hits in cosmics track"}; + Gaudi::Property<long> m_minM {this, "MinCosmicsMult", 0, "minimal multiplicity of hits in cosmics track"}; + Gaudi::Property<long> m_maxM {this, "MaxCosmicsMult", 6156, "minimal multiplicity of hits in cosmics track"}; + Gaudi::Property<float> m_tol {this, "MaxDistance2Line", 2.0, "maximal distance between hit and cosmics track (cellSize unit)"}; + + // Timing + Gaudi::Property<float> m_minR {this, "MinR", 0., "minimal asymmetry range to compute time (absolute value)"}; + Gaudi::Property<float> m_maxR {this, "MaxR", 0.8, "maximal asymmetry range to compute time (absolute value)"}; + Gaudi::Property<std::vector<float>> m_par {this, "RtoTime", {1.4, -0.7, 25.0, 0.19}, "parameters to convert R to time "}; + Gaudi::Property<float> m_tRes {this, "TRes", 0, "time resolution parameter"}; + + // Tupling setup + Gaudi::Property<bool> m_tuple {this, "Ntupling" , false, "produce ntuple"}; + Gaudi::Property<int> m_maxAdc {this, "MaxArraySize", 500, "ntuple max array (# cosmics ADCs)"}; + Gaudi::Property<bool> m_full {this, "AllDigits" , false, "fill digit vector with all 0-sup ADC"}; +}; +#endif // CALOFUTURECOSMICSTOOL_H diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureCosmicsTrackAlg.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureCosmicsTrackAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..362c39a4604ff167e80c190eea190283bbdb5c7d --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFutureCosmicsTrackAlg.cpp @@ -0,0 +1,143 @@ +// Include files + +// from LHCb +#include "GaudiKernel/Vector3DTypes.h" +#include "GaudiKernel/Plane3DTypes.h" +#include "LHCbMath/LineTypes.h" +#include "LHCbMath/GeomFun.h" +#include "Event/Track.h" +#include "CaloFutureInterfaces/ICaloFutureCosmicsTool.h" + +// local +#include "CaloFutureCosmicsTrackAlg.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : CaloFutureCosmicsTrackAlg +// +// 2008-04-08 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( CaloFutureCosmicsTrackAlg ) + +//============================================================================= +// Initialization +//============================================================================= +StatusCode CaloFutureCosmicsTrackAlg::initialize() { + StatusCode sc = GaudiTupleAlg::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; // error printed already by GaudiTupleeAlg + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "==> Initialize" << endmsg; + + // tools + m_caloTrack = tool<ICaloFutureCosmicsTrackTool>(m_trackToolType , "TrackTool", this); + + if(m_monitor){ + book1D( "Rec/1" , "Reconstruction performance" , 0. , 5. , 5); + book2D( "Rec/2" , "Ecal versus Hcal timing slot" , -25 , 25. , 2 , -25. , 25. , 2 ); + book1D( "Rec/Forward/1" , "Reconstruction performance (forward)" , 0. , 5. , 5); + book2D( "Rec/Forward/2" , "Ecal versus Hcal timing slot (forward)" , -25 , 25. , 2 , -25. , 25. , 2 ); + book1D( "Rec/Backward/1" , "Reconstruction performance (backward)" , 0. , 5. , 5); + book2D( "Rec/Backward/2" , "Ecal versus Hcal timing slot (backward)" , -25 , 25. , 2 , -25. , 25. , 2 ); + book2D( "Rec/3" , "Cosmics track (phi,theta)" , -3.2 , 0 , 50 , 0 , 3.2 , 50 ); + book1D( "Asymmetry/1", " Ecal asymmetry" , -1., 1.,50); + book1D( "Asymmetry/2", " Hcal asymmetry" , -1., 1.,50); + book1D( "Kernel/1", " Ecal Kernel" , 0., 1., 50); + book1D( "Kernel/2", " Hcal Kernel" , 0., 1., 50); + } + return StatusCode::SUCCESS; +} + +//============================================================================= +// Main execution +//============================================================================= +StatusCode CaloFutureCosmicsTrackAlg::execute() { + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "==> Execute" << endmsg; + setFilterPassed(false); + + if(m_monitor){ + fill( histo1D(HistoID("Rec/1")) , 0. , 1.); // bin0 = counter + fill( histo1D(HistoID("Rec/Forward/1")) , 0. , 1.); // bin0 = counter + fill( histo1D(HistoID("Rec/Backward/1")) , 0. , 1.); // bin0 = counter + } + + + // create and store container + LHCb::Tracks* forwards = new LHCb::Tracks(); + LHCb::Tracks* backwards = new LHCb::Tracks(); + put(forwards, m_forward); + put(backwards, m_backward); + + // process tracking + StatusCode esc = m_caloTrack->processing(); + if(!m_caloTrack->tracked()){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "No track reconstructed" << endmsg; + return StatusCode::SUCCESS; + } + + + //store tracks + LHCb::Track* track = new LHCb::Track(); + track->copy( m_caloTrack->track() ); + ( m_caloTrack->forward() ) ? forwards->insert( track ) : backwards->insert( track ); + + + // Checks + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) { + debug() << " Track ---- " << endmsg; + debug() << " backward : "<< track->checkFlag(LHCb::Track::Flags::Backward) << endmsg; + debug() << " Timed : " << track->checkFlag(LHCb::Track::Flags::Selected) << " / " << m_caloTrack->timed() << endmsg; + debug() << " firstState : "<< track->firstState() << endmsg; + // commented out by VB. 8.8.2k+9 + // debug() << " Time : " << track->likelihood()<< endmsg; + debug() << " Chi2 : " << track->info(LHCb::Track::AdditionalInfo::FitMatchChi2, 999.)<< endmsg; + double z = 8000; + m_caloTrack->propagate( z ); + debug() << "Propagated track ---" << endmsg; + debug() << "Position : " << m_caloTrack->referencePoint() << endmsg; + debug() << "Position Error : " << sqrt(m_caloTrack->referencePointCovariance()) << endmsg; + debug() << "Time : " << m_caloTrack->time() << endmsg; + } + + + + // Monitoring + std::stringstream dir(""); + dir << ( m_caloTrack->forward() ? "Forward/" : "Backward/" ); + if(m_monitor && m_caloTrack->tracked()){ + fill( histo1D(HistoID("Rec/"+dir.str()+"1")) , 1. , 1.); // bin1 = reconstructed + fill( histo1D(HistoID("Rec/1")) , 1. , 1.); // bin1 = reconstructed + fill( histo1D(HistoID("Asymmetry/1")), m_caloTrack->ecal()->asymmetry(), 1.); + fill( histo1D(HistoID("Asymmetry/2")), m_caloTrack->hcal()->asymmetry(), 1.); + fill( histo1D(HistoID("Kernel/1")), m_caloTrack->ecal()->kernel(), 1.); + fill( histo1D(HistoID("Kernel/2")), m_caloTrack->hcal()->kernel(), 1.); + + + double phi = m_caloTrack->phi(); + double theta = m_caloTrack->theta(); + if( !m_caloTrack->forward() ){ + phi += acos(-1.); + if( phi > acos(-1.)) phi -= 2*acos(-1.); // phi in [-pi,pi] + theta = acos(-1.) - theta; // theta in [0,pi] + } + fill( histo2D(HistoID("Rec/3")), phi, theta, 1.); + } + if(m_monitor && m_caloTrack->timed()){ + fill( histo1D(HistoID("Rec/"+dir.str()+"1")) , 2. , 1.); // bin2 = timed (ecal or hcal) + fill( histo1D(HistoID("Rec/1")) , 2. , 1.); // bin2 = timed (ecal or hcal) + } + if(m_monitor && m_caloTrack->ecal()->timed() && m_caloTrack->hcal()->timed()){ + fill( histo1D(HistoID("Rec/"+dir.str()+"1")) , 3. , 1.); // bin2 = ecal+hcal timing + fill( histo2D(HistoID("Rec/"+dir.str()+"2")) , m_caloTrack->ecal()->slot()+12.5, m_caloTrack->hcal()->slot()+12.5, 1. ); + fill( histo1D(HistoID("Rec/1")) , 3. , 1.); // bin2 = ecal+hcal timing + fill( histo2D(HistoID("Rec/2")) , m_caloTrack->ecal()->slot()+12.5, m_caloTrack->hcal()->slot()+12.5, 1. ); + } + + + + if( m_caloTrack->tracked())setFilterPassed(true); + + return StatusCode::SUCCESS; +} diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureCosmicsTrackAlg.h b/CaloFuture/CaloFutureTools/src/CaloFutureCosmicsTrackAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..f4b6281ad33d87277350274fb30c04a71a55f8e0 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFutureCosmicsTrackAlg.h @@ -0,0 +1,40 @@ +#ifndef CALOFUTURECOSMICSTRACKALG_H +#define CALOFUTURECOSMICSTRACKALG_H 1 + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiTupleAlg.h" +// from LHCb +#include "CaloFutureInterfaces/ICaloFutureCosmicsTrackTool.h" + + +/** @class CaloFutureCosmicsTrackAlg CaloFutureCosmicsTrackAlg.h + * + * + * @author Olivier Deschamps + * @date 2008-05-17 + */ +class CaloFutureCosmicsTrackAlg : public GaudiTupleAlg { +public: + /// Standard constructor + using GaudiTupleAlg::GaudiTupleAlg; + + StatusCode initialize() override; ///< Algorithm initialization + StatusCode execute() override; ///< Algorithm execution + +private: + ICaloFutureCosmicsTrackTool* m_caloTrack = nullptr; + + Gaudi::Property<std::string> m_trackToolType + {this, "TrackTool", "CaloFutureCosmicsTrackTool"}; + + Gaudi::Property<std::string> m_forward + {this, "ForwardTrackContainer", LHCb::TrackLocation::CaloCosmicsForward}; + + Gaudi::Property<std::string> m_backward + {this, "BackwardTrackContainer", LHCb::TrackLocation::CaloCosmicsBackward}; + + Gaudi::Property<bool> m_monitor {this, "Monitor", false}; + +}; +#endif // CALOFUTURECOSMICSTRACKALG_H diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureCosmicsTrackTool.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureCosmicsTrackTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..399969fa31b77f2ce7193feb53ac5dd7ddb03003 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFutureCosmicsTrackTool.cpp @@ -0,0 +1,569 @@ +// Include files + +// From std +#include <math.h> + +// from Gaudi +#include "GaudiKernel/PhysicalConstants.h" + +// from LHCb +#include "GaudiKernel/Vector3DTypes.h" +#include "GaudiKernel/Plane3DTypes.h" +#include "LHCbMath/LineTypes.h" +#include "LHCbMath/GeomFun.h" +#include "Event/ODIN.h" +#include "Event/Track.h" +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureInterfaces/ICaloFutureCosmicsTool.h" + +// local +#include "CaloFutureCosmicsTrackTool.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : CaloFutureCosmicsTrackTool +// +// 2008-05-17 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( CaloFutureCosmicsTrackTool ) + + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +CaloFutureCosmicsTrackTool::CaloFutureCosmicsTrackTool( const std::string& type, + const std::string& name, + const IInterface* parent ) + : base_class ( type, name , parent ) +{ + declareInterface<ICaloFutureCosmicsTrackTool>(this); +} + +//============================================================================= +// Initialization +//============================================================================= +StatusCode CaloFutureCosmicsTrackTool::initialize() { + StatusCode sc = base_class::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; + + if ( msgLevel(MSG::DEBUG) ) debug() << "==> Initialize" << endmsg; + + // tools + m_eCosmics = tool<ICaloFutureCosmicsTool>(m_cosmics , "Ecal", this); + m_hCosmics = tool<ICaloFutureCosmicsTool>(m_cosmics , "Hcal", this); + // odin + m_odin = tool<IEventTimeDecoder>("OdinTimeDecoder","OdinDecoder",this); + + return StatusCode::SUCCESS; +} + +//============================================================================= +// Main execution +//============================================================================= +StatusCode CaloFutureCosmicsTrackTool::processing() { + + if ( msgLevel(MSG::DEBUG) ) debug() << "==> Execute" << endmsg; + + + m_odin->getTime(); + m_run = -1; + m_evt = -1; + m_bx = -1; + LHCb::ODIN* odin = getIfExists<LHCb::ODIN> (LHCb::ODINLocation::Default); + if( odin ){ + m_run = odin->runNumber(); + m_evt = (long) odin->eventNumber() ; + m_bx = odin->bunchId() ; + } + + // init + m_track.reset(); + m_tracked=false; + m_timed = false; + m_time = -999.; + m_stime = 999.; + m_chi2 = 9999.; + m_phi = -999.; + m_sPhi = 999.; + m_theta = -999.; + m_sTheta = 999.; + m_dir = 0; + m_ref = 0; // Ecal is reference by default + m_refPoint[0] = Gaudi::XYZPoint(); + m_refPointCov[0]=Gaudi::SymMatrix3x3(); + m_refPt = Gaudi::XYZPoint(); + m_refPtCov=Gaudi::SymMatrix3x3(); + // + StatusCode esc = ecal()->processing(); + StatusCode hsc = hcal()->processing(); + if(esc.isFailure() ) + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "EcalCosmic processing failed"<<endmsg; + if(hsc.isFailure() ) + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "HcalCosmic processing failed"<<endmsg; + + + if( !ecal()->tracked() || !hcal()->tracked() ){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Cannot reconstruct Cosmics (Ecal/Hcal):(" + <<ecal()->tracked()<<"/"<<hcal()->tracked()<<")"<<endmsg; + return StatusCode::SUCCESS; + } + + + // 1) ecal-hcal matching + if( matching().isFailure() )return StatusCode::SUCCESS; + + // 2) reconstruct 3D trajectory + if( fit3D().isFailure() )return StatusCode::SUCCESS; + + // 3) Produce Track object + if( buildTrack().isFailure() )return StatusCode::SUCCESS; + m_tracked = true; + + + // 4) Timing + m_timed = true; + if(m_timer == "Ecal" ){ + if(ecal()->timed()){ + m_time = ecal()->time(); + m_stime = ecal()->timeVariance(); + }else{ + m_timed = false; + } + } + else if(m_timer == "Hcal" ){ + if(hcal()->timed()){ + m_time = hcal()->time(); + m_stime = hcal()->timeVariance(); + }else{ + m_timed = false; + } + } + else if(m_timer == "EcalElseHcal" ){ + if(ecal()->timed() ){ + m_time = ecal()->time(); + m_stime = ecal()->timeVariance(); + }else if(hcal()->timed() ){ + m_time=hcal()->time(); + m_stime = hcal()->timeVariance(); + } else m_timed = false; + } else{ + warning() << "Unexpected timer : '" << m_timer << "' -> NO TIMING INFORMATION" << endmsg; + m_timed = false; + } + // Update track info + if( timed() ){ + m_track.setFlag( LHCb::Track::Flags::Selected , true ); + // not stored anymore in Track class SHM + //m_track.addInfo( LHCb::Track::CaloFutureTimeInfo, m_time ); + } + + + // 5) Ntupling + if(m_tuple){ + if( tupling(500).isFailure())return StatusCode::FAILURE; + } + + return StatusCode::SUCCESS; +} + + +//============================================================================= +StatusCode CaloFutureCosmicsTrackTool::matching(){ + + // match Ecal and Hcal + // return phi and Chi2 + + m_chi2 = 9999; + + + Gaudi::XYZVector vec = ecal()->referencePoint()-hcal()->referencePoint(); + m_dir = (vec.Y() > 0) ? +1 : -1; + // Phi = atan(DX/DY) + double dX = vec.X(); + double dY = vec.Y(); + double s2X = ecal()->referencePointVariance().X()+ hcal()->referencePointVariance().X(); + double s2Y = ecal()->referencePointVariance().Y()+ hcal()->referencePointVariance().Y(); + m_phi = (dX != 0) ? atan( dY/dX ) : acos( 0. ); + double d2 = (dX*dX+dY*dY); + m_sPhi = (d2 !=0) ? dY*dY/d2/d2*s2X + dX*dX/d2/d2*s2Y : acos(-1.)*acos(-1.); + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " Phi = " << m_phi << " +- " << m_sPhi << endmsg; + // Chi2 = (phi-phi_eca<l)^2/sig^2 + (phi-phi_hcal)^2/sig^2 + double ePhi = ecal()->phi(); + double hPhi = hcal()->phi(); + double s2ePhi = ecal()->phiVariance(); + double s2hPhi = hcal()->phiVariance(); + + if(m_phi<0)m_phi += acos(-1.); + if(ePhi<0)ePhi += acos(-1.); + if(hPhi<0)hPhi += acos(-1.); + + m_chi2 = (m_phi-ePhi)*(m_phi-ePhi)/(s2ePhi+m_sPhi) + (m_phi-hPhi)*(m_phi-hPhi)/(s2hPhi+m_sPhi); + m_chi2 /= 2.; + + // + if(m_dir == 1)m_phi -= acos(-1.); + + + + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " Chi2 = " << m_chi2 << endmsg; + + if(m_chi2 > m_chi2max)return StatusCode::FAILURE; + if(m_chi2 < m_chi2min)return StatusCode::FAILURE; + return StatusCode::SUCCESS; +} + + + + + +//============================================================================= +StatusCode CaloFutureCosmicsTrackTool::fit3D(){ + + Gaudi::Plane3D backEcal = ecal()->det()->plane(CaloPlane::Back); + Gaudi::Plane3D frontHcal = hcal()->det()->plane(CaloPlane::Front); + Gaudi::Plane3D frontEcal = ecal()->det()->plane(CaloPlane::Front); + // Gaudi::Plane3D middleEcal = ecal()->det()->plane(CaloPlane::Middle); + // Gaudi::Plane3D middleHcal = hcal()->det()->plane(CaloPlane::Middle); + Gaudi::Plane3D backHcal = hcal()->det()->plane(CaloPlane::Back); + + // Assign closest Ecal/Hcal cells to the back/front plane respectively + typedef std::pair<Gaudi::XYZPoint,Gaudi::XYZPoint> pointPair; + pointPair eBound = ecal()->extrema(); + pointPair hBound = hcal()->extrema(); + Gaudi::XYZPoint eP = eBound.first; + Gaudi::XYZPoint hP = hBound.first; + Gaudi::XYZPoint eM = eBound.second; + Gaudi::XYZPoint hM = hBound.second; + if( dist2D(eBound.first ,hBound.second) < dist2D(eP,hP)){eP=eBound.first;hP=hBound.second;eM=eBound.second;hM=hBound.first;} + if( dist2D(eBound.second,hBound.second) < dist2D(eP,hP)){eP=eBound.second;hP=hBound.second;eM=eBound.first;hM=hBound.first;} + if( dist2D(eBound.second,hBound.first) < dist2D(eP,hP)){eP=eBound.second;hP=hBound.first;eM=eBound.first;hM=hBound.second;} + // + double ePZ=( -backEcal.Normal().X()*eP.X()-backEcal.Normal().Y()*eP.Y() - backEcal.HesseDistance() )/backEcal.Normal().Z(); + double hPZ=(-frontHcal.Normal().X()*hP.X()-frontHcal.Normal().Y()*hP.Y()-frontHcal.HesseDistance() )/frontHcal.Normal().Z(); + eP.SetZ(ePZ); + hP.SetZ(hPZ); + double eMZ=(-frontEcal.Normal().X()*eM.X()-frontEcal.Normal().Y()*eM.Y()-frontEcal.HesseDistance() )/frontEcal.Normal().Z(); + double hMZ=(-backHcal.Normal().X()*hM.X()-backHcal.Normal().Y()*hM.Y()-backHcal.HesseDistance() )/backHcal.Normal().Z(); + eM.SetZ(eMZ); + hM.SetZ(hMZ); + const LHCb::CaloCellID ePId = ecal()->det()->Cell( eP ); + const LHCb::CaloCellID hPId = hcal()->det()->Cell( hP ); + const LHCb::CaloCellID eMId = ecal()->det()->Cell( eM ); + const LHCb::CaloCellID hMId = hcal()->det()->Cell( hM ); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) { + debug() << "Closest Points " << eP << "/" << hP <<endmsg; + debug() << "--> " << ePId << "/" << hPId <<endmsg; + debug() << "Farest Points " << eM << "/" << hM <<endmsg; + debug() << "--> " << eMId << "/" << hMId <<endmsg; + } + // + std::vector<pointPair> points; // position and variance + double ePSig = ecal()->det()->cellSize(ePId)*m_fac; + double hPSig = hcal()->det()->cellSize(hPId)*m_fac; + double eMSig = ecal()->det()->cellSize(eMId)*m_fac; + double hMSig = hcal()->det()->cellSize(hMId)*m_fac; + ePSig *= ePSig/12.; + hPSig *= hPSig/12.; + eMSig *= eMSig/12.; + hMSig *= hMSig/12.; + + // closest point + if(m_intern){ + points.push_back(std::make_pair(eP , Gaudi::XYZPoint(ePSig,ePSig,0.))); + points.push_back(std::make_pair(hP , Gaudi::XYZPoint(hPSig,hPSig,0.))); + } + + // middle plane (should depend on the trajectory.vs.acceptance) + points.push_back( std::make_pair( ecal()->referencePoint(),ecal()->referencePointVariance())); + points.push_back( std::make_pair( hcal()->referencePoint(),hcal()->referencePointVariance())); + + if(m_extern){ + // maxima (should depend on the trajectory.vs.acceptance) + points.push_back( std::make_pair(eM, Gaudi::XYZPoint(eMSig,eMSig,0.))); + points.push_back( std::make_pair(hM, Gaudi::XYZPoint(hMSig,hMSig,0.))); + } + + /* + // @TODO TAKE THE TRAJECTORY.vs.ACCEPTANCE INTO ACCOUNT + Gaudi::Math::XYZLine line(eP, hP-eP); // 3D line + // if the 3D line is in the whole Ecal acceptance add Ecal middle and front plane points + Gaudi::XYZPoint point; + double mu; + Gaudi::Math::intersection<Gaudi::Math::XYZLine,Gaudi::Plane3D>(line,frontEcal,point,mu); + if( ecal()()->det()->geometry()->isInside(point) ){ + debug() << " cosmics cross the whole Ecal" << endmsg; + const LHCb::CaloCellID id = ecal()->det()->Cell( point ); + points.push_back( std::make_pair(eM, Gaudi::XYZPoint(eMsig,eMsig,0.))); + } + Gaudi::Math::intersection<Gaudi::Math::XYZLine,Gaudi::Plane3D>(line,backHcal,point,mu); + if( hcal()()->det()->geometry()->isInside(point) ){ + debug() << " cosmics cross the whole Hcal" << endmsg; + const LHCb::CaloCellID id = hcal()->det()->Cell( point ); + points.push_back( std::make_pair(hM, Gaudi::XYZPoint(hMsig,hMsig,0.))); + } + */ + + // + double Ax = 0; + double Bx = 0; + double Cx = 0; + double Dx = 0; + double Ex = 0; + double Ay = 0; + double By = 0; + double Cy = 0; + double Dy = 0; + double Ey = 0; + + Gaudi::XYZVector d = ecal()->referencePoint()-hcal()->referencePoint(); + + for(std::vector<pointPair>::iterator ip = points.begin() ; ip != points.end() ; ip++){ + pointPair p = *ip; + double sig2X= p.second.X()+ d.X()/d.Z()*p.second.Z(); + double sig2Y= p.second.Y()+ d.Y()/d.Z()*p.second.Z(); + Ax += p.first.Z()*p.first.Z()/sig2X; + Bx += p.first.Z()/sig2X; + Cx += -(p.first.X()*p.first.Z())/sig2X; + Dx += 1./sig2X; + Ex += -p.first.X()/sig2X; + // + Ay += p.first.Z()*p.first.Z()/sig2Y; + By += p.first.Z()/sig2Y; + Cy += -(p.first.Y()*p.first.Z())/sig2Y; + Dy += 1./sig2Y; + Ey += -p.first.Y()/sig2Y; + } + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) { + debug() << "(A->E)x " << Ax << " " << Bx << " " << Cx << " " << Dx << " " << Ex << endmsg; + debug() << "(A->E)y " << Ay << " " << By << " " << Cy << " " << Dy << " " << Ey << endmsg; + } + + m_tx = -(Dx*Cx-Bx*Ex)/(Ax*Dx-Bx*Bx); + m_ty = -(Dy*Cy-By*Ey)/(Ay*Dy-By*By); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "tx = " << m_tx << " ty = " << m_ty << endmsg; + double x0 = (Bx*Cx-Ax*Ex)/(Ax*Dx-Bx*Bx); + double y0 = (By*Cy-Ay*Ey)/(Ay*Dy-By*By); + + // Theta + double tth = sqrt( m_tx*m_tx + m_ty*m_ty); + m_theta = atan( tth ); + // Approximate error + Gaudi::XYZVector sD = hcal()->referencePointVariance() - (-1.)*ecal()->referencePointVariance(); + m_stx = m_tx*m_tx * (sD.X()/d.X()/d.X() + sD.Z()/d.Z()/d.Z() ); + m_sty = m_ty*m_ty * (sD.Y()/d.Y()/d.Y() + sD.Z()/d.Z()/d.Z() ); + double sTth = (m_tx/tth)*(m_tx/tth) * m_stx + (m_ty/tth)*(m_ty/tth) * m_sty; + m_sTheta = sTth / (1+tth*tth)/(1+tth*tth); + + // Phi + double tphi = m_ty/m_tx; + m_phi = atan(tphi); + if(m_phi<0.)m_phi += acos(-1.); + if(m_dir == 1)m_phi -= acos(-1.); + + // Ecal reference + double ex = x0 + m_tx *ecal()->referencePoint().Z(); + double ey = y0 + m_ty *ecal()->referencePoint().Z(); + m_refPoint[0].SetX(ex); + m_refPoint[0].SetY(ey); + m_refPoint[0].SetZ( ecal()->referencePoint().Z() ); + m_refPointCov[0](0,0) = ecal()->referencePointVariance().X(); // APPROXIMATIVE ERROR + m_refPointCov[0](1,1) = ecal()->referencePointVariance().Y(); // APPROXIMATIVE ERROR + // Hcal reference + double hx = x0 + m_tx *hcal()->referencePoint().Z(); + double hy = y0 + m_ty *hcal()->referencePoint().Z(); + m_refPoint[1].SetX(hx); + m_refPoint[1].SetY(hy); + m_refPoint[1].SetZ( hcal()->referencePoint().Z() ); + m_refPointCov[1](0,0)= hcal()->referencePointVariance().X(); // APPROXIMATIVE ERROR + m_refPointCov[1](1,1)= hcal()->referencePointVariance().Y(); // APPROXIMATIVE ERROR + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) { + debug() << " Ecal Reference Point : (" + << ecal()->referencePoint().X() << "," + << ecal()->referencePoint().Y() << "," + << ecal()->referencePoint().Z() << ") " + << " -> Fit3D : (" + << ex << "," + << ey << "," + << ecal()->referencePoint().Z() << ") " << endmsg; + debug() << " Theta = " << m_theta << endmsg; + } + + m_slopes = Gaudi::XYZVector( m_tx, m_ty , m_dir ); + m_slopesCov(0,0) = m_stx; + m_slopesCov(1,1) = m_sty; + + return StatusCode::SUCCESS; +} +//============================================================================= +double CaloFutureCosmicsTrackTool::dist2D(Gaudi::XYZPoint p1 ,Gaudi::XYZPoint p2){ + Gaudi::XYZVector v = p1-p2; + return v.rho(); +} +//============================================================================= +StatusCode CaloFutureCosmicsTrackTool::buildTrack(){ + + + // Gaudi::XYZVector direction = hcal()->referencePoint() - ecal()->referencePoint(); + + Gaudi::TrackVector eTrV ; + Gaudi::TrackSymMatrix eTrM; + eTrV(0) = m_refPoint[0].X(); + eTrV(1) = m_refPoint[0].Y(); + eTrV(2) = m_tx; + eTrV(3) = m_ty; + eTrV(4) = 1./ ecal()->deposit() ; + eTrM(0,0) = m_refPointCov[0](0,0); + eTrM(1,1) = m_refPointCov[0](1,1); + eTrM(2,2) = m_stx; + eTrM(3,3) = m_sty; + LHCb::State eState = LHCb::State( eTrV , eTrM , ecal()->referencePoint().Z() , LHCb::State::Location::MidECal); + + + Gaudi::TrackVector hTrV ; + Gaudi::TrackSymMatrix hTrM; + hTrV(0) = m_refPoint[1].X(); + hTrV(1) = m_refPoint[1].Y(); + hTrV(2) = m_tx; + hTrV(3) = m_ty; + hTrV(4) = 1./ hcal()->deposit() ; + hTrM(0,0) = m_refPointCov[1](0,0); + hTrM(1,1) = m_refPointCov[1](1,1); + hTrM(2,2) = m_stx; + hTrM(3,3) = m_sty; + + LHCb::State hState = LHCb::State( hTrV , hTrM , hcal()->referencePoint().Z() , LHCb::State::Location::MidHCal); + + // Track + m_track.setType(LHCb::Track::Types::Calo); + // Default reference position is Ecal + m_ref = 0; // reference is Ecal by default + // Set first state according to 'timer' + if(m_timer == "Ecal"){ + m_track.addToStates( eState ); // 1st state is Ecal + m_track.addToStates( hState ); + } + else if(m_timer == "Hcal"){ + m_ref = 1; // reference is Hcal + m_track.addToStates( hState ); // 1st state is Hcal + m_track.addToStates( eState ); + } + else if(m_timer == "EcalElseHcal"){ + if( !ecal()->timed() && hcal()->timed()){ + m_ref = 1; // reference is Hcal + m_track.addToStates( hState ); // 1st state is Hcal + m_track.addToStates( eState ); + }else{ + m_track.addToStates( eState ); // 1st state is Ecal + m_track.addToStates( hState ); + } + } + else{ + warning() << "Unexpected timer : '" << m_timer << "' -> 1st state is Ecal by default" << endmsg; + m_track.addToStates( eState ); // 1st state is Ecal + m_track.addToStates( hState ); + } + + // not stored anymore in Track class + //m_track.addInfo( LHCb::Track::CaloFutureMatchChi2, m_chi2); + if( !forward())m_track.setFlag( LHCb::Track::Flags::Backward, true ); + + + // Global reference + m_refPt = m_refPoint[m_ref]; + m_refPtCov = m_refPointCov[m_ref]; + + return StatusCode::SUCCESS; +} + + +//============================================================================= +StatusCode CaloFutureCosmicsTrackTool::tupling(unsigned int unit){ + + + if( ecal()->tupling(unit+1).isFailure())return StatusCode::FAILURE; + if( hcal()->tupling(unit+2).isFailure())return StatusCode::FAILURE; + + + Tuple ntp = nTuple(unit, "CosmicsTrack" ,CLID_ColumnWiseTuple); + StatusCode sc; + Gaudi::XYZVector vec = hcal()->referencePoint()-ecal()->referencePoint(); + sc = ntp->column("Run" , m_run ); + sc = ntp->column("Event" , m_evt ); + sc = ntp->column("BCID" , m_bx ); + sc = ntp->column("L" , vec.R() ); + sc = ntp->column("eTime" , ecal()->time()); + sc = ntp->column("hTime" , hcal()->time()); + sc = ntp->column("eSlot" , ecal()->slot() ); + sc = ntp->column("hSlot" , hcal()->slot() ); + sc = ntp->column("eDep" , ecal()->deposit() ); + sc = ntp->column("hDep" , hcal()->deposit() ); + sc = ntp->column("direction" , m_dir); + sc = ntp->column("L" , vec.R() ); + sc = ntp->column("chi2" , m_chi2 ); + sc = ntp->column("phi" , m_phi ); + sc = ntp->column("phiVariance", sqrt( m_sPhi ) ); + sc = ntp->column("theta" , m_theta ); + sc = ntp->column("thetaVariance", m_sTheta ); + sc = ntp->column("th" , vec.theta( )); + sc = ntp->column("ph" , vec.phi( )); + sc = ntp->column("ecalRefX" , m_refPoint[0].X() ); + sc = ntp->column("ecalRefY" , m_refPoint[0].Y() ); + sc = ntp->column("ecalRefZ" , m_refPoint[0].Z() ); + sc = ntp->column("hcalRefX" , m_refPoint[1].X() ); + sc = ntp->column("hcalRefY" , m_refPoint[1].Y() ); + sc = ntp->column("hcalRefZ" , m_refPoint[1].Z() ); + sc = ntp->column("eTimed" , (int)ecal()->timed()); + sc = ntp->column("hTimed" , (int)hcal()->timed()); + sc = ntp->column("eR" , ecal()->asymmetry()); + sc = ntp->column("hR" , hcal()->asymmetry()); + sc = ntp->column("dX" , vec.X()); + sc = ntp->column("dY" , vec.Y()); + sc = ntp->column("dZ" , vec.Z()); + + sc=ntp->write(); + + + if(sc.isFailure())Warning(name() + " Ntupling failed").ignore(); + return sc; +} + + + +StatusCode CaloFutureCosmicsTrackTool::propagate(double z){ + Gaudi::XYZPoint ref = m_refPoint[m_ref]; + Gaudi::SymMatrix3x3 refCov = m_refPointCov[m_ref]; + m_refPt.SetX( ref.X() + slopes().X() * (z-ref.Z()) ); + m_refPt.SetY( ref.Y() + slopes().Y() * (z-ref.Z()) ); + m_refPt.SetZ( z ); + m_refPtCov(0,0) = (refCov(0,0) + slopesCovariance()(0,0) * (z-ref.Z()) * (z-ref.Z())); + m_refPtCov(1,1) = (refCov(1,1) + slopesCovariance()(1,1) * (z-ref.Z()) * (z-ref.Z())); + if( !timed() )return StatusCode::SUCCESS; + double time = (m_ref == 0) ? ecal()->time() : hcal()->time(); + Gaudi::XYZVector vec = m_refPt - m_refPoint[m_ref]; + double sign = 0; + if( vec.Z() != 0)sign = vec.Z()/fabs(vec.Z())*m_dir; + m_time = time + (vec.R() / Gaudi::Units::c_light) *sign; + return StatusCode::SUCCESS; +} + + +StatusCode CaloFutureCosmicsTrackTool::propagate(Gaudi::Plane3D plane){ + Gaudi::XYZPoint ref = m_refPoint[m_ref]; + Gaudi::XYZVector vec = slopes()/slopes().R(); + Gaudi::Math::XYZLine line(ref, vec); + Gaudi::XYZPoint point; + double mu; + Gaudi::Math::intersection<Gaudi::Math::XYZLine,Gaudi::Plane3D>(line,plane,point,mu); + return propagate( point.Z() ); +} diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureCosmicsTrackTool.h b/CaloFuture/CaloFutureTools/src/CaloFutureCosmicsTrackTool.h new file mode 100644 index 0000000000000000000000000000000000000000..5d9dd1ef60742bf0c8f024b6160881a6cd16ab96 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFutureCosmicsTrackTool.h @@ -0,0 +1,95 @@ +#ifndef CALOFUTURECOSMICSTRACKTOOL_H +#define CALOFUTURECOSMICSTRACKTOOL_H 1 + +// Include files +// from Gaudi +#include "GaudiKernel/IEventTimeDecoder.h" +#include "GaudiAlg/GaudiTupleTool.h" + +// from LHCb +#include "CaloFutureInterfaces/ICaloFutureCosmicsTrackTool.h" // Interface + +/** @class CaloFutureCosmicsTrackTool CaloFutureCosmicsTrackTool.h + * + * + * @author Olivier Deschamps + * @date 2008-05-17 + */ +class CaloFutureCosmicsTrackTool : public extends<GaudiTupleTool, ICaloFutureCosmicsTrackTool> { +public: + /// Standard constructor + CaloFutureCosmicsTrackTool( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + // + StatusCode processing() override; + StatusCode tupling(unsigned int unit) override; + double phi() override {return m_phi;} + double phiVariance() override {return m_sPhi;} + double theta() override {return m_theta;} + double thetaVariance() override {return m_sTheta;} + const Gaudi::XYZVector slopes() override {return m_slopes;} + const Gaudi::XYZPoint referencePoint() override { return m_refPt;} + const Gaudi::SymMatrix3x3 slopesCovariance() override {return m_slopesCov;} + const Gaudi::SymMatrix3x3 referencePointCovariance() override { return m_refPtCov;} + bool forward() override {return (m_dir == 1) ? true : false;} + bool tracked() override {return m_tracked;} + double time() override {return m_time;} + double timeVariance() override {return m_stime;} + bool timed() override {return m_timed;} + ICaloFutureCosmicsTool* ecal() override {return m_eCosmics;} + ICaloFutureCosmicsTool* hcal() override {return m_hCosmics;} + const LHCb::Track& track() override {return m_track;} + StatusCode propagate(Gaudi::Plane3D plane) override; + StatusCode propagate(double z ) override; + +private: + StatusCode matching(); + StatusCode fit3D(); + double dist2D(Gaudi::XYZPoint,Gaudi::XYZPoint); + StatusCode buildTrack(); + + // + ICaloFutureCosmicsTool* m_eCosmics = nullptr; + ICaloFutureCosmicsTool* m_hCosmics = nullptr; + IEventTimeDecoder* m_odin = nullptr; + // + long m_run; + long m_evt; + long m_bx; + double m_tx; + double m_ty; + Gaudi::XYZVector m_slopes; + Gaudi::SymMatrix3x3 m_slopesCov; + double m_stx; + double m_sty; + double m_theta; + double m_sTheta; + double m_phi; + double m_sPhi; + double m_chi2; + Gaudi::Property<bool> m_intern {this, "UseInternalPlanes", false}; + Gaudi::Property<bool> m_extern {this, "UseExternalPlanes", false}; + double m_time; + double m_stime; + Gaudi::XYZPoint m_refPoint[2]; + Gaudi::SymMatrix3x3 m_refPointCov[2]; + Gaudi::XYZPoint m_refPt; + Gaudi::SymMatrix3x3 m_refPtCov; + int m_ref; + + int m_dir; + bool m_tracked; + bool m_timed; + LHCb::Track m_track; + // properties + Gaudi::Property<std::string> m_cosmics {this, "CosmicsTool", "CaloFutureCosmicsTool"}; + Gaudi::Property<float> m_chi2max {this, "MaxChi2", 15}; + Gaudi::Property<float> m_chi2min {this, "MinChi2", 0}; + Gaudi::Property<float> m_fac {this, "Factor", 1.5}; + Gaudi::Property<bool> m_tuple {this, "Ntupling", false, "produce ntuple"}; + Gaudi::Property<std::string> m_timer {this, "Timer", "EcalElseHcal"}; +}; +#endif // CALOFUTURECOSMICSTRACKTOOL_H diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureElectron.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureElectron.cpp new file mode 100644 index 0000000000000000000000000000000000000000..44c67e6b53284a15f3e7f151d498e667225ba818 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFutureElectron.cpp @@ -0,0 +1,128 @@ +// Include files + +// LHCb +#include "GaudiKernel/Point3DTypes.h" +#include "GaudiKernel/Vector3DTypes.h" +#include "Event/Particle.h" + +// local +#include "CaloFutureElectron.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : CaloFutureElectron +// +// 2006-11-30 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( CaloFutureElectron ) + + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +CaloFutureElectron::CaloFutureElectron( const std::string& type, + const std::string& name, + const IInterface* parent ) +: base_class ( type, name , parent ) +{ + declareInterface<ICaloFutureElectron>(this); +} + +//============================================================================= +bool CaloFutureElectron::set(const LHCb::Particle* particle, std::string det,CaloPlane::Plane plane , double delta){ + m_status = setting(particle) && caloSetting(); + if( m_status )return Part2CaloFuture::match(particle , det, plane, delta ); + return m_status; +} +bool CaloFutureElectron::set(const LHCb::ProtoParticle* proto, std::string det,CaloPlane::Plane plane , double delta){ + m_status = setting(proto) && caloSetting(); + if( m_status )return Part2CaloFuture::match(proto , det, plane, delta ); + return m_status; +} +//============================================================================= +LHCb::CaloHypo* CaloFutureElectron::electron(){ + return m_electron; +} +//============================================================================= +LHCb::CaloHypo* CaloFutureElectron::bremstrahlung(){ + return m_bremstrahlung; +} +//============================================================================= +LHCb::CaloMomentum CaloFutureElectron::bremCaloFutureMomentum(){ + if(!m_status || NULL == m_bremstrahlung )return LHCb::CaloMomentum(); + Gaudi::XYZPoint point; + Gaudi::SymMatrix3x3 matrix; + m_track->position(point,matrix); + LHCb::CaloMomentum bremPhoton( m_bremstrahlung ,point, matrix); + return bremPhoton; +} + +//============================================================================= +double CaloFutureElectron::ecalE(){ + if( !m_status )return 0.; + return (double) m_electron->e() ; +} +//============================================================================= +double CaloFutureElectron::eOverP(){ + if( !m_status )return 0.; + return (double) m_electron->e()/m_track->p(); +} +//============================================================================= +LHCb::State CaloFutureElectron::closestState(std::string toWhat ){ + LHCb::State state; // empty state + if( !m_status ) return state; + // get hypo position + double x = 0. ; + double y = 0. ; + if( "hypo" == toWhat ){ + x = m_calopos->parameters()(LHCb::CaloPosition::Index::X); + y = m_calopos->parameters()(LHCb::CaloPosition::Index::Y); + }else if("cluster" == toWhat ){ + x = m_calopos->center()(LHCb::CaloPosition::Index::X); + y = m_calopos->center()(LHCb::CaloPosition::Index::Y); + }else{ + return state; + } + // default to electron + LHCb::Tr::PID pid = ( m_particle ? LHCb::Tr::PID(m_particle->particleID().abspid()) : LHCb::Tr::PID::Electron() ); + return Part2CaloFuture::closestState(x,y, pid); +} +//============================================================================= +double CaloFutureElectron::caloTrajectoryZ(CaloPlane::Plane refPlane , std::string toWhat ){ + LHCb::State theState = closestState( toWhat ); + LHCb::State refState = caloState( refPlane ); + return m_zOffset + theState.z() - refState.z(); +} +//============================================================================= +double CaloFutureElectron::caloTrajectoryL(CaloPlane::Plane refPlane , std::string toWhat ){ + LHCb::State theState = closestState( toWhat ); + LHCb::State refState = caloState( refPlane ); + Gaudi::XYZVector depth = theState.position()-refState.position(); + ROOT::Math::Plane3D plane = m_calo->plane( refPlane ); + double dist = plane.Distance( theState.position() );//signed distance to refPlane + return depth.R() * dist/fabs(dist); +} + +//============================================================================= +bool CaloFutureElectron::caloSetting(){ + // CaloFuture setting + m_electron = NULL; + m_bremstrahlung = NULL; + m_calopos = NULL; + + SmartRefVector<LHCb::CaloHypo> hypos = m_proto->calo(); + if(0 == hypos.size())return false; + + for(SmartRefVector<LHCb::CaloHypo>::const_iterator ihypo = hypos.begin(); ihypo != hypos.end() ; ++ihypo){ + const LHCb::CaloHypo* hypo = *ihypo; + if(NULL == hypo)continue; + if( LHCb::CaloHypo::Hypothesis::EmCharged == hypo->hypothesis() ) m_electron = (LHCb::CaloHypo*) hypo; + if( LHCb::CaloHypo::Hypothesis::Photon == hypo->hypothesis() ) m_bremstrahlung = (LHCb::CaloHypo*) hypo; + } + if( NULL == m_electron )return false; // Electron hypo is mandatory - brem. not + m_calopos = m_electron->position(); + if( NULL == m_calopos) return false; + return true; +} + diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureElectron.h b/CaloFuture/CaloFutureTools/src/CaloFutureElectron.h new file mode 100644 index 0000000000000000000000000000000000000000..d65dfef59aeefda6d2fed1b2d1cbbf56a772fd21 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFutureElectron.h @@ -0,0 +1,61 @@ +#ifndef CALOFUTUREELECTRON_H +#define CALOFUTUREELECTRON_H 1 + +// Include files +#include "Part2CaloFuture.h" + +//from LHCb +#include "CaloFutureUtils/ICaloFutureElectron.h" +#include "CaloFutureUtils/CaloMomentum.h" + +// Forward declarations +namespace LHCb +{ + class ProtoParticle; +} + + +/** @class CaloFutureElectron CaloFutureElectron.h + * + * + * @author Olivier Deschamps + * @date 2006-11-30 + */ +class CaloFutureElectron : public extends<Part2CaloFuture, ICaloFutureElectron> { +public: + /// Standard constructor + CaloFutureElectron( const std::string& type, + const std::string& name, + const IInterface* parent); + + bool set(const LHCb::Particle* particle, + std::string det = DeCalorimeterLocation::Ecal, + CaloPlane::Plane plane = CaloPlane::ShowerMax, + double delta =0 ) override; + bool set(const LHCb::ProtoParticle* proto, + std::string det = DeCalorimeterLocation::Ecal, + CaloPlane::Plane plane = CaloPlane::ShowerMax, + double delta =0 ) override; + + LHCb::CaloHypo* electron() override; + LHCb::CaloHypo* bremstrahlung() override; + LHCb::CaloMomentum bremCaloFutureMomentum() override; + double ecalE() override; + double eOverP() override; + using ICaloFutureElectron::closestState; + LHCb::State closestState(std::string toWhat = "hypo") override; + double caloTrajectoryZ(CaloPlane::Plane refPlane = CaloPlane::ShowerMax ,std::string toWhat = "hypo") override; + double caloTrajectoryL(CaloPlane::Plane refPlane = CaloPlane::ShowerMax ,std::string toWhat = "hypo") override; + + + +protected: + bool caloSetting (); +private: + LHCb::CaloHypo* m_electron = nullptr; + LHCb::CaloHypo* m_bremstrahlung = nullptr; + const LHCb::CaloPosition* m_calopos = nullptr; + Gaudi::Property<float> m_zOffset + {this, "zOffset", 0, "Should be 0.0 if ShowerMax plane is correctly defined in condDB"}; +}; +#endif // CALOFUTUREELECTRON_H diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureGetterTool.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureGetterTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..813e522722c1e2be4f3c8f9fe8eb8fdfff9ff0c0 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFutureGetterTool.cpp @@ -0,0 +1,246 @@ +// ============================================================================ +// Include files +// ============================================================================ +// from Gaudi +// ============================================================================ +#include "GaudiKernel/IIncidentSvc.h" +#include "GaudiKernel/Incident.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +// ============================================================================ +// local +// ============================================================================ +#include "CaloFutureGetterTool.h" +// ============================================================================ +/** @file + * Implementation file for class : CaloFutureGetterTool + * + * @date 2009-04-17 + * @author Olivier Deschamps + */ +// ============================================================================ +// Declaration of the Tool Factory +DECLARE_COMPONENT( CaloFutureGetterTool ) +// ============================================================================ +// Standard constructor, initializes variables +// ============================================================================ +CaloFutureGetterTool::CaloFutureGetterTool ( const std::string& type, const std::string& name, + const IInterface* parent ) +: base_class ( type, name , parent ) +{ + declareInterface<ICaloFutureGetterTool>(this); + + std::string flag = context(); + if( std::string::npos != name.find ("HLT") || + std::string::npos != name.find ("Hlt") )flag="Hlt"; + + // digits + if((m_detMask&8)!=0)m_digiLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation( "Hcal" , flag ) ) ; + if((m_detMask&4)!=0)m_digiLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation( "Ecal" , flag ) ) ; + if((m_detMask&2)!=0)m_digiLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation( "Prs" , flag ) ) ; + if((m_detMask&1)!=0)m_digiLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureDigitLocation( "Spd" , flag ) ) ; + + if((m_detMask&8)!=0)m_clusLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureClusterLocation( "Hcal" , flag ) ) ; + if((m_detMask&4)!=0)m_clusLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureClusterLocation( "Ecal" , flag ) ) ; + m_clusLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureSplitClusterLocation( flag ) ) ; + + m_hypoLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation("Photons" , flag ) ); + m_hypoLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation("Electrons" , flag ) ); + m_hypoLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation("SplitPhotons" , flag ) ); + m_hypoLoc.value().push_back( LHCb::CaloFutureAlgUtils::CaloFutureHypoLocation("MergedPi0s" , flag ) ); +} + +// ============================================================================ + +StatusCode CaloFutureGetterTool::initialize() +{ + StatusCode sc = base_class::initialize(); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) )debug() << "Initialize CaloFuture2CaloFuture tool " << endmsg; + + counterStat = tool<IFutureCounterLevel>("FutureCounterLevel"); + + if( m_detMask != 0xF) info() << "Incomplete calorimeter detector is requested - mask = " << m_detMask.value() << endmsg; + // + if((m_detMask&8)!=0)m_provider["Hcal"] = tool<ICaloFutureDataProvider>( "CaloFutureDataProvider" , "FutureHcalDataProvider" ); + if((m_detMask&4)!=0)m_provider["Ecal"] = tool<ICaloFutureDataProvider>( "CaloFutureDataProvider" , "FutureEcalDataProvider" ); + if((m_detMask&2)!=0)m_provider["Prs"] = tool<ICaloFutureDataProvider>( "CaloFutureDataProvider" , "FuturePrsDataProvider" ); + if((m_detMask&1)!=0)m_provider["Spd"] = tool<ICaloFutureDataProvider>( "CaloFutureDataProvider" , "FutureSpdDataProvider" ); + // + // subscribe to the incidents + IIncidentSvc* inc = incSvc() ; + if ( 0 != inc ) + { + inc -> addListener ( this , IncidentType::BeginEvent ) ; + inc -> addListener ( this , IncidentType::EndEvent ) ; + } + // prepare the known locations: + // + // digits + if ( m_digiUpd ){ + m_digits.clear() ; + for ( std::vector<std::string>::iterator iloc = m_digiLoc.begin() ;m_digiLoc.end() != iloc; ++iloc ){ + m_digits[ *iloc ] = 0 ; + } + } + // clusters + if ( m_clusUpd ){ + m_clusters.clear() ; + for ( std::vector<std::string>::iterator iloc = m_clusLoc.begin() ;m_clusLoc.end() != iloc; ++iloc){ + m_clusters[ *iloc ] = 0 ; + } + } + // hypos + if ( m_hypoUpd ){ + m_hypos.clear() ; + for ( std::vector<std::string>::iterator iloc = m_hypoLoc.begin() ;m_hypoLoc.end() != iloc; ++iloc){ + m_hypos[ *iloc ] = 0 ; + } + } + // + return StatusCode::SUCCESS; +} +// ============================================================================ +StatusCode CaloFutureGetterTool::finalize() +{ + // un-subscribe to the incidents + IIncidentSvc* inc = incSvc() ; + if ( 0 != inc ) { inc -> removeListener ( this ) ; } + // clear data + nullify () ; + m_provider . clear () ; + // finalize the base + return base_class::finalize () ; +} +// ============================================================================ +namespace +{ + // ========================================================================= + template <class TYPE> + void __nullify ( std::map<std::string,TYPE*>& _map ) + { + for ( typename std::map<std::string,TYPE*>::iterator ientry = _map.begin() ; + _map.end() != ientry ; ++ientry ) { ientry->second = 0 ; } + } + // ========================================================================== +} +// ============================================================================ +void CaloFutureGetterTool::nullify() +{ + __nullify ( m_digits ) ; + __nullify ( m_clusters ) ; + __nullify ( m_hypos ) ; +} +// ============================================================================ +// getters +// ============================================================================ +LHCb::CaloDigits* CaloFutureGetterTool::digits ( const std::string& loc ) +{ + std::map<std::string,LHCb::CaloDigits*>::iterator it = m_digits.find( loc ); + // + if ( m_digits.end () == it ){ + Error ( "Illegal Attempt to retrive digits from '" + loc + "'" ).ignore() ; + return 0 ; + } + // + if ( 0 != it->second ) { return it -> second ; } + // + it -> second = getIfExists<LHCb::CaloDigits>( loc ); + if ( NULL != it->second ){ + if(counterStat->isQuiet())counter ("#Digits @ " + loc ) += it->second->size() ; + return it->second ; + } + // + Error ("No Digits at " + loc ).ignore() ; + return 0 ; +} +// ============================================================================ +LHCb::CaloClusters* CaloFutureGetterTool::clusters ( const std::string& loc ) +{ + std::map<std::string,LHCb::CaloClusters*>::iterator it = m_clusters.find( loc ); + // + if ( m_clusters.end () == it ) + { + Error ( "Illegal attempt to retrive clusters from '" + loc + "'" ).ignore() ; + return 0 ; + } + // + if ( 0 != it->second ) { return it->second ; } + // + it -> second = getIfExists<LHCb::CaloClusters>( loc ); + if ( NULL != it->second ) + { + if(counterStat->isQuiet())counter ("#Clusters @ " + loc ) += it->second->size() ; + return it->second ; + } + // + Error ("No Clusters at " + loc ).ignore() ; + return 0 ; +} +// ============================================================================ +LHCb::CaloHypos* CaloFutureGetterTool::hypos ( const std::string& loc ) +{ + std::map<std::string,LHCb::CaloHypos*>::iterator it = m_hypos.find( loc ); + // + if ( m_hypos.end () == it ) + { + Error ( "Illegal attempt to retrive hypos from '" + loc + "'" ).ignore() ; + return 0 ; + } + // + if ( 0 != it->second ) { return it->second ; } + // + it -> second = getIfExists<LHCb::CaloHypos>( loc ); + if ( NULL != it->second ) + { + if(counterStat->isQuiet())counter ("#Hypos @ " + loc ) += it->second->size() ; + return it->second ; + } + // + Error ("No Hypos at " + loc ).ignore() ; + return 0 ; +} +// ============================================================================ +void CaloFutureGetterTool::update() +{ + // digits + if ( m_digiUpd ) + { + for(std::vector<std::string>::iterator iloc = m_digiLoc.begin();m_digiLoc.end() != iloc; ++iloc){ + if ( exist<LHCb::CaloDigits>(*iloc) && 0 == m_digits[*iloc] ){ + LHCb::CaloDigits* digits = get<LHCb::CaloDigits>( *iloc ); + m_digits[ *iloc ] = digits ; + if(counterStat->isQuiet())counter ("#Digits @ " + (*iloc) ) += digits->size() ; + } + } + } + // clusters + if( m_clusUpd ) { + for(const auto& iloc : m_clusLoc) { + LHCb::CaloClusters* clusters = getIfExists<LHCb::CaloClusters>( iloc ); + if ( clusters ) { + m_clusters[ iloc ] = clusters ; + if(counterStat->isQuiet())counter ("#Clusters @ " + iloc ) += clusters->size() ; + } + } + } + // hypos + if( m_hypoUpd ) { + for(const auto& iloc : m_hypoLoc) { + LHCb::CaloHypos* hypos = getIfExists<LHCb::CaloHypos>( iloc ); + if ( hypos ) { + m_hypos[ iloc ] = hypos ; + if(counterStat->isQuiet())counter ("#Hypos @ " + iloc ) += hypos->size() ; + } + } + } + // provider + // if( m_provUpd) + // { + // for(std::map<std::string,ICaloFutureDataProvider*>::iterator ip = m_provider.begin();m_provider.end()!=ip;++ip) + // { + // const std::string& det = ip->first; + // ICaloFutureDataProvider* provider = ip->second; + // m_prov[det] = provider->getBanks(); + // } + // } + +} diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureGetterTool.h b/CaloFuture/CaloFutureTools/src/CaloFutureGetterTool.h new file mode 100644 index 0000000000000000000000000000000000000000..d2cc900c1cfce2bf494c653732bdb75c7405cfc0 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFutureGetterTool.h @@ -0,0 +1,153 @@ +// ============================================================================ +#ifndef CALOFUTUREGETTERTOOL_H +#define CALOFUTUREGETTERTOOL_H 1 +// ============================================================================ +// Include files +// ============================================================================ +// STD & STL +// ============================================================================ +#include <algorithm> +// ============================================================================ +// GaudiKernel +// ============================================================================ +#include "GaudiKernel/IIncidentListener.h" +// ============================================================================ +// GaudiAlg +// ============================================================================ +#include "GaudiAlg/GaudiTool.h" +// ============================================================================ +// Event +// ============================================================================ +#include "Event/CaloDigit.h" +#include "Event/CaloCluster.h" +#include "Event/CaloHypo.h" +// ============================================================================ +// Calo +// ============================================================================ +#include "CaloFutureDAQ/ICaloFutureDataProvider.h" +#include "CaloFutureInterfaces/ICaloFutureGetterTool.h" // Interface +#include "CaloFutureInterfaces/IFutureCounterLevel.h" +// ============================================================================ +/** @class CaloFutureGetterTool CaloFutureGetterTool.h + * + * + * @author Olivier Deschamps + * @date 2009-04-17 + */ +class CaloFutureGetterTool : public extends<GaudiTool , ICaloFutureGetterTool , IIncidentListener > +{ +public: + /// Standard constructor + CaloFutureGetterTool( const std::string& type, + const std::string& name, + const IInterface* parent); + + // ========================================================================== + StatusCode initialize() override; + StatusCode finalize() override; + // ========================================================================== + + // update + void update() override; + int detectorsMask() override {return m_detMask;} + + + + // setters + void addToDigits ( const std::string&loc,bool clear ) override + { + if ( clear ) + { + m_digiLoc.clear () ; + m_digits.clear () ; + } + // + if ( m_digiLoc.end() == std::find ( m_digiLoc.begin() , + m_digiLoc.end () , loc ) ) + { m_digiLoc.value().push_back( loc ) ; } + // + if ( m_digits.end() == m_digits.find( loc ) ) + { m_digits[loc] = 0 ; } + // + } + void addToClusters(const std::string& loc,bool clear ) override + { + if ( clear ) + { + m_clusLoc.clear () ; + m_clusters.clear () ; + } + // + if ( m_clusLoc.end() == std::find ( m_clusLoc.begin () , + m_clusLoc.end () , loc ) ) + { m_clusLoc.value().push_back( loc ) ; } + // + if ( m_clusters.end() == m_clusters.find( loc ) ) + { m_clusters[loc] = 0 ; } + // + } + void addToHypos (const std::string& loc,bool clear ) override + { + if ( clear ) + { + m_hypoLoc.clear () ; + m_hypos.clear () ; + } + // + if ( m_hypoLoc.end() == std::find ( m_hypoLoc.begin () , + m_hypoLoc.end () , loc ) ) + { m_hypoLoc.value().push_back( loc ) ; } + // + if ( m_hypos.end() == m_hypos.find( loc ) ) + { m_hypos[loc] = 0 ; } + // + } + + //getters + LHCb::CaloDigits* digits ( const std::string& loc ) override; + LHCb::CaloClusters* clusters ( const std::string& loc ) override; + LHCb::CaloHypos* hypos ( const std::string& loc ) override; + + bool hasData(const std::string& det) override + { + std::map<std::string,bool>::iterator it = m_prov.find(det); + return (it == m_prov.end()) ? false : (*it).second; + } + ICaloFutureDataProvider* provider( const std::string& det) override + { + std::map<std::string,ICaloFutureDataProvider*>::iterator it = m_provider.find(det); + return (it == m_provider.end()) ? NULL : (*it).second; + } + +public: + // ========================================================================= + /// Inform that a new incident has occurred + void handle(const Incident& /* inc */ ) override { nullify() ; } + // ========================================================================= +protected: + // ========================================================================= + /// nullify the pointers + void nullify() ; + // ========================================================================= +private: + IFutureCounterLevel* counterStat = nullptr; + // ========================================================================= + std::map<std::string,LHCb::CaloDigits*> m_digits; + std::map<std::string,LHCb::CaloClusters*> m_clusters; + std::map<std::string,LHCb::CaloHypos*> m_hypos; + std::map<std::string,ICaloFutureDataProvider*> m_provider; + std::map<std::string,bool> m_prov; + Gaudi::Property<bool> m_digiUpd {this, "GetDigits", true}; + Gaudi::Property<bool> m_clusUpd {this, "GetClusters", false}; + Gaudi::Property<bool> m_hypoUpd {this, "GetHypos", false}; + // bool m_provUpd; + Gaudi::Property<std::vector<std::string>> m_digiLoc {this, "DigitLocations"}; + Gaudi::Property<std::vector<std::string>> m_clusLoc {this, "ClusterLocations"}; + Gaudi::Property<std::vector<std::string>> m_hypoLoc {this, "HypoLocations"}; + Gaudi::Property<int> m_detMask {this, "DetectorMask", 0xF}; +}; +// ============================================================================ +// The END +// ============================================================================ +#endif // CALOFUTUREGETTERTOOL_H +// ============================================================================ diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureHypo2CaloFuture.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureHypo2CaloFuture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fc305456944e67bd49408d52b4c51807b73db463 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFutureHypo2CaloFuture.cpp @@ -0,0 +1,192 @@ +// Include files + +// from Gaudi +#include "GaudiKernel/SystemOfUnits.h" +// from LHCb +#include "GaudiKernel/Vector3DTypes.h" +#include "GaudiKernel/Plane3DTypes.h" +#include "LHCbMath/LineTypes.h" +#include "LHCbMath/GeomFun.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +// local +#include "CaloFutureHypo2CaloFuture.h" + + +//----------------------------------------------------------------------------- +// Implementation file for class : CaloFutureHypo2CaloFuture +// +// 2008-09-11 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( CaloFutureHypo2CaloFuture ) + + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +CaloFutureHypo2CaloFuture::CaloFutureHypo2CaloFuture( const std::string& type, + const std::string& name, + const IInterface* parent ) + : CaloFuture2CaloFuture ( type, name , parent ) +{ + declareInterface<ICaloFutureHypo2CaloFuture>(this); +} + +//============================================================================= +StatusCode CaloFutureHypo2CaloFuture::initialize(){ + StatusCode sc = CaloFuture2CaloFuture::initialize(); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Initialize CaloFutureHypo2CaloFuture tool " << endmsg; + m_lineID = LHCb::CaloCellID(); // initialize + m_point = Gaudi::XYZPoint(); + return sc; +} + + +//============================================================================= +const std::vector<LHCb::CaloCellID>& CaloFutureHypo2CaloFuture::cellIDs(const LHCb::CaloHypo &fromHypo, const std::string &toCaloFuture){ + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Matching CaloHypo to " << toCaloFuture << " hypo energy = " << fromHypo.e() << endmsg; + + // get the cluster + const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( &fromHypo ); + + if(cluster == 0){ + Error("No valid cluster!").ignore() ; + return m_cells; + } + + LHCb::CaloCellID seedID = cluster->seed(); + std::string fromCaloFuture = CaloCellCode::CaloNameFromNum( seedID.calo() ); + if( toCaloFuture != m_toCaloFuture || fromCaloFuture != m_fromCaloFuture)setCalos(fromCaloFuture,toCaloFuture); + if( !m_ok )return m_cells; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Cluster seed " << seedID << " " << m_fromDet->cellCenter( seedID ) << endmsg; + + if(m_whole){ + return CaloFuture2CaloFuture::cellIDs( *cluster, toCaloFuture); + } + + m_point = Gaudi::XYZPoint(); + m_lineID = LHCb::CaloCellID(); + if(m_line && fromHypo.position() != NULL){ + const Gaudi::XYZPoint ref( fromHypo.position()->x(), fromHypo.position()->y(),fromHypo.position()->z() ); + const Gaudi::XYZVector vec = (ref-Gaudi::XYZPoint(0,0,0)); + const Gaudi::Plane3D plane = m_toPlane; + Gaudi::Math::XYZLine line(ref, vec); + double mu; + Gaudi::Math::intersection<Gaudi::Math::XYZLine,Gaudi::Plane3D>(line,plane,m_point,mu); + m_lineID = m_toDet->Cell( m_point ); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "Matching cell " << m_lineID << endmsg; + } + return cellIDs( *cluster, toCaloFuture); +} + + + +const std::vector<LHCb::CaloCellID>& CaloFutureHypo2CaloFuture::cellIDs(const LHCb::CaloCluster &fromCluster, const std::string &toCaloFuture){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " toCaloFuture " << toCaloFuture << endmsg; + reset(); + LHCb::CaloCellID seedID = fromCluster.seed(); + std::string fromCaloFuture = CaloCellCode::CaloNameFromNum( seedID.calo() ); + if( toCaloFuture != m_toCaloFuture || fromCaloFuture != m_fromCaloFuture)setCalos(fromCaloFuture,toCaloFuture); + if( !m_ok)return m_cells; + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "----- cluster energy " << fromCluster.e()<< " " << seedID << endmsg; + m_neighbour.setDet ( m_fromDet ); + + // get data + m_digs = m_getter->digits( m_toLoc ); + + //matching cluster + const LHCb::CaloCluster::Entries& entries = fromCluster.entries(); + for(LHCb::CaloCluster::Entries::const_iterator ent = entries.begin(); ent != entries.end(); ++ent){ + LHCb::CaloClusterEntry entry = *ent; + LHCb::CaloCellID cellID = entry.digit()->cellID(); + if( !(m_seed && (LHCb::CaloDigitStatus::SeedCell & entry.status()) != 0 ) && + !(m_seed && m_neighb && m_neighbour(seedID , cellID) != 0. ) && + !( (m_status & entry.status()) != 0 ) && + !(m_whole) )continue; + SmartRef<LHCb::CaloDigit> digit = (*ent).digit(); + CaloFuture2CaloFuture::cellIDs( digit->cellID() , toCaloFuture, false ); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << toCaloFuture << ": digit is selected in front of the cluster : " + << cellID << "/" << seedID << " " << m_digits.size() << endmsg; + } + // photon line + if(m_line ){ + if( m_lineID == LHCb::CaloCellID() ){ + const Gaudi::XYZPoint ref( fromCluster.position().x(), fromCluster.position().y(),fromCluster.position().z() ); + const Gaudi::XYZVector vec = (ref-Gaudi::XYZPoint(0,0,0)); + const Gaudi::Plane3D plane = m_toPlane; + Gaudi::Math::XYZLine line(ref, vec); + double mu; + Gaudi::Math::intersection<Gaudi::Math::XYZLine,Gaudi::Plane3D>(line,plane,m_point,mu); + m_lineID = m_toDet->Cell( m_point ); + } + if( !(m_lineID == LHCb::CaloCellID()) ){ + addCell( m_lineID , toCaloFuture ); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << toCaloFuture << " : digit is selected in the photon line : " + << m_lineID << "/" << seedID << " " << m_digits.size() << endmsg; + if(m_neighb){ + const std::vector<LHCb::CaloCellID>& neighbors = m_toDet->neighborCells( m_lineID ); + for( std::vector<LHCb::CaloCellID>::const_iterator n = neighbors.begin();n!=neighbors.end();n++){ + double halfCell = m_toDet->cellSize( *n )*0.5; + const Gaudi::XYZPoint cellCenter = m_toDet -> cellCenter ( *n ) ; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << *n + << " Point : (" << m_point.X() << "," << m_point.Y() + << " Cell : ( " << cellCenter.X()<< "," << cellCenter.Y() + << " size/2 : " << halfCell << " Tolerance : " << m_x << "/" << m_y << endmsg; + if( fabs(m_point.X() - cellCenter.X()) < (halfCell+m_x) && + fabs(m_point.Y() - cellCenter.Y()) < (halfCell+m_y) ){ + addCell( *n , toCaloFuture ); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << toCaloFuture << " : digit is selected in the photon line neighborhood : " + << *n << "/" << seedID << " " << m_digits.size() << endmsg; + } + } + } + } + } + + m_lineID = LHCb::CaloCellID();//reset + return m_cells; +} + + + +const std::vector<LHCb::CaloDigit*>& CaloFutureHypo2CaloFuture::digits(const LHCb::CaloHypo &fromHypo, const std::string &toCaloFuture){ + cellIDs( fromHypo, toCaloFuture); + return m_digits; +} + +double CaloFutureHypo2CaloFuture::energy(const LHCb::CaloHypo &fromHypo, const std::string &toCaloFuture){ + cellIDs(fromHypo, toCaloFuture); + return m_energy; +} +const std::vector<LHCb::CaloDigit*>& CaloFutureHypo2CaloFuture::digits(const LHCb::CaloCluster &fromCluster, const std::string &toCaloFuture){ + cellIDs( fromCluster, toCaloFuture); + return m_digits; +} + +double CaloFutureHypo2CaloFuture::energy(const LHCb::CaloCluster &fromCluster, const std::string &toCaloFuture){ + cellIDs(fromCluster, toCaloFuture); + return m_energy; +} + +int CaloFutureHypo2CaloFuture::multiplicity(const LHCb::CaloCluster &fromCluster, const std::string &toCaloFuture){ + cellIDs(fromCluster, toCaloFuture); + return m_count; +} +int CaloFutureHypo2CaloFuture::multiplicity(const LHCb::CaloHypo &fromHypo, const std::string &toCaloFuture){ + cellIDs(fromHypo, toCaloFuture); + return m_count; +} + diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureHypo2CaloFuture.h b/CaloFuture/CaloFutureTools/src/CaloFutureHypo2CaloFuture.h new file mode 100644 index 0000000000000000000000000000000000000000..2ca57130df7ed1855b8a0a8a1cc26284d428b45d --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFutureHypo2CaloFuture.h @@ -0,0 +1,70 @@ +// $Id: CaloFutureHypo2CaloFuture.h,v 1.4 2010-03-08 01:58:39 odescham Exp $ +#ifndef CALOFUTUREHYPO2CALOFUTURE_H +#define CALOFUTUREHYPO2CALOFUTURE_H 1 + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiTool.h" +#include "CaloFutureInterfaces/ICaloFutureHypo2CaloFuture.h" // Interface +#include "CaloFuture2CaloFuture.h" +#include "CaloFutureUtils/CellNeighbour.h" + +#ifdef __INTEL_COMPILER // Disable ICC remark from ROOT + #pragma warning(disable:654) // overloaded virtual function is only partially overridden +#endif + +/** @class CaloFutureHypo2CaloFuture CaloFutureHypo2CaloFuture.h + * + * + * @author Olivier Deschamps + * @date 2008-09-11 + */ +class CaloFutureHypo2CaloFuture : public CaloFuture2CaloFuture, virtual public ICaloFutureHypo2CaloFuture { +public: + /// Standard constructor + CaloFutureHypo2CaloFuture( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + // cellIDs + using CaloFuture2CaloFuture::cellIDs; + const std::vector<LHCb::CaloCellID>& cellIDs(const LHCb::CaloHypo &fromHypo, const std::string &toCaloFuture) override; + const std::vector<LHCb::CaloCellID>& cellIDs(const LHCb::CaloCluster &fromCluster, const std::string &toCaloFuture) override; + const std::vector<LHCb::CaloCellID>& cellIDs() override {return m_cells;}; + // digits + using CaloFuture2CaloFuture::digits; + const std::vector<LHCb::CaloDigit*>& digits(const LHCb::CaloCluster &fromCluster, const std::string &toCaloFuture) override; + const std::vector<LHCb::CaloDigit*>& digits(const LHCb::CaloHypo &fromHypo, const std::string &toCaloFuture) override; + const std::vector<LHCb::CaloDigit*>& digits() override {return m_digits;}; + // energy + using CaloFuture2CaloFuture::energy; + double energy(const LHCb::CaloCluster &fromCluster, const std::string &toCaloFuture) override; + double energy(const LHCb::CaloHypo &fromHypo, const std::string &toCaloFuture) override; + double energy() override {return m_energy;}; + // multiplicity + using CaloFuture2CaloFuture::multiplicity; + int multiplicity(const LHCb::CaloCluster &fromCluster, const std::string &toCaloFuture) override; + int multiplicity(const LHCb::CaloHypo &fromHypo, const std::string &toCaloFuture) override; + int multiplicity() override {return m_count;}; + void setCalos(const std::string &from, const std::string &to) override {CaloFuture2CaloFuture::setCalos(from,to); }; + + // external setting + StatusCode _setProperty(const std::string& p,const std::string& v) override {return setProperty(p,v);}; + + +protected: + +private: + Gaudi::Property<bool> m_seed {this, "Seed", true}; + Gaudi::Property<bool> m_neighb {this, "AddNeighbors", true}; + Gaudi::Property<bool> m_line {this, "PhotonLine", true}; + Gaudi::Property<bool> m_whole {this, "WholeCluster", false}; + Gaudi::Property<int> m_status {this, "StatusMask", 0x0}; + Gaudi::Property<float> m_x {this, "xTolerance", 5.*Gaudi::Units::mm}; + Gaudi::Property<float> m_y {this, "yTolerance", 5.*Gaudi::Units::mm}; + CellNeighbour m_neighbour; + LHCb::CaloCellID m_lineID ; + Gaudi::XYZPoint m_point; +}; +#endif // CALOFUTUREHYPO2CALOFUTURE_H diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d51285ccf02b1322714d8e6bcc9f88e13703b75 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.cpp @@ -0,0 +1,485 @@ +// Include files + +// local +#include "CaloFutureHypoEstimator.h" +#include "Event/ProtoParticle.h" +#include "GaudiKernel/IRegistry.h" +#include "Event/Track.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : CaloFutureHypoEstimator +// +// 2010-08-18 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( CaloFutureHypoEstimator ) + + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +CaloFutureHypoEstimator::CaloFutureHypoEstimator( const std::string& type, + const std::string& name, + const IInterface* parent ) + : GaudiTool ( type, name , parent ) +{ + declareInterface<ICaloFutureHypoEstimator>(this); + + m_cmLoc= LHCb::CaloFutureAlgUtils::CaloFutureIdLocation("ClusterMatch", context()); + m_emLoc= LHCb::CaloFutureAlgUtils::CaloFutureIdLocation("ElectronMatch", context()); + m_bmLoc= LHCb::CaloFutureAlgUtils::CaloFutureIdLocation("BremMatch", context()); + using namespace LHCb::CaloFutureIdLocation; + m_pidLoc["Photon"] = LHCb::CaloFutureAlgUtils::PathFromContext( context() , PhotonID ); + m_pidLoc["Pi0Merged"] = LHCb::CaloFutureAlgUtils::PathFromContext( context() , MergedID ); + m_pidLoc["PhotonFromMergedPi0"] = LHCb::CaloFutureAlgUtils::PathFromContext( context() , PhotonFromMergedID ); +} + +StatusCode CaloFutureHypoEstimator::finalize(){ + IIncidentSvc* inc = incSvc() ; + if ( 0 != inc ) { inc -> removeListener ( this ) ; } + return GaudiTool::finalize(); +} + +StatusCode CaloFutureHypoEstimator::initialize() { + StatusCode sc = GaudiTool::initialize(); // must be executed first + IIncidentSvc* inc = incSvc() ; + if ( 0 != inc )inc -> addListener ( this , IncidentType::BeginEvent ) ; + counterStat = tool<IFutureCounterLevel>("FutureCounterLevel"); + m_toCaloFuture = tool<ICaloFutureHypo2CaloFuture> ("CaloFutureHypo2CaloFuture", "CaloFutureHypo2CaloFuture", this); + m_tables = tool<ICaloFutureRelationsGetter>("CaloFutureRelationsGetter","CaloFutureRelationsGetter",this); + std::string seed = m_seed ? "true" : "false"; + std::string line = m_extrapol ? "true" : "false"; + std::string neig = m_neig ? "true" : "false"; + hypo2CaloFuture()->_setProperty("Seed", seed).ignore(); + hypo2CaloFuture()->_setProperty("PhotonLine", line).ignore(); + hypo2CaloFuture()->_setProperty("AddNeighbors", neig).ignore(); + + m_electron = tool<ICaloFutureElectron>("CaloFutureElectron","CaloFutureElectron",this); + m_GammaPi0 = tool<IFutureGammaPi0SeparationTool>("FutureGammaPi0SeparationTool" , "FutureGammaPi0SeparationTool", this); + m_GammaPi0XGB = tool<IFutureGammaPi0SeparationTool>("FutureGammaPi0XGBoostTool" , "FutureGammaPi0XGBoostTool"); + m_neutralID = tool<IFutureNeutralIDTool>("FutureNeutralIDTool" , "FutureNeutralIDTool", this); + + m_ecal = getDet<DeCalorimeter>( DeCalorimeterLocation::Ecal ); + + clean(); + m_status = true; + return sc; +} + +//============================================================================= + + +// ------------ +double CaloFutureHypoEstimator::data(const LHCb::CaloCluster* cluster,CaloFutureDataType::DataType type, double def ){ + double val = def; + if ( cluster != m_cluster || NULL == cluster){ + clean(); + m_status = estimator(cluster); + if( !m_status ){ + if(counterStat->isQuiet())counter("Cluster estimation failed") += 1; + clean(); + } + } + caloDataType::iterator it = m_data.find( type ); + if( it != m_data.end() )val = m_data[type]; + if( val == CaloFutureDataType::Default)return def; + return val; + +} + +// ------------ +double CaloFutureHypoEstimator::data(const LHCb::CaloHypo* hypo,CaloFutureDataType::DataType type, double def){ + double val = def; + if ( hypo != m_hypo || NULL == hypo ){ + clean(); + m_status = estimator(hypo); + if( !m_status){ + if(counterStat->isQuiet())counter("Hypo estimation failed") += 1; + clean(); + } + } + caloDataType::iterator it = m_data.find( type ); + if( it != m_data.end() )val = m_data[type]; + if( val == CaloFutureDataType::Default)return def; + return val; +} + + +// ------------ FROM HYPO +bool CaloFutureHypoEstimator::estimator(const LHCb::CaloHypo* hypo){ + using namespace CaloFutureDataType; + if( NULL == hypo)return false; + m_hypo = (LHCb::CaloHypo*) hypo; + + LHCb::CaloMomentum mom(hypo); + m_data[HypoE] = mom.e(); + m_data[HypoEt] = mom.pt(); + m_data[HypoM] = mom.mass(); // for mergedPi0 hypothesis only (->for all clusters - toDo in CaloFutureMergedPi0Alg) + m_data[ToPrsE] = m_toCaloFuture->energy(*hypo, "Prs"); + m_data[ToPrsM] = m_toCaloFuture->multiplicity(*hypo, "Prs"); + m_data[ToSpdM] = m_toCaloFuture->multiplicity(*hypo, "Spd"); + // using extra-digits + const LHCb::CaloHypo::Digits& digits = hypo->digits(); + LHCb::CaloDataFunctor::IsFromCalo isSpd { DeCalorimeterLocation::Spd }; + LHCb::CaloDataFunctor::IsFromCalo isPrs { DeCalorimeterLocation::Prs }; + m_data[HypoSpdM]= std::count_if ( digits.begin(),digits.end(),isSpd ); + m_data[HypoPrsM]= std::count_if ( digits.begin(),digits.end(),isPrs ); + double sumPrs = 0; + for( LHCb::CaloHypo::Digits::const_iterator id = digits.begin(); id != digits.end() ; ++id){ + if ( 0 != *id && isPrs ( *id ) ) { sumPrs += (*id)->e(); } + } + m_data[HypoPrsE]=sumPrs; + + + + + // electron matching + if( !m_skipC ){ + double chi2e = CaloFutureDataType::Default; + double trajL = CaloFutureDataType::Default; + const LHCb::Track* etrack = NULL; + //LHCb::CaloFuture2Track::ITrHypoTable2D* etable = getIfExists<LHCb::CaloFuture2Track::ITrHypoTable2D> (m_emLoc); + LHCb::CaloFuture2Track::ITrHypoTable2D* etable = m_tables->getTrHypoTable2D( m_emLoc); + if ( NULL != etable ) { + const LHCb::CaloFuture2Track::ITrHypoTable2D::InverseType::Range range = etable -> inverse()->relations(hypo); + if ( !range.empty() ){ + chi2e= range.front().weight(); + etrack = range.front(); + if( NULL != etrack ){ + LHCb::ProtoParticle* dummy = new LHCb::ProtoParticle(); + dummy->setTrack( etrack ); + dummy->addToCalo ( hypo ); + //CaloFutureElectron->caloTrajectory must be after addToCalo + if ( m_electron->set(dummy) ) + trajL =m_electron->caloTrajectoryL(CaloPlane::ShowerMax,"hypo"); + delete dummy; + } + } + }else + if(counterStat->isQuiet())counter( "Missing "+ m_emLoc) += 1; + + m_track[CaloFutureMatchType::ElectronMatch]=etrack; + m_data[ElectronMatch] = chi2e; + m_data[TrajectoryL]= trajL; + + // brem matching + double chi2b = CaloFutureDataType::Default; + const LHCb::Track* btrack = NULL; + //LHCb::CaloFuture2Track::ITrHypoTable2D* btable = getIfExists<LHCb::CaloFuture2Track::ITrHypoTable2D> (m_bmLoc); + LHCb::CaloFuture2Track::ITrHypoTable2D* btable = m_tables->getTrHypoTable2D(m_bmLoc); + if ( NULL != btable ) { + const LHCb::CaloFuture2Track::ITrHypoTable2D::InverseType::Range range = btable -> inverse()->relations(hypo); + if ( !range.empty() ){ + chi2b= range.front().weight(); + btrack = range.front(); + } + }else + if(counterStat->isQuiet())counter( "Missing "+ m_bmLoc) += 1; + + m_track[CaloFutureMatchType::BremMatch]=btrack; + m_data[BremMatch] = chi2b; + } + + // NeutralID (warning : protect against infinite loop from CaloFuturePhotonIDAlg using this tools with DoD active) + if( !m_skipN ){ + for( std::map<std::string,std::string>::iterator l = m_pidLoc.begin(); m_pidLoc.end()!=l; ++l){ + std::string loc = l->second; + std::string hypothesis = l->first; + if ( exist<LHCb::CaloFuture2Track::IHypoEvalTable>( loc ) ) + //m_idTable[hypothesis] = get<LHCb::CaloFuture2Track::IHypoEvalTable> ( loc ) ; + m_idTable[hypothesis] = m_tables->getHypoEvalTable( loc ); + else + if(counterStat->isQuiet())counter( "Missing "+ loc) += 1; + } + std::ostringstream type(""); + type << hypo->hypothesis(); + std::string hypothesis = type.str(); + const LHCb::CaloFuture2Track::IHypoEvalTable* idTable = NULL ; + std::map<std::string, LHCb::CaloFuture2Track::IHypoEvalTable*>::iterator it = m_idTable.find(hypothesis); + if( it != m_idTable.end())idTable = it->second; + if( NULL != idTable ){ + const LHCb::CaloFuture2Track::IHypoEvalTable::Range range = idTable->relations( hypo ) ; + if ( !range.empty() )m_data[NeutralID]= range.front().to(); + } + } + // link 2 cluster : + const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( hypo ); + m_clusters[CaloFutureClusterType::SplitOrMain]=cluster; + m_clusters[CaloFutureClusterType::Main]= LHCb::CaloFutureAlgUtils::ClusterFromHypo( hypo , false); // get the main cluster + + //Prs info + if( cluster == NULL ){ + Warning("Cluster point to NULL",StatusCode::SUCCESS).ignore(); + }else{ + // Ecal seed + LHCb::CaloCluster::Entries::const_iterator iseed = + LHCb::ClusterFunctors::locateDigit(cluster->entries().begin(),cluster->entries().end(), LHCb::CaloDigitStatus::SeedCell); + if (iseed != cluster->entries().end()) { + const LHCb::CaloDigit* seed = iseed->digit(); + const LHCb::CaloCellID idseed=seed->cellID(); + double sum9 = 0.; + double sum1 = 0.; + // PrsE4 + std::vector<double> Prse4s; + Prse4s.reserve(4); + Prse4s.push_back(0.); + Prse4s.push_back(0.); + Prse4s.push_back(0.); + Prse4s.push_back(0.); + std::vector<double> Prse9; + Prse9.reserve(9); + Prse9.push_back(0.); + Prse9.push_back(0.); + Prse9.push_back(0.); + Prse9.push_back(0.); + Prse9.push_back(0.); + Prse9.push_back(0.); + Prse9.push_back(0.); + Prse9.push_back(0.); + Prse9.push_back(0.); + + for( LHCb::CaloHypo::Digits::const_iterator id = digits.begin(); id != digits.end() ; ++id){ + + if ( 0 == *id || !isPrs ( *id ) )continue; + LHCb::CaloCellID id2 = (*id)->cellID(); + if( abs((int)(*id)->cellID().row() - (int)idseed.row())<2 && abs( (int)(*id)->cellID().col() - (int)idseed.col())<2 ){ + // Build sum1 and sum9 + // + sum9 += (*id)->e(); + if( (*id)->cellID().row() == idseed.row() && (*id)->cellID().col() == idseed.col() ) sum1=(*id)->e(); + // Prs4 + // + if(id2.col() <= idseed.col() && id2.row() >= idseed.row() )Prse4s[0] += (*id)->e(); + if(id2.col() >= idseed.col() && id2.row() >= idseed.row() )Prse4s[1] += (*id)->e(); + if(id2.col() >= idseed.col() && id2.row() <= idseed.row() )Prse4s[2] += (*id)->e(); + if(id2.col() <= idseed.col() && id2.row() <= idseed.row() )Prse4s[3] += (*id)->e(); + // Select the 3X3 cluster + // + int dcol = (int)id2.col()-(int)idseed.col()+1; + int drow = (int)id2.row()-(int)idseed.row()+1; + int indexPrs = drow*3+dcol; + Prse9[indexPrs] += (*id)->e(); + } + } + // Build E19 and E49 + // + double Prse4max = 0; + for( std::vector<double>::iterator ih = Prse4s.begin();Prse4s.end() != ih;++ih){ + if( *ih >= Prse4max ) Prse4max=*ih; + } + m_data[PrsE4Max] = Prse4max; + double sum9Inv = 0.; + if( sum9 > 0. ) { + sum9Inv = 1./sum9; + m_data[PrsE49] = Prse4max * sum9Inv; + m_data[PrsE19] = sum1 * sum9Inv; + } + else + { + m_data[PrsE49] = 0.; + m_data[PrsE19] = 0.; + } + m_data[PrsE1]= Prse9[0]; + m_data[PrsE2]= Prse9[1]; + m_data[PrsE3]= Prse9[2]; + m_data[PrsE4]= Prse9[3]; + m_data[PrsE5]= Prse9[4]; + m_data[PrsE6]= Prse9[5]; + m_data[PrsE7]= Prse9[6]; + m_data[PrsE8]= Prse9[7]; + m_data[PrsE9]= Prse9[8]; + } + } + + // gamma/pi0 separation + m_data[CaloFutureDataType::DataType::isPhoton]= m_GammaPi0->isPhoton( hypo ); + m_data[CaloFutureDataType::DataType::isPhotonXGB] = m_GammaPi0XGB->isPhoton( hypo ); + + + // 1- Ecal variables : + std::map<std::string,double> isPhotonData = m_GammaPi0->inputDataMap(); + for( std::map<std::string,double>::iterator idata = isPhotonData.begin() ; isPhotonData.end() != idata; ++idata){ + std::string name = "isPhoton_"+idata->first; + double val = idata->second; + bool ok =false; + for( int i = 0; i < Last ; ++i){ + if( Name[i] == name){ + m_data[(DataType)i]=val; + ok=true; + break; + } + } + if( !ok )Warning("DataType '" + name + "' is undefined",StatusCode::SUCCESS).ignore(); + } + // 2- Prs variables : + std::map<std::string,double> isPhotonPrsData = m_GammaPi0->inputPrsDataMap(); + for( std::map<std::string,double>::iterator idata = isPhotonPrsData.begin() ; isPhotonPrsData.end() != idata; ++idata){ + std::string name = "isPhoton_"+idata->first; + double val = idata->second; + bool ok =false; + for( int i = 0; i < Last ; ++i){ + if( Name[i] == name){ + m_data[(DataType)i]=val; + ok=true; + break; + } + } + if( !ok )Warning("DataType '" + name + "' is undefined",StatusCode::SUCCESS).ignore(); + } + // + bool ok = ( 0 != cluster ) ? estimator( cluster , hypo) : false; + + + // Estimator MUST be at the end (after all inputs are loaded) + m_data[isNotH]= m_neutralID->isNotH( hypo,this ); + m_data[isNotE]= m_neutralID->isNotE( hypo,this ); + + + return ok; +} + +// ------------ FROM CLUSTER +bool CaloFutureHypoEstimator::estimator(const LHCb::CaloCluster* cluster, const LHCb::CaloHypo* fromHypo){ + using namespace CaloFutureDataType; + if( NULL ==cluster)return false; + m_cluster = (LHCb::CaloCluster*) cluster; + + + if (cluster->entries().empty()) { + if(counterStat->isQuiet())counter("Empty cluster") += 1; + return false; + } + LHCb::CaloCluster::Entries::const_iterator iseed = + LHCb::ClusterFunctors::locateDigit(cluster->entries().begin(),cluster->entries().end(), LHCb::CaloDigitStatus::SeedCell); + + if (iseed != cluster->entries().end()) { + + const LHCb::CaloDigit* seed = iseed->digit(); + if (0 == seed) { + if(counterStat->isQuiet())counter("Seed points to NULL") += 1; + return false; + } + + double eEcal = cluster->e(); + m_data[ClusterE] = eEcal; + // + double cSize = m_ecal->cellSize(cluster->seed()); + Gaudi::XYZPoint cCenter=m_ecal->cellCenter( cluster->seed() ); + double asX = ( cluster->position().x() - cCenter.x() )/cSize; + double asY = ( cluster->position().y() - cCenter.y() )/cSize; + m_data[ClusterAsX]=asX; + m_data[ClusterAsY]=asY; + + m_data[E1] = seed->e(); + caloDataType::iterator it = m_data.find( HypoE ); + double eHypo = ( it != m_data.end() ) ? m_data[HypoE] : 0; + m_data[E1Hypo] = eHypo > 0. ? (seed->e()) / eHypo : -1.; + LHCb::CaloCellID sid = seed->cellID(); + m_data[CellID] = (double) sid.all(); + m_data[Spread] = cluster->position().spread()(1,1)+cluster->position().spread()(0,0); + // E4 + std::vector<double> e4s; + e4s.reserve(4); + e4s.push_back(0); + e4s.push_back(0); + e4s.push_back(0); + e4s.push_back(0); + double e9 = 0.; + double ee9 =0.; // full cluster energy without fraction applied + double e2 = 0.; + bool hasShared=false; + int code = 0.; + int mult = 0.; + int nsat = 0; // number of saturated cells + for( LHCb::CaloCluster::Entries::const_iterator ie = cluster->entries().begin() ; cluster->entries().end() != ie ; ++ie){ + const LHCb::CaloDigit* dig = (*ie).digit(); + if( NULL == dig)continue; + double ecel = dig->e()*ie->fraction(); + if( ( ( ie->status() & LHCb::CaloDigitStatus::UseForEnergy) != 0 || + ( ie->status() & LHCb::CaloDigitStatus::UseForCovariance) != 0) && m_ecal->isSaturated(dig->e(),dig->cellID()))nsat++; + LHCb::CaloCellID id = dig->cellID(); + if( id.area() != sid.area() || abs((int)id.col() - (int)sid.col()) > 1 || abs((int)id.row() - (int)sid.row()) > 1)continue; + if(id.col() <= sid.col() && id.row() >= sid.row() )e4s[0] += ecel; + if(id.col() >= sid.col() && id.row() >= sid.row() )e4s[1] += ecel; + if(id.col() >= sid.col() && id.row() <= sid.row() )e4s[2] += ecel; + if(id.col() <= sid.col() && id.row() <= sid.row() )e4s[3] += ecel; + e9 += ecel; + // new info + ee9+= dig->e(); + mult++; + if( ie->status() & LHCb::CaloDigitStatus::SharedCell)hasShared=true; + if( !(id == sid) && ecel > e2){ + e2 = ecel; + int dc = (int)id.col() - (int)sid.col()+1; + int dr = (int)id.row() - (int)sid.row()+1; + code = 3*dr + dc; + } + } + m_data[Saturation]=(double) nsat; + double e4max = 0; + for( std::vector<double>::iterator ih = e4s.begin();e4s.end() != ih;++ih){ + if( *ih >= e4max)e4max=*ih; + } + + code = mult * 10 + code; + if( hasShared )code *= -1; + m_data[ClusterCode] = (double) code; + m_data[ClusterFrac] = (e9 > 0.) ? e9/ee9 : -1; + + m_data[E4] = e4max; + m_data[E9] = e9; + m_data[E49] = (e9>0.) ? e4max /e9 : 0.; + m_data[E19] = (e9>0.) ? seed->e() / e9 : -1.; + + + + if( NULL == fromHypo){ + // hypo and cluster parameters may produce small difference according to m_toCaloFuture setting (due to extrapolation) + m_data[ToPrsE] = m_toCaloFuture->energy(*cluster, "Prs"); + m_data[ToPrsM] = m_toCaloFuture->multiplicity(*cluster, "Prs"); + m_data[ToSpdM] = m_toCaloFuture->multiplicity(*cluster, "Spd"); + } + double eHcal = m_toCaloFuture->energy(*cluster, "Hcal"); + m_data[ToHcalE]= eHcal; + m_data[Hcal2Ecal] = (eEcal > 0) ? eHcal/eEcal : 0.; + } + + // cluster-match chi2 + if( !m_skipCl ){ + const LHCb::CaloCluster* clus = cluster ; + // special trick for split cluster : use full cluster matching + if (NULL != fromHypo && fromHypo->hypothesis() == LHCb::CaloHypo::Hypothesis::PhotonFromMergedPi0) + clus = LHCb::CaloFutureAlgUtils::ClusterFromHypo( fromHypo , false); // get the main cluster + double chi2 = CaloFutureDataType::Default; const LHCb::Track* ctrack = NULL; + //LHCb::CaloFuture2Track::IClusTrTable* ctable = getIfExists<LHCb::CaloFuture2Track::IClusTrTable> (m_cmLoc); + LHCb::CaloFuture2Track::IClusTrTable* ctable = m_tables->getClusTrTable( m_cmLoc ); + if ( NULL != ctable ) { + const LHCb::CaloFuture2Track::IClusTrTable::Range range = ctable -> relations(clus); + + + if ( !range.empty() ){ + chi2= range.front().weight(); + ctrack = range.front(); + } + }else + if(counterStat->isQuiet())counter( "Missing "+ m_cmLoc) += 1; + + m_track[CaloFutureMatchType::ClusterMatch]=ctrack; + m_data[ClusterMatch] = chi2; + } + return true; +} + + + +void CaloFutureHypoEstimator::clean(){ + m_data.clear(); + m_cluster=NULL; + m_hypo=NULL; + m_track.clear(); + return; +} + + + diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h new file mode 100644 index 0000000000000000000000000000000000000000..f414b34d8f59eb222d28aa1d4642acca86230707 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFutureHypoEstimator.h @@ -0,0 +1,103 @@ +#ifndef CALOFUTUREHYPOESTIMATOR_H +#define CALOFUTUREHYPOESTIMATOR_H 1 + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiTool.h" +#include "GaudiKernel/IIncidentListener.h" +#include "GaudiKernel/IIncidentSvc.h" +#include "GaudiKernel/Incident.h" +#include "Event/CaloDataFunctor.h" +#include "CaloFutureUtils/ClusterFunctors.h" +#include "CaloFutureUtils/CaloMomentum.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "CaloFutureUtils/CaloFuture2Track.h" +#include "Relations/Relation2D.h" +#include "Relations/IRelationWeighted.h" +#include "Relations/IRelationWeighted2D.h" +#include "Event/Track.h" +#include "CaloFutureInterfaces/ICaloFutureHypoEstimator.h" // Interface +#include "CaloFutureInterfaces/IFutureCounterLevel.h" +#include "CaloFutureInterfaces/IFutureGammaPi0SeparationTool.h" +#include "CaloFutureInterfaces/IFutureNeutralIDTool.h" +#include "CaloFutureUtils/ICaloFutureElectron.h" +#include "CaloFutureInterfaces/ICaloFutureRelationsGetter.h" +#include "CaloDet/DeCalorimeter.h" + +/** @class CaloFutureHypoEstimator CaloFutureHypoEstimator.h + * + * + * @author Olivier Deschamps + * @date 2010-08-18 + */ + +class CaloFutureHypoEstimator : public GaudiTool, virtual public ICaloFutureHypoEstimator, virtual public IIncidentListener { +public: + /// Standard constructor + CaloFutureHypoEstimator( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + StatusCode finalize() override; + + double data(const LHCb::CaloCluster* cluster ,CaloFutureDataType::DataType type, double def = CaloFutureDataType::Default) override; + double data(const LHCb::CaloHypo* hypo ,CaloFutureDataType::DataType type, double def = CaloFutureDataType::Default) override; + + void handle(const Incident& ) override { + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "IIncident Svc reset" << endmsg; + clean(); + } + ICaloFutureHypo2CaloFuture* hypo2CaloFuture() override {return m_toCaloFuture;}; + const LHCb::Track* toTrack(CaloFutureMatchType::MatchType match) override { + caloMatchType::iterator it = m_track.find( match ); + if( it == m_track.end() )return NULL; + return (*it).second; + } + const LHCb::CaloCluster* toCluster(CaloFutureClusterType::ClusterType clus=CaloFutureClusterType::SplitOrMain) override { + caloClusterType::iterator it = m_clusters.find( clus ); + if( it == m_clusters.end() )return NULL; + return (*it).second; + } + + + StatusCode _setProperty(const std::string& p,const std::string& v) override {return setProperty(p,v);}; + bool status() override {return m_status;} + + +private: + IFutureCounterLevel* counterStat = nullptr; + bool estimator(const LHCb::CaloCluster* cluster,const LHCb::CaloHypo* fromHypo=NULL); + bool estimator(const LHCb::CaloHypo* hypo); + void clean(); + + Gaudi::Property<bool> m_extrapol {this, "Extrapolation", true}; + Gaudi::Property<bool> m_seed {this, "AddSeed", false}; + Gaudi::Property<bool> m_neig {this, "AddNeighbors", false}; + + ICaloFutureHypo2CaloFuture* m_toCaloFuture = nullptr; + caloDataType m_data; + caloMatchType m_track; + caloClusterType m_clusters; + LHCb::CaloHypo* m_hypo = nullptr; + LHCb::CaloCluster* m_cluster = nullptr; + + Gaudi::Property<std::map<std::string,std::string>> m_pidLoc {this, "NeutralIDLocations"}; + Gaudi::Property<std::string> m_cmLoc {this, "ClusterMatchLocation"}; + Gaudi::Property<std::string> m_emLoc {this, "ElectronMatchLocation"}; + Gaudi::Property<std::string> m_bmLoc {this, "BremMatchLocation"}; + Gaudi::Property<bool> m_skipC {this, "SkipChargedID", false}; + Gaudi::Property<bool> m_skipN {this, "SkipNeutralID", false}; + Gaudi::Property<bool> m_skipCl {this, "SkipClusterMatch", false}; + + std::map<std::string,LHCb::CaloFuture2Track::IHypoEvalTable*> m_idTable; + bool m_status = true; + ICaloFutureElectron * m_electron = nullptr; + IFutureGammaPi0SeparationTool* m_GammaPi0 = nullptr; + IFutureGammaPi0SeparationTool* m_GammaPi0XGB = nullptr; + IFutureNeutralIDTool* m_neutralID = nullptr; + ICaloFutureRelationsGetter* m_tables = nullptr; + DeCalorimeter* m_ecal = nullptr; +}; +#endif // CALOFUTUREHYPOESTIMATOR_H diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureRelationsGetter.cpp b/CaloFuture/CaloFutureTools/src/CaloFutureRelationsGetter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..779b36c3c4a8819c4e29ecefcab3bcd1c08c4bdc --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFutureRelationsGetter.cpp @@ -0,0 +1,80 @@ +// Include files + +// from Gaudi +#include "GaudiKernel/IIncidentSvc.h" +#include "GaudiKernel/Incident.h" + + +// local +#include "CaloFutureRelationsGetter.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : CaloFutureRelationsGetter +// +// 2013-10-04 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( CaloFutureRelationsGetter ) + + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +CaloFutureRelationsGetter::CaloFutureRelationsGetter( const std::string& type, + const std::string& name, + const IInterface* parent ) +: GaudiTool ( type, name , parent ) +{ + declareInterface<ICaloFutureRelationsGetter>(this); + declareInterface<IIncidentListener>(this); +} + +//============================================================================= + + +StatusCode CaloFutureRelationsGetter::initialize(){ + StatusCode sc = GaudiTool::initialize(); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) )debug() << "Initialize CaloFutureRelationsGetter tool " << endmsg; + // subscribe to the incidents + IIncidentSvc* inc = incSvc() ; + if ( inc )inc -> addListener ( this , IncidentType::BeginEvent ) ; + return sc; +} + +StatusCode CaloFutureRelationsGetter::finalize(){ + IIncidentSvc* inc = incSvc() ; + if ( inc ) { inc -> removeListener ( this ) ; } + return GaudiTool::finalize(); +} + +LHCb::CaloFuture2Track::ITrHypoTable2D* CaloFutureRelationsGetter::getTrHypoTable2D(std::string location){ + auto it = m_hypoTr.find(location); + if( it == m_hypoTr.end() ) m_hypoTr[location] = getIfExists<LHCb::CaloFuture2Track::IHypoTrTable2D> (location); + + auto links = m_hypoTr[location]->relations(); + m_trHypo.i_clear().ignore(); + for(const auto& l : links) m_trHypo.i_push( l.to(), l.from(), l.weight() ); + m_trHypo.i_sort(); + return &m_trHypo; +} + +LHCb::CaloFuture2Track::IHypoEvalTable* CaloFutureRelationsGetter::getHypoEvalTable(std::string location){ + auto it = m_hypoEval.find(location); + if( it == m_hypoEval.end()) m_hypoEval[location] = getIfExists<LHCb::CaloFuture2Track::IHypoEvalTable> (location); + return m_hypoEval[location]; +} + +LHCb::CaloFuture2Track::IClusTrTable* CaloFutureRelationsGetter::getClusTrTable(std::string location){ + auto it = m_clusTr.find(location); + if( it == m_clusTr.end()) m_clusTr[location] = getIfExists<LHCb::CaloFuture2Track::IClusTrTable> (location); + return m_clusTr[location]; +} + +void CaloFutureRelationsGetter::clean(){ + m_clusTr.clear(); + m_hypoEval.clear(); + m_hypoTr.clear(); + +} + diff --git a/CaloFuture/CaloFutureTools/src/CaloFutureRelationsGetter.h b/CaloFuture/CaloFutureTools/src/CaloFutureRelationsGetter.h new file mode 100644 index 0000000000000000000000000000000000000000..c00507e6750599c9b2a735ba3187bb25cead363b --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CaloFutureRelationsGetter.h @@ -0,0 +1,56 @@ +#ifndef CALOFUTURERELATIONSGETTER_H +#define CALOFUTURERELATIONSGETTER_H 1 + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiTool.h" +#include "CaloFutureInterfaces/ICaloFutureRelationsGetter.h" // Interface +#include "GaudiKernel/IIncidentListener.h" +#include "GaudiKernel/IIncidentSvc.h" +#include "GaudiKernel/Incident.h" +// from LHCb +#include "Relations/Relation2D.h" +#include "Relations/IRelationWeighted.h" +#include "Relations/IRelationWeighted2D.h" +#include "Event/Track.h" +#include "Event/CaloHypo.h" +#include "CaloFutureUtils/CaloFuture2Track.h" + + +#include "Relations/RelationWeighted2D.h" + + +/** @class CaloFutureRelationsGetter CaloFutureRelationsGetter.h + * + * + * @author Olivier Deschamps + * @date 2013-10-04 + */ +class CaloFutureRelationsGetter : public GaudiTool, virtual public ICaloFutureRelationsGetter, virtual public IIncidentListener { +public: + /// Standard constructor + CaloFutureRelationsGetter( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + StatusCode finalize() override; + void handle(const Incident& ) override { + if( UNLIKELY( msgLevel(MSG::DEBUG) ) )debug() << "IIncident Svc reset" << endmsg; + clean(); + } + + // getters + LHCb::CaloFuture2Track::ITrHypoTable2D* getTrHypoTable2D(std::string location) override; + LHCb::CaloFuture2Track::IHypoEvalTable* getHypoEvalTable(std::string location) override; + LHCb::CaloFuture2Track::IClusTrTable* getClusTrTable (std::string location) override; + +private: + + LHCb::RelationWeighted2D<LHCb::Track, LHCb::CaloHypo, float> m_trHypo; + std::map<std::string,LHCb::CaloFuture2Track::IHypoTrTable2D*> m_hypoTr; + std::map<std::string,LHCb::CaloFuture2Track::IHypoEvalTable*> m_hypoEval; + std::map<std::string,LHCb::CaloFuture2Track::IClusTrTable*> m_clusTr; + void clean(); +}; +#endif // CALOFUTURERELATIONSGETTER_H diff --git a/CaloFuture/CaloFutureTools/src/CheckCaloFutureHypoRef.cpp b/CaloFuture/CaloFutureTools/src/CheckCaloFutureHypoRef.cpp new file mode 100644 index 0000000000000000000000000000000000000000..188d7db7b655e684fa4baa9e675a7fa6cdbdb124 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CheckCaloFutureHypoRef.cpp @@ -0,0 +1,58 @@ +// Include files + +// from LHCb +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "Event/CaloHypo.h" +// local +#include "CheckCaloFutureHypoRef.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : CheckCaloFutureHypoRef +// +// 2012-05-14 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( CheckCaloFutureHypoRef ) + + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +CheckCaloFutureHypoRef::CheckCaloFutureHypoRef( const std::string& name, + ISvcLocator* pSvcLocator) +: GaudiAlgorithm ( name , pSvcLocator ) +{ + using namespace LHCb::CaloFutureAlgUtils; + m_inputs.value() = { + CaloFutureHypoLocation("Photons" , context()), + CaloFutureHypoLocation("Electrons" , context()), + CaloFutureHypoLocation("MergedPi0s", context()) + }; +} + +//============================================================================= +// Main execution +//============================================================================= +StatusCode CheckCaloFutureHypoRef::execute() { + + if ( msgLevel(MSG::DEBUG) ) debug() << "==> Execute" << endmsg; + + for (const auto& loc : m_inputs ) { + const LHCb::CaloHypos* hypos = getIfExists<LHCb::CaloHypos> (loc); + if ( !hypos ) continue; + if(counterStat->isQuiet()) counter("#Hypos in " + loc) += hypos->size(); + int bLink=0; + for (const auto& h : *hypos ) { + for( const auto& cluster : h->clusters() ) { + if( !cluster ) bLink++; + else if(counterStat->isVerbose())counter("Cluster energy " +loc)+=cluster->e(); + } + } + if(counterStat->isQuiet())counter("Broken SmarRef " +loc) += bLink; + if(bLink != 0)Warning("CaloHypo -> CaloCluster* SmartReference is broken for "+loc,StatusCode::SUCCESS).ignore(); + } + return StatusCode::SUCCESS; +} + +//============================================================================= diff --git a/CaloFuture/CaloFutureTools/src/CheckCaloFutureHypoRef.h b/CaloFuture/CaloFutureTools/src/CheckCaloFutureHypoRef.h new file mode 100644 index 0000000000000000000000000000000000000000..542aa748f74d3a3c86b48427def80294628cd309 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/CheckCaloFutureHypoRef.h @@ -0,0 +1,26 @@ +#ifndef CHECKCALOFUTUREHYPOREF_H +#define CHECKCALOFUTUREHYPOREF_H 1 + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiAlgorithm.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" + +/** @class CheckCaloFutureHypoRef CheckCaloFutureHypoRef.h + * + * + * @author Olivier Deschamps + * @date 2012-05-14 + */ +class CheckCaloFutureHypoRef : public GaudiAlgorithm { +public: + /// Standard constructor + CheckCaloFutureHypoRef( const std::string& name, ISvcLocator* pSvcLocator ); + + StatusCode execute() override; ///< Algorithm execution + +private: + Gaudi::Property<std::vector<std::string>> m_inputs {this, "CaloHypos"}; + IFutureCounterLevel* counterStat = nullptr; +}; +#endif // CHECKCALOFUTUREHYPOREF_H diff --git a/CaloFuture/CaloFutureTools/src/FutureCounterLevel.cpp b/CaloFuture/CaloFutureTools/src/FutureCounterLevel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a6fb46037eac18ce72a38b1bcae20e2f990d89b --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/FutureCounterLevel.cpp @@ -0,0 +1,32 @@ +#include "FutureCounterLevel.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : FutureCounterLevel +// +// 2016-08-13 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( FutureCounterLevel ) + + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +FutureCounterLevel::FutureCounterLevel( const std::string& type, + const std::string& name, + const IInterface* parent ) +: base_class ( type, name , parent ) +{ + declareInterface<IFutureCounterLevel>(this); + + // sync m_isQuiet and m_isVerbose with m_clevel + m_clevel.declareUpdateHandler( + [=](const Property&) { + this->m_isQuiet = ( this->m_clevel > 0 ); + this->m_isVerbose = ( this->m_clevel > 1 ); + }); + m_clevel.useUpdateHandler(); +} + +//============================================================================= diff --git a/CaloFuture/CaloFutureTools/src/FutureCounterLevel.h b/CaloFuture/CaloFutureTools/src/FutureCounterLevel.h new file mode 100644 index 0000000000000000000000000000000000000000..ab49b410559e358c97c4da7cd6b0f5d0fc6f5e30 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/FutureCounterLevel.h @@ -0,0 +1,34 @@ +#ifndef FUTURECOUNTERLEVEL_H +#define FUTURECOUNTERLEVEL_H 1 + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiTool.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" // Interface + + +/** @class FutureCounterLevel FutureCounterLevel.h + * + * + * @author Olivier Deschamps + * @date 2016-08-13 + */ +class FutureCounterLevel final : public extends<GaudiTool, IFutureCounterLevel> { +public: + /// Standard constructor + FutureCounterLevel( const std::string& type, + const std::string& name, + const IInterface* parent); + + bool isQuiet() const override {return m_isQuiet; }; + bool isVerbose() const override {return m_isVerbose; }; + bool isLevel(int l) const override {return m_clevel >= l; }; + int level() const override {return m_clevel ; }; + +private: + + Gaudi::Property<int> m_clevel {this, "SetLevel", 1, "quiet mode is the default"}; + bool m_isQuiet = true; + bool m_isVerbose = false; +}; +#endif // FUTURECOUNTERLEVEL_H diff --git a/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.cpp b/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..282fcd021cd34bf6af5583ee61811f848c53e4b7 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.cpp @@ -0,0 +1,381 @@ +// Include files + +#include <cmath> + +#include "CaloFutureUtils/CaloMomentum.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +// from Event +#include "Event/RecHeader.h" +#include "Event/CaloHypo.h" +#include "Event/CaloCluster.h" + +// local +#include "FutureGammaPi0SeparationTool.h" + +using namespace LHCb; +using namespace Gaudi::Units; +//----------------------------------------------------------------------------- +// Implementation file for class : FutureGammaPi0SeparationTool +// +// 2010-03-24 : Miriam Calvo Gomez +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( FutureGammaPi0SeparationTool ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +FutureGammaPi0SeparationTool::FutureGammaPi0SeparationTool( const std::string& type, + const std::string& name, + const IInterface* parent ) +: base_class ( type, name , parent ) +{ + declareInterface<IFutureGammaPi0SeparationTool>(this); +} + +//============================================================================= +// Initialization +//============================================================================= +StatusCode FutureGammaPi0SeparationTool::initialize() { + + StatusCode sc = base_class::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; // error printed already by GaudiAlgorithm + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "==> Initialize" << endmsg; + + /// Retrieve geometry of detector + m_ecal = getDetIfExists<DeCalorimeter>( DeCalorimeterLocation::Ecal ); + + // TMVA discriminant + static const std::vector<std::string> inputVars = { + "fr2", "fr2r4", "abs(asym)", + "kappa", "Eseed/Ecl", "(E2+Eseed)/Ecl", + "eSumPS>0?eMaxPS/eSumPS:0", + "eSumPS>0?e2ndPS/eSumPS:0", + "r2PS", "abs(asymPS)", + "multiPS", "multiPS15", + "multiPS30", "multiPS45" } ; + + m_reader0 = std::make_unique<ReadMLPOuter>(inputVars); + m_reader1 = std::make_unique<ReadMLPMiddle>(inputVars); + m_reader2 = std::make_unique<ReadMLPInner>(inputVars); + + return StatusCode::SUCCESS; +} + +//============================================================================= +// Finalize +//============================================================================= +StatusCode FutureGammaPi0SeparationTool::finalize() { + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "==> Finalize" << endmsg; + + m_reader0.reset(); + m_reader1.reset(); + m_reader2.reset(); + + return base_class::finalize(); // must be executed last +} + +//============================================================================= +// Main execution +//============================================================================= + + +double FutureGammaPi0SeparationTool::isPhoton(const LHCb::CaloHypo* hypo){ + + // clear all data + m_data.clear(); + m_prsdata.clear(); + + if ( !m_ecal ) return m_def; + if ( LHCb::CaloMomentum(hypo).pt() < m_minPt) return m_def; + + double fr2 = 0; + double fasym = 0; + double fkappa = 0; + double fr2r4 = 0; + double Eseed = 0; + double E2 = 0; + double Ecl = 0; + int area =0; + + double r2PS = 0.; + double r2r4PS = 0; + double asymPS = 0; + double kappaPS = 0; + double ePrs = 0; + double eMaxPS = 0; + double e2ndPS = 0; + double ecornerPS = 0; + double eSumPS = 0.; + int multiPS = 0; + int multiPS15 = 0; + int multiPS30 = 0; + int multiPS45 = 0; + + // evaluate the NN inputs + bool ecalV = ClusterVariables(hypo, fr2, fasym, fkappa, fr2r4, Ecl, Eseed, E2, area); + bool prsV = PrsVariables(hypo, r2PS, asymPS, kappaPS, r2r4PS, eSumPS, ePrs, eMaxPS, e2ndPS, ecornerPS, + multiPS, multiPS15, multiPS30, multiPS45); + if( !ecalV || !prsV )return m_def; + // return NN output + return photonDiscriminant(area, fr2, fr2r4, fasym, fkappa, Eseed, E2, + r2PS, asymPS, eMaxPS, e2ndPS, multiPS, multiPS15, multiPS30, multiPS45); +} + + +bool FutureGammaPi0SeparationTool::ClusterVariables(const LHCb::CaloHypo* hypo, + double& fr2, double& fasym, double& fkappa, double& fr2r4, double& etot, + double& Eseed, double& E2, int& area) { + m_data.clear(); + + if ( !hypo ) return false; + const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( hypo ); // OD 2014/05 - change to Split Or Main cluster + if ( !cluster ) return false; + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) )debug()<<"Inside ClusterVariables ------"<<endmsg; + + const auto cxx = cluster->position().spread()(0,0); + const auto cyy = cluster->position().spread()(1,1); + const auto cxy = cluster->position().spread()(0,1); + fr2 = cxx + cyy ; + fasym = ( cxx > 0 && cyy > 0 ? cxy / std::sqrt( cxx*cyy ) : 0 ); + const auto arg = ( fr2 > 0. ? 1. - 4.* ( cxx*cyy - cxy*cxy ) / ( fr2 * fr2 ) : 0. ); + fkappa = std::sqrt( arg > 0. ? arg : 0. ); + + const auto xmean = cluster->position().x(); + const auto ymean = cluster->position().y(); + + // OD : WARNING cluster->e() is cluster-shape dependent (3x3 / 2x2 ...) RE-EVALUATE E3x3 instead for back. compatibility + // etot = cluster->e(); //same as position.e + etot = 0.; + + const Gaudi::XYZPoint position ( xmean, ymean, cluster->position().z() ); + + double r4 = 0.; + area = -1; + int ncells = 0; + double secondE = 0.; + + const auto & entries = cluster->entries() ; + for ( auto entry = entries.begin() ; entries.end() != entry ; ++entry ){ + const LHCb::CaloDigit* digit = entry->digit() ; + if ( !digit ) { continue ; } + const auto fraction = entry->fraction(); + const auto energy = digit->e() * fraction ; + + if( abs( (int)digit->cellID().col() - (int)cluster->seed().col() ) <= 1 && + abs( (int)digit->cellID().row() - (int)cluster->seed().row() ) <= 1 && + digit->cellID().area() == cluster->seed().area() ) { etot += energy; } + + if ( entry->status() & LHCb::CaloDigitStatus::SeedCell ){ + area = digit->cellID().area(); + Eseed = energy; + }else{ + if(energy>secondE) { + secondE = energy; + } + } + + const auto& pos = m_ecal->cellCenter( digit->cellID() ); + const auto x = pos.x() ; + const auto y = pos.y() ; + + if ( energy <= 0 ) { continue ; } + const double weight = energy > 0.0 ? energy : 0.0 ; + + auto rr = std::pow(x-xmean,2) + std::pow(y-ymean,2); + if ( entries.size() <= 1 || rr < 1.e-10 ) { rr=0; } // to avoid huge unphysical value due to machine precision + r4 += weight * rr*rr; + + ncells++; + }//loop cluster cells + + if( etot > 0. ){ + r4 /= etot; + fr2r4 = (r4 !=0) ? (r4 - fr2*fr2)/r4 : 0.; + E2 = (secondE+Eseed)/etot; + Eseed = Eseed/etot; + }else{ + // should never happen + r4 = 0; + fr2r4 = 0.; + E2 = 0.; + Eseed = 0.; + } + + m_data["Ecl"] = etot; + m_data["Fr2"] = fr2; + m_data["Fr2r4"] = fr2r4; + m_data["Asym"] = fasym; + m_data["Kappa"] = fkappa; + m_data["Eseed"] = Eseed; + m_data["E2"] = E2; + return true; +} + +bool FutureGammaPi0SeparationTool::PrsVariables(const LHCb::CaloHypo* hypo, + double& r2PS, double& asymPS, double& kappaPS, double& r2r4PS, + double& eSumPS, double& ePrs, double& eMaxPS, double& e2ndPS, double& ecornerPS, + int& multiPS, int& multiPS15, int& multiPS30, int& multiPS45) { + + // clear prs data + m_prsdata.clear(); + e2ndPS = 0.; + ePrs = 0.; + eSumPS=0.; + eMaxPS=0.; + multiPS=0; + multiPS15=0; + multiPS30=0; + multiPS45=0; + asymPS=0.; + r2PS=0.; + kappaPS=0.; + r2r4PS=0.; + ecornerPS=0.; + + if( !hypo)return false; + const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( hypo ); + if( !cluster)return false; + + + LHCb::CaloCellID cellPrs = cluster->seed(); // use cluster seed projection (mostly the same as line projection + faster access) + cellPrs.setCalo(1); + + if( LHCb::CaloCellID() == cellPrs )return true; // no valid Prs info + + // compute energy sum / max / ... + const LHCb::CaloHypo::Digits& digits = hypo->digits(); + double xPs = 0.; + double yPs = 0.; + for( auto d = digits.begin() ; digits.end() != d ; ++d ){ + const LHCb::CaloDigit* digit = *d; + if ( !digit ) continue ; + if ((int) digit->cellID().calo() != 1 )continue; // select Prs digits + int dcol = int(digit->cellID().col()) - int(cellPrs.col()); + int drow = int(digit->cellID().row()) - int(cellPrs.row()); + if( abs(dcol) > 1 || abs(drow)> 1 )continue; // keep only neighbors + + double e = digit->e(); + + // energy + eSumPS += e ; + if( cellPrs == digit->cellID() )ePrs = e ; + + // barycenter + xPs += double(dcol) * digit->e(); + yPs += double(drow) * digit->e(); + + // multiplicities + if( e > eMaxPS ) eMaxPS = e; + if( e > 0.0 ) multiPS++; + if( e > 15.0 ) multiPS15++; + if( e > 30.0 ) multiPS30++; + if( e > 45.0 ) multiPS45++; + } + + + if( eSumPS <= 0. )return true; + xPs = xPs/eSumPS; + yPs = yPs/eSumPS; + + // spread and related shape variables + double cxxPS = 0.; + double cyyPS = 0.; + double cxyPS = 0.; + double r4PS = 0.; + double c1 = 0.0; + double c2 = 0.0; + double c3 = 0.0; + double c4 = 0.0; + for (const auto& digit : digits) { + if ( !digit ) continue ; + if ((int) digit->cellID().calo() != 1 )continue; // select Prs digits + int dcol = ( int(digit->cellID().col()) - int(cellPrs.col()) ); + int drow = ( int(digit->cellID().row()) - int(cellPrs.row()) ); + if( abs(dcol) > 1 || abs(drow)> 1 )continue; // keep only neighbors + + // 2Nd max + double e = digit->e(); + if( e > e2ndPS && e < eMaxPS )e2ndPS = e; + + // spread + double dxPS = (xPs - double(dcol)); + double dyPS = (yPs - double(drow)); + cxxPS += dxPS * dxPS * e; + cyyPS += dyPS * dyPS * e; + cxyPS += dxPS * dyPS * e; + + // shape variables + r4PS += e * ( dxPS * dxPS + dyPS * dyPS) * ( dxPS * dxPS + dyPS * dyPS); + + // corner energy + if(dcol==-1 && drow== 1 ){ c1 += e;} + if(dcol==-1 && drow== 0 ){ c1 += e; c3 += e;} + if(dcol==-1 && drow==-1 ){ c3 += e;} + if(dcol== 0 && drow== 1 ){ c1 += e; c2 += e;} + if(dcol== 0 && drow==-1 ){ c3 += e; c4 += e;} + if(dcol== 1 && drow== 1 ){ c2 += e;} + if(dcol== 1 && drow== 0 ){ c2 += e; c4 += e;} + if(dcol== 1 && drow==-1 ){ c4 += e;} + } + cxxPS = cxxPS/eSumPS; + cxyPS = cxyPS/eSumPS; + cyyPS = cyyPS/eSumPS; + r2PS = cxxPS + cyyPS; + asymPS = ( cxxPS > 0.0 && cyyPS > 0.0) ? cxyPS / std::sqrt( cxxPS * cyyPS) : 0.; + const auto arg = ( r2PS > 0.0 ? 1.0 - 4.0 * (cxxPS * cyyPS - cxyPS * cxyPS) / ( r2PS * r2PS ) : 0. ); + kappaPS = std::sqrt( arg > 0. ? arg : 0. ); + r4PS = r4PS/eSumPS; + if( r4PS!=0.0) r2r4PS = ( r4PS - r2PS * r2PS) /r4PS; + + ecornerPS = std::max( { c1, c2, c3, c4 } ); + eMaxPS = eMaxPS/eSumPS; + e2ndPS = e2ndPS/eSumPS; + + + // === store the data + m_prsdata["PrsFr2"] = r2PS; + m_prsdata["PrsAsym"] = asymPS; + m_prsdata["PrsM"] = multiPS; + m_prsdata["PrsM15"] = multiPS15; + m_prsdata["PrsM30"] = multiPS30; + m_prsdata["PrsM45"] = multiPS45; + m_prsdata["PrsEmax"] = eMaxPS; + m_prsdata["PrsE2"] = e2ndPS; + return true; +} + + +double FutureGammaPi0SeparationTool::photonDiscriminant(int area, + double r2, double r2r4, double asym, + double kappa, double Eseed, double E2, + double r2PS, double asymPS, double eMaxPS, double e2ndPS, + int multiPS, int multiPS15, int multiPS30, int multiPS45) +{ + std::vector<double> input = { + r2, + r2r4, + std::abs(asym), + kappa, + Eseed, //already divided by Ecl + E2, //means (e2+eseed)/ecl + eMaxPS,//divided by Esum + e2ndPS,//divided by Esum + r2PS, + std::abs(asymPS), + double(multiPS), + double(multiPS15), + double(multiPS30), + double(multiPS45) }; + + double value = ( area == 0 ? m_reader0->GetMvaValue(input) + : area == 1 ? m_reader1->GetMvaValue(input) + : area == 2 ? m_reader2->GetMvaValue(input) + : -1e10 ); + //info() << " INPUT TO GAMMA/PI0 : NN[" << input << "]= " << value << " (area="<<area<<")"<< endmsg; + return value; +} diff --git a/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.h b/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.h new file mode 100644 index 0000000000000000000000000000000000000000..d4e13cbac08e992975ba1ff0da566a9d053419f7 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/FutureGammaPi0SeparationTool.h @@ -0,0 +1,93 @@ +#ifndef FUTUREGAMMAPI0SEPARATIONTOOL_H +#define FUTUREGAMMAPI0SEPARATIONTOOL_H 1 + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiTool.h" +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureInterfaces/IFutureGammaPi0SeparationTool.h" + +// Math +#include "GaudiKernel/Point3DTypes.h" +#include "GaudiKernel/Vector3DTypes.h" +#include "LHCbMath/Line.h" +#include "LHCbMath/GeomFun.h" + +//using namespace LHCb; + +#include "TMV_MLP_inner.C" +#include "TMV_MLP_middle.C" +#include "TMV_MLP_outer.C" + + +/** @class FutureGammaPi0SeparationTool FutureGammaPi0SeparationTool.h + * + * + * @author Miriam Calvo Gomez + * @date 2010-03-29 + */ + +class FutureGammaPi0SeparationTool : public extends<GaudiTool, IFutureGammaPi0SeparationTool>{ +public: + + /// Standard constructor + FutureGammaPi0SeparationTool( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + StatusCode finalize() override; + + //double isPhoton(const LHCb::Particle* gamma); + double isPhoton(const LHCb::CaloHypo* hypo) override; + + bool ClusterVariables(const LHCb::CaloHypo* hypo, + double& fr2, double& fasym, double& fkappa, double& fr2r4, double& etot, + double& Eseed, double& E2, int& area) override; + + bool PrsVariables(const LHCb::CaloHypo* hypo, + double& r2PS, double& asymPS, double& kappaPS, double& r2r4PS, + double& eSumPS, double& ePrs, double& eMaxPS, double& e2ndPS, double& ecornerPS, + int& multiPS, int& multiPS15, int& multiPS30, int& multiPS45) override; + + double inputData(std::string data) override { //@TODO: const-ify + // try ecal data + auto it = m_data.find(data); + if( it != m_data.end() )return it->second; + // else try prs data : + auto itp = m_prsdata.find(data); + if( itp != m_prsdata.end() )return itp->second; + // yapa + return 0.; + } + std::map<std::string,double> inputDataMap() override {return m_data;} + std::map<std::string,double> inputPrsDataMap() override {return m_prsdata;} + double isPhoton(const double* v) override { + return photonDiscriminant(int(v[0]), + v[1],v[2],v[3], + v[4],v[5],v[6], + v[7],v[8],v[9],v[10], + int(v[11]),int(v[12]),int(v[13]),int(v[14])); + } + +private: + + Gaudi::Property<float> m_minPt {this, "MinPt", 2000.}; + + std::unique_ptr<IClassifierReader> m_reader0; + std::unique_ptr<IClassifierReader> m_reader1; + std::unique_ptr<IClassifierReader> m_reader2; + + const DeCalorimeter* m_ecal = nullptr; + + double photonDiscriminant(int area, + double r2, double r2r4, double asym, + double kappa, double Eseed, double E2, + double r2PS, double asymPS, double eMaxPS, double e2ndPS, + int multiPS, int multiPS15, int multiPS30, int multiPS45); + + std::map<std::string,double> m_data; + std::map<std::string,double> m_prsdata; + double m_def = -1.e+06; +}; +#endif // FUTUREGAMMAPI0SEPARATIONTOOL_H diff --git a/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.cpp b/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e94d6fe4521bd8edd2fef2ce35d3036deb019e08 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.cpp @@ -0,0 +1,216 @@ +// Include files + +#include "CaloFutureUtils/CaloMomentum.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +// from Event +#include "Event/RecHeader.h" +#include "Event/CaloHypo.h" +#include "Event/CaloCluster.h" +#include <unordered_map> +#include <iostream> +#include <iomanip> +#include <string> +#include <cstdlib> + +// local +#include "FutureGammaPi0XGBoostTool.h" +#include <fstream> + +using namespace LHCb; +using namespace Gaudi::Units; +//----------------------------------------------------------------------------- +// Implementation file for class : FutureGammaPi0XGBoostTool +// +// 2018-03-24 : author @sayankotor +//----------------------------------------------------------------------------- + +//Declare nessesary help functionality +namespace { + +size_t getClusterType (const CaloCellID& id) { + + const int CaloFutureNCol[4] = {64, 32, 16, 16}; + const int CaloFutureNRow[4] = {52, 20, 12, 12}; + const unsigned Granularity[3] = {1, 2, 3}; + + const unsigned ClusterSize = 5; + int type (id.area()); + int xOffsetOut = std::min (int(id.col() - (32 - CaloFutureNCol[type]*Granularity[type]/2)), // left edge + int(31 + CaloFutureNCol[type]*Granularity[type]/2 - id.col())); // right edge + int yOffsetOut = std::min (int(id.row() - (32 - CaloFutureNRow[type]*Granularity[type]/2)), + int(31 + CaloFutureNRow[type]*Granularity[type]/2 - id.row())); + int innerWidth = CaloFutureNCol[type+1] * (type != 2 ? Granularity[type] : 1); // process inner hole specially + int innerHeight = CaloFutureNRow[type+1] * (type != 2 ? Granularity[type] : 1); // process inner hole specially + + int xOffsetIn = std::min (int(id.col() - (31 - innerWidth/2)), + int(32 + innerWidth/2 - id.col())); + int yOffsetIn = std::min (int(id.row() - (31 - innerHeight/2)), + int(32 + innerHeight/2 - id.row())); + const int margin = (ClusterSize-1)/2; + bool outerBorder = xOffsetOut < margin || yOffsetOut < margin; + bool innerBorder = xOffsetIn > -margin && yOffsetIn > -margin; + if (innerBorder) return type+3; + else if (outerBorder) return type+6; + return type; +} + +} + +// Declaration of the Tool Factory +DECLARE_COMPONENT( FutureGammaPi0XGBoostTool ) + +//============================================================================= +// Initialization +//============================================================================= +StatusCode FutureGammaPi0XGBoostTool::initialize() { + + StatusCode sc = base_class::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; // error printed already by GaudiAlgorithm + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "==> Initialize" << endmsg; + + /// Retrieve geometry of detector + m_ecal = getDet<DeCalorimeter>( DeCalorimeterLocation::Ecal ); + + + const std::string paramEnv = "PARAMFILESROOT"; + std::string paramRoot = std::string(getenv(paramEnv.c_str())); + + m_xgb0 = std::make_unique<FutureXGBClassifierPhPi0>(paramRoot + "/data/GammaPi0XgbTool_simpl0.model"); + m_xgb1 = std::make_unique<FutureXGBClassifierPhPi0>(paramRoot + "/data/GammaPi0XgbTool_simpl1.model"); + m_xgb2 = std::make_unique<FutureXGBClassifierPhPi0>(paramRoot + "/data/GammaPi0XgbTool_simpl2.model"); + m_xgb03_b = std::make_unique<FutureXGBClassifierPhPi0>(paramRoot + "/data/GammaPi0XgbTool_bound03.model"); + m_xgb06_b = std::make_unique<FutureXGBClassifierPhPi0>(paramRoot + "/data/GammaPi0XgbTool_bound06.model"); + m_xgb14_b = std::make_unique<FutureXGBClassifierPhPi0>(paramRoot + "/data/GammaPi0XgbTool_bound14.model"); + m_xgb17_b = std::make_unique<FutureXGBClassifierPhPi0>(paramRoot + "/data/GammaPi0XgbTool_bound17.model"); + m_xgb25_b = std::make_unique<FutureXGBClassifierPhPi0>(paramRoot + "/data/GammaPi0XgbTool_bound25.model"); + m_xgb28_b = std::make_unique<FutureXGBClassifierPhPi0>(paramRoot + "/data/GammaPi0XgbTool_bound28.model"); + + return StatusCode::SUCCESS; +} + +//============================================================================= +// Finalize +//============================================================================= +StatusCode FutureGammaPi0XGBoostTool::finalize() { + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "==> Finalize" << endmsg; + + m_xgb0.reset(); + m_xgb1.reset(); + m_xgb2.reset(); + m_xgb03_b.reset(); + m_xgb06_b.reset(); + m_xgb14_b.reset(); + m_xgb17_b.reset(); + m_xgb25_b.reset(); + m_xgb28_b.reset(); + + return base_class::finalize(); // must be executed last +} + +//============================================================================= +// Main execution +//============================================================================= + + +double FutureGammaPi0XGBoostTool::isPhoton(const LHCb::CaloHypo* hypo){ + + if ( !m_ecal ) return m_def; + if ( LHCb::CaloMomentum(hypo).pt() < m_minPt) return m_def; + const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( hypo ); + if (!cluster) return m_def; + + std::vector<double> rawEnergyVector(25, 0.0); + + int cluster_type = getClusterType(cluster->seed()); + bool rawEnergy = GetRawEnergy(hypo, cluster_type, rawEnergyVector); + + if(!rawEnergy) return m_def; + + double prediction_xgb = XGBDiscriminant(cluster_type, rawEnergyVector); + return prediction_xgb; +} + + +double FutureGammaPi0XGBoostTool::XGBDiscriminant(int cluster_type, std::vector<double>& row_energies) +{ + + double value = -1e10; + switch (cluster_type) { + case 0: value = m_xgb0->getClassifierValues(row_energies); + break; + case 1: value = m_xgb1->getClassifierValues(row_energies); + break; + case 2: value = m_xgb2->getClassifierValues(row_energies); + break; + case 3: value = m_xgb03_b->getClassifierValues(row_energies); + break; + case 4: value = m_xgb14_b->getClassifierValues(row_energies); + break; + case 5: value = m_xgb25_b->getClassifierValues(row_energies); + break; + case 6: value = m_xgb06_b->getClassifierValues(row_energies); + break; + case 7: value = m_xgb17_b->getClassifierValues(row_energies); + break; + case 8: value = m_xgb28_b->getClassifierValues(row_energies); + break; + default: warning() << "FutureGammaPi0XGBoostTool: Unsupperted cluster type" << endmsg; + + } + return value; +} + +bool FutureGammaPi0XGBoostTool::GetRawEnergy(const LHCb::CaloHypo* hypo, int& cluster_type, std::vector<double>& rowEnergy) const{ + if( nullptr == hypo)return false; + + const LHCb::CaloDigits * digits_full = getIfExists<LHCb::CaloDigits>(LHCb::CaloDigitLocation::Ecal); + const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( hypo ); // OD 2014/05 - change to Split Or Main cluster + + if( nullptr == digits_full || nullptr == cluster) return false; + + LHCb::CaloCellID centerID = cluster->seed(); + + std::vector<std::vector<double>> vector_cells (5, std::vector<double>(5, 0.0)); + + std::vector<int> col_numbers = {(int)centerID.col() - 2, (int)centerID.col() - 1, (int)centerID.col(), (int)centerID.col() + 1, (int)centerID.col() + 2}; + std::vector<int> row_numbers = {(int)centerID.row() - 2, (int)centerID.row() - 1, (int)centerID.row(), (int)centerID.row() + 1, (int)centerID.row() + 2}; + + if (cluster_type > 2) + { + for (auto& col_number: col_numbers){ + for (auto& row_number: row_numbers){ + const auto id_ = LHCb::CaloCellID(centerID.calo(), centerID.area(), row_number, col_number); + auto * test = digits_full->object(id_); + if (test) { + vector_cells[col_number - (int)centerID.col() + 2][row_number - (int)centerID.row() + 2] = test->e(); + } else { + continue; + } + } + } + } + + else + { + for (auto& col_number: col_numbers){ + for (auto& row_number: row_numbers){ + const auto id_ = LHCb::CaloCellID(centerID.calo(), centerID.area(), row_number, col_number); + auto * test = digits_full->object(id_); + if (test) { + vector_cells[col_number - (int)centerID.col() + 2][row_number - (int)centerID.row() + 2] = test->e(); + } else { + continue; + } + } + } + } + + for (int i = 0; i < 5; i++){ + for (int j = 0; j < 5; j++){ + rowEnergy[i*5 + j] = vector_cells[i][j]; + } + } + return true; +} diff --git a/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.h b/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.h new file mode 100644 index 0000000000000000000000000000000000000000..4a26ee010687de605c320a0a63fcca0220b737c5 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/FutureGammaPi0XGBoostTool.h @@ -0,0 +1,87 @@ +#ifndef FutureGammaPi0XGBoostTool_H +#define FutureGammaPi0XGBoostTool_H + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiTool.h" +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureInterfaces/IFutureGammaPi0SeparationTool.h" + +// Math +#include "GaudiKernel/Point3DTypes.h" +#include "GaudiKernel/Vector3DTypes.h" +#include "LHCbMath/Line.h" +#include "LHCbMath/GeomFun.h" + +//using xgb in c++ + +#include "FutureXGBClassifierPhPi0.h" + + +/** @class FutureGammaPi0XGBoostTool FutureGammaPi0XGBoostTool.h + * + * + * @author @sayankotor + * @date 2018-03-24 + */ + + +class FutureGammaPi0XGBoostTool : public extends<GaudiTool, IFutureGammaPi0SeparationTool>{ + + +public: + + FutureGammaPi0XGBoostTool( const std::string& type, + const std::string& name, + const IInterface* parent):base_class ( type, name , parent ){}; + StatusCode initialize() override; + StatusCode finalize() override; + + //double isPhoton(const LHCb::Particle* gamma); + double isPhoton(const LHCb::CaloHypo* hypo) override; + + bool GetRawEnergy(const LHCb::CaloHypo* hypo, int& cluster_type, std::vector<double>& rowEnergy) const; + std::vector<std::vector<double>> GetCluster(const LHCb::CaloCellID & centerID, const LHCb::CaloDigits * digits_full) const; + + double inputData(std::string) override { //@TODO: const-ify + /* // try ecal data */ + /* auto it = m_data.find(data); */ + /* if( it != m_data.end() )return it->second; */ + /* // else try prs data : */ + /* auto itp = m_prsdata.find(data); */ + /* if( itp != m_prsdata.end() )return itp->second; */ + /* // yapa */ + return 0.; + } + + std::map<std::string,double> inputDataMap() override {return std::map<std::string,double>();} + std::map<std::string,double> inputPrsDataMap() override {return std::map<std::string,double>();} + bool ClusterVariables(const LHCb::CaloHypo*, double&, double&, double&, double&, double&, + double&, double&, int&) override {return true;} + bool PrsVariables(const LHCb::CaloHypo*, double&, double&, double&, double&, + double&, double&, double&, double&, double&, + int&, int&, int&, int&) override {return true;} + double isPhoton(const double*) override {return 0.0;}; + +private: + + Gaudi::Property<float> m_minPt {this, "MinPt", 2000.}; + + std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb0; + std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb1; + std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb2; + std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb03_b; + std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb14_b; + std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb25_b; + std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb06_b; + std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb17_b; + std::unique_ptr<FutureXGBClassifierPhPi0> m_xgb28_b; + + const DeCalorimeter* m_ecal = nullptr; + + + double XGBDiscriminant(int cluster_type, std::vector<double>& row_energies); + + const double m_def = -1.e+06; +}; +#endif // FutureGammaPi0XGBoostTool_H \ No newline at end of file diff --git a/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.cpp b/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d4fd6c0d7aed95ff5dbac042c6ed4014032ee44c --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.cpp @@ -0,0 +1,275 @@ +// Include files + +// from Gaudi +#include "CaloFutureUtils/CaloMomentum.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +// from Event +#include "Event/RecHeader.h" +#include "Event/CaloHypo.h" +#include "Event/CaloCluster.h" + +// local +#include "FutureNeutralIDTool.h" + + +using namespace LHCb; +using namespace Gaudi::Units; + +//----------------------------------------------------------------------------- +// Implementation file for class : FutureNeutralIDTool +// +// 2013-07-25 : Mostafa HOBALLAH +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( FutureNeutralIDTool ) + + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +FutureNeutralIDTool::FutureNeutralIDTool( const std::string& type, + const std::string& name, + const IInterface* parent ) + : GaudiTool ( type, name , parent ) +{ + declareInterface<IFutureNeutralIDTool>(this); +} + +//============================================================================= +// Initialization +//============================================================================= +StatusCode FutureNeutralIDTool::initialize() { + + StatusCode sc = GaudiTool::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; // error printed already by GaudiAlgorithm + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "==> Initialize" << endmsg; + + + // TMVA discriminant + std::vector<std::string> inputVars; + + inputVars.push_back("TMath::TanH(CaloHypo_ClusterMatch/2000)"); + inputVars.push_back("CaloHypo_ToPrsE"); + inputVars.push_back("CaloHypo_E19"); + inputVars.push_back("CaloHypo_Hcal2Ecal"); + inputVars.push_back("CaloHypo_PrsE19"); + inputVars.push_back("CaloHypo_PrsE49"); + inputVars.push_back("CaloHypo_Spread"); + inputVars.push_back("CaloHypo_PrsE4Max"); + inputVars.push_back("CaloHypo_HypoPrsM"); + inputVars.push_back("CaloHypo_HypoSpdM"); + + std::vector<std::string> inputVars1; + + inputVars1.push_back("CaloHypo_ClusterMatch"); + inputVars1.push_back("CaloHypo_ToPrsE"); + inputVars1.push_back("CaloHypo_E19"); + inputVars1.push_back("CaloHypo_Hcal2Ecal"); + inputVars1.push_back("CaloHypo_PrsE19"); + inputVars1.push_back("CaloHypo_PrsE49"); + inputVars1.push_back("CaloHypo_Spread"); + inputVars1.push_back("CaloHypo_PrsE4Max"); + inputVars1.push_back("CaloHypo_HypoPrsM"); + inputVars1.push_back("CaloHypo_HypoSpdM"); + + + + m_reader1 = std::make_unique<ReadMLPH>(inputVars); + m_reader0 = std::make_unique<ReadMLPE>(inputVars1); + + + return StatusCode::SUCCESS; + +} + +//============================================================================= +// Finalize +//============================================================================= +StatusCode FutureNeutralIDTool::finalize() { + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) debug() << "==> Finalize" << endmsg; + StatusCode sc = GaudiTool::finalize(); // must be executed first + + m_reader0.reset(); + m_reader1.reset(); + + + return sc; +} + +//============================================================================= +// Main execution +//============================================================================= + + +double FutureNeutralIDTool::isNotE(const LHCb::CaloHypo* hypo,ICaloFutureHypoEstimator* estimator){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug()<<"Inside NeutralID ------"<<endmsg; + + if( estimator != NULL)m_estimator=estimator; + + double pt = LHCb::CaloMomentum(hypo).pt(); + + double tmva_outputE = CaloFutureDataType::Default; + + if (pt>m_minPt){ + + double clmatch = 0; + double prse = 0; + double e19 = 0; + double hclecl = 0; + double prse19 = 0; + double prse49 = 0; + double sprd = 0; + double prse4mx = 0; + double prsm = 0; + double spdm = 0; + + + + const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( hypo , false); + if (cluster!=0){ + + Variables(hypo,clmatch,prse, e19, hclecl,prse19,prse49, sprd, prse4mx, prsm, spdm); + + tmva_outputE = photonDiscriminantE(clmatch, prse, e19, hclecl, prse19,prse49, sprd, prse4mx, prsm, spdm); + + }//cluster exists + else{ + tmva_outputE = CaloFutureDataType::Default; + } + } + else{ + tmva_outputE = CaloFutureDataType::Default; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug()<<"Outside range of pt"<<endmsg; + } + + return tmva_outputE; +} + +double FutureNeutralIDTool::isNotH(const LHCb::CaloHypo* hypo,ICaloFutureHypoEstimator* estimator){ + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug()<<"Inside NeutralID ------"<<endmsg; + + if( estimator != NULL)m_estimator=estimator; + + + double pt = LHCb::CaloMomentum(hypo).pt(); + + double tmva_outputH = CaloFutureDataType::Default; + + if (pt>m_minPt){ + + double clmatch = 0; + double prse = 0; + double e19 = 0; + double hclecl = 0; + double prse19 = 0; + double prse49 = 0; + double sprd = 0; + double prse4mx = 0; + double prsm = 0; + double spdm = 0; + + const LHCb::CaloCluster* cluster = LHCb::CaloFutureAlgUtils::ClusterFromHypo( hypo , false); + if (cluster!=0){ + Variables(hypo,clmatch,prse, e19, hclecl,prse19,prse49, sprd, prse4mx, prsm, spdm); + + tmva_outputH = photonDiscriminantH(clmatch, prse, e19, hclecl, prse19,prse49, sprd, prse4mx, prsm, spdm); + + }//cluster exists + else{ + tmva_outputH = CaloFutureDataType::Default; + } + } + else{ + tmva_outputH = CaloFutureDataType::Default; + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug()<<"Outside range of pt"<<endmsg; + } + + return tmva_outputH; +} + + + +double FutureNeutralIDTool::photonDiscriminantE(double clmatch, double prse, double e19, double hclecl, double prse19, + double prse49, double sprd, double prse4mx, double prsm, double spdm) { + + + std::vector<double> input; + + input.push_back(tanh(clmatch/2000)); + input.push_back(prse); + input.push_back(e19); + input.push_back(hclecl); + input.push_back(prse19); + input.push_back(prse49); + input.push_back(sprd); + input.push_back(prse4mx); + input.push_back(prsm); + input.push_back(spdm); + + double valueE = -1e10; + valueE = m_reader0->GetMvaValue(input); + + + return valueE; +} + + + + +double FutureNeutralIDTool::photonDiscriminantH(double clmatch, double prse, double e19, double hclecl, double prse19, + double prse49, double sprd, double prse4mx, double prsm, double spdm) { + + + std::vector<double> input; + + input.push_back(tanh(clmatch/2000)); + input.push_back(prse); + input.push_back(e19); + input.push_back(hclecl); + input.push_back(prse19); + input.push_back(prse49); + input.push_back(sprd); + input.push_back(prse4mx); + input.push_back(prsm); + input.push_back(spdm); + + double valueH = -1e10; + valueH = m_reader1->GetMvaValue(input); + + + return valueH; +} + + + +void FutureNeutralIDTool::Variables(const LHCb::CaloHypo* hypo, double& clmatch, double& prse, + double& e19, double& hclecl, double& prse19,double& prse49, double& sprd, double& prse4mx, + double& prsm, double& spdm) { + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug()<<"Inside Variables ------"<<endmsg; + + using namespace CaloFutureDataType; + + // load the estimator tool only when not passed in argument (to avoid circular initialization with the estimator itself) + if( m_estimator == NULL)m_estimator = tool<ICaloFutureHypoEstimator>("CaloFutureHypoEstimator","CaloFutureHypoEstimatorForNeutralID",this); + + clmatch = m_estimator->data(hypo , ClusterMatch ,0.); + prse = m_estimator->data(hypo , ToPrsE ,0.); + e19 = m_estimator->data(hypo , E19 ,0.); + hclecl = m_estimator->data(hypo , Hcal2Ecal ,0.); + prse19 = m_estimator->data(hypo , PrsE19 ,0.); + prse49 = m_estimator->data(hypo , PrsE49 ,0.); + sprd = m_estimator->data(hypo , Spread ,0.); + prse4mx = m_estimator->data(hypo , PrsE4Max ,0.); + prsm = m_estimator->data(hypo , HypoPrsM ,0.); + spdm = m_estimator->data(hypo , HypoSpdM ,0.); + +} + diff --git a/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.h b/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.h new file mode 100644 index 0000000000000000000000000000000000000000..8a1695b84c868bde3ba56e5eafaa66c2a9cf9d49 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/FutureNeutralIDTool.h @@ -0,0 +1,79 @@ +// $Id: $ +#ifndef FUTURENEUTRALIDTOOL_H +#define FUTURENEUTRALIDTOOL_H 1 + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiTool.h" +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureInterfaces/IFutureNeutralIDTool.h" +#include "CaloFutureInterfaces/ICaloFutureHypoEstimator.h" +// Math +#include "GaudiKernel/Point3DTypes.h" +#include "GaudiKernel/Vector3DTypes.h" +#include "LHCbMath/Line.h" +#include "LHCbMath/GeomFun.h" + +//using namespace LHCb; + +#include "TMV_MLP_H.C" +#include "TMV_MLP_E.C" + +/** @class neutralIDTool neutralIDTool.h + * + * + * @author Mostafa HOBALLAH + * @date 2013-07-25 + */ +class FutureNeutralIDTool : public GaudiTool, virtual public IFutureNeutralIDTool{ +public: + + // Return the interface ID + // static const InterfaceID& interfaceID() { return IID_FutureNeutralIDTool; } + + /// Standard constructor + FutureNeutralIDTool( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + StatusCode finalize() override; + + //double isPhoton(const LHCb::Particle* gamma); + double isNotE(const LHCb::CaloHypo* hypo,ICaloFutureHypoEstimator* e=NULL) override; + double isNotH(const LHCb::CaloHypo* hypo,ICaloFutureHypoEstimator* e=NULL) override; + void Variables(const LHCb::CaloHypo* hypo, double& clmatch, + double& prse, double& e19, double& hclecl, double& prse19,double& prse49, + double& sprd, double& prse4mx, double& prsm, double& spdm) override; + + + double isNotE(const double* v) override { + return photonDiscriminantE(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); + } + double isNotH(const double* v) override { + return photonDiscriminantH(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); + } + +private: + + Gaudi::Property<float> m_minPt {this, "MinPt", 75.}; + + std::unique_ptr<IClassifierReader> m_reader0; + std::unique_ptr<IClassifierReader> m_reader1; + + + + //Gaudi::XYZPoint m_vertex; + //Gaudi::Plane3D m_planePrs; + + double photonDiscriminantE(double clmatch, double prse, double e19, double hclecl, double prse19, + double prse49, double sprd, double prse4mx, double prsm, double spdm); + + double photonDiscriminantH(double clmatch, double prse, double e19, double hclecl, double prse19, + double prse49, double sprd, double prse4mx, double prsm, double spdm); + + + ICaloFutureHypoEstimator* m_estimator = nullptr; + +}; +#endif // FUTURENEUTRALIDTOOL_H diff --git a/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.cpp b/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ff885ffa015462aec106c50c1773618f3960037a --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.cpp @@ -0,0 +1,76 @@ +#include "FutureXGBClassifierPhPi0.h" +#include <iostream> +#include <exception> + + +FutureXGBClassifierPhPi0::FutureXGBClassifierPhPi0() +{ + XGDMatrixCreateFromMat( + &m_predictionsCache.at(0), + 1, + 2, + 0.5, + &m_cache_matrix); +} + +FutureXGBClassifierPhPi0::FutureXGBClassifierPhPi0(const std::string& path) +{ + xgb_path = path; + //std::cout<<"PATH str: "<< xgb_path << std::endl; + XGDMatrixCreateFromMat( + &m_predictionsCache.at(0), + 1, + 2, + 0.5, + &m_cache_matrix); + XGBoosterCreate(&m_cache_matrix, 1, &m_booster); + int err_code = XGBoosterLoadModel(m_booster, xgb_path.c_str()); + if (err_code == -1){ + log << MSG::WARNING << "Do not load XGBModel " << endmsg; + } +} + +void FutureXGBClassifierPhPi0::setPath(const std::string& path) +{ + XGBoosterCreate(&m_cache_matrix, 1, &m_booster); + try{ + XGBoosterLoadModel(m_booster, path.c_str()); + } + catch(const std::exception& e){ + log << MSG::WARNING << "Standard exception " << endmsg; + } +} + +double FutureXGBClassifierPhPi0::getClassifierValues(const std::vector<double>& featureValues) +{ + // currently XGBoost only supports float + std::vector<float> features_f(featureValues.begin(), featureValues.end()); + + // fill the feature vector into a XGBoost DMatrix + XGDMatrixCreateFromMat(&features_f.at(0), + 1, + features_f.size(), + 0, + &m_feature_matrix); + + // XGBoost returns the predictions into a arrayish object and return + // its size + unsigned long predictions_length; + const float *predictions; + try{ + XGBoosterPredict(m_booster, + m_feature_matrix, + 0, + 0, + &predictions_length, + &predictions); + } + catch(...){ + log << MSG::WARNING << "some exeption " << endmsg; + } + std::vector<double> vec_predictions; + for (unsigned int i =0; i<predictions_length; i++){ + vec_predictions.push_back(predictions[i]); + } + return vec_predictions[0]; +} \ No newline at end of file diff --git a/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.h b/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.h new file mode 100644 index 0000000000000000000000000000000000000000..a5f6ce917fa5e13116b82832492b8bd2b7bdb3ca --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/FutureXGBClassifierPhPi0.h @@ -0,0 +1,43 @@ +#ifndef XGBCLASSIFIER_H +#define XGBCLASSIFIER_H + +#include <string> +#include <vector> +#include "xgboost/c_api.h" +#include "GaudiKernel/ServiceHandle.h" +#include "GaudiKernel/IMessageSvc.h" +#include "GaudiKernel/MsgStream.h" +//#include "/afs/cern.ch/user/v/vchekali/public/xgboost/include/xgboost/c_api.h" + +class IClassifier +{ +public: + + /** * @brief Main classification method * + * Takes a vector of values of features and returns the corresponding MVA + * output. + * * @param[in] featureValues A vector of feature values + * * @return MVA classifier value */ + virtual double getClassifierValues(const std::vector<double>& featureValues) = 0; +}; + +class FutureXGBClassifierPhPi0 : public IClassifier { + public: + FutureXGBClassifierPhPi0(); + FutureXGBClassifierPhPi0(const std::string& path); + double getClassifierValues(const std::vector<double>& featureValues) override; + void setPath(const std::string& path); + ServiceHandle<IMessageSvc> msgh = ServiceHandle<IMessageSvc>("MessageSvc","XGBLog"); + MsgStream log = MsgStream(&(*msgh), "XGBLog"); + + private: + std::string xgb_path ="def_path"; + std::vector<float> m_predictionsCache = {0, 0}; + DMatrixHandle m_cache_matrix, + m_feature_matrix; + BoosterHandle m_booster; + +}; + + +#endif // XGBCLASSIFIER_H diff --git a/CaloFuture/CaloFutureTools/src/L0CaloFuture2CaloFutureTool.cpp b/CaloFuture/CaloFutureTools/src/L0CaloFuture2CaloFutureTool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..633ba6f7e02e8c70293fb16551e0ebe31559dcb1 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/L0CaloFuture2CaloFutureTool.cpp @@ -0,0 +1,344 @@ +#include "CaloFutureInterfaces/ICaloFutureClusterization.h" +#include "L0CaloFuture2CaloFutureTool.h" +#include "CaloKernel/CaloVector.h" +#include "CaloDet/DeCalorimeter.h" +#include "CaloFutureUtils/CaloFutureNeighbours.h" +#include "Event/L0DUBase.h" + +#include <boost/functional/hash.hpp> + +/** @class L0CaloFuture2CaloFutureTool L0CaloFuture2CaloFutureTool.cpp + * + * Tool to get a list of CaloFutureClusters (owned by TES) in the vicinity of + * the input L0CaloFutureCandidate(s), if necessary invoking decoding and clusterization. + * + * @author Dmitry Goloubkov + * @date 2009-07-29 + */ + +DECLARE_COMPONENT( L0CaloFuture2CaloFutureTool ) + +/// Standard constructor +L0CaloFuture2CaloFutureTool::L0CaloFuture2CaloFutureTool(const std::string& type, + const std::string& name, + const IInterface* parent) + : base_class ( type, name , parent ) +{ + declareInterface<IL0CaloFuture2CaloFuture>(this); + m_ecalCaloFutureNum = CaloCellCode::CaloNumFromName("Ecal"); +} +// ========================================================================== +StatusCode L0CaloFuture2CaloFutureTool::initialize() +{ + StatusCode sc = base_class::initialize(); + if (sc.isFailure()) return Error("Failed to initialize", sc); + + m_calo = getDet<DeCalorimeter>( DeCalorimeterLocation::Ecal ); + m_clusterizationTool = tool< ICaloFutureClusterization >(m_clusterizationToolName); + m_dataProviderTool = tool< ICaloFutureDataProvider >(m_dataProviderToolName, "EcalDataProvider", this, true); + + info() << "Clusterizing Calo around L0 candidates : NeighbourLevel set to " << m_neighbourLevel << endmsg; + + return StatusCode::SUCCESS; +} +// ========================================================================== +StatusCode L0CaloFuture2CaloFutureTool::clusterize + ( std::vector<LHCb::CaloCluster*>& clusters , + const LHCb::CaloCellID& cellID, + const unsigned int level ) const +{ + if ( ! isUsable( cellID ) ) return StatusCode::FAILURE; + + // Invoke the CaloFutureDataProvider tool + const LHCb::CaloDigits* digits = makeDigits( cellID, level ); + if ( 0 == digits ) return Error(" Failure to (re)make CaloDigits!", StatusCode::FAILURE ); + + // Select the right seed : + LHCb::CaloCellID seedID = cellID; + unsigned int area = cellID.area(); + unsigned int row = cellID.row(); + unsigned int col = cellID.col(); + double dig = m_dataProviderTool->digit( cellID ); + LHCb::CaloCellID ul(m_ecalCaloFutureNum, area, row+1, col ); + if( m_dataProviderTool->digit( ul ) > dig ){ dig = m_dataProviderTool->digit( ul ); seedID = ul;} + LHCb::CaloCellID ur(m_ecalCaloFutureNum, area, row+1, col+1); + if( m_dataProviderTool->digit( ur ) > dig ){ dig = m_dataProviderTool->digit( ur ); seedID = ur;} + LHCb::CaloCellID dr(m_ecalCaloFutureNum, area, row , col+1); + if( m_dataProviderTool->digit( dr ) > dig ){ dig = m_dataProviderTool->digit( dr ); seedID = dr;} + + // Invoke the CaloFutureClusterizationTool + StatusCode sc = makeClusters( clusters, digits, seedID, level ); + if ( sc.isFailure() ) return Error(" Failure from the CaloFutureClusterizationTool!", sc ); + + return putClustersOnTES( clusters ); +} +// ========================================================================== +StatusCode L0CaloFuture2CaloFutureTool::clusterize + ( std::vector<LHCb::CaloCluster*>& clusters, + const LHCb::CaloCellID& cellID ) const +{ + return clusterize( clusters, cellID, m_neighbourLevel ); +} + +// ========================================================================== +StatusCode L0CaloFuture2CaloFutureTool::clusterize +( std::vector<LHCb::CaloCluster*>& clusters, + const LHCb::L0CaloCandidate* candidate, + const unsigned int level ) const +{ + if ( ! isUsable( candidate ) ) return StatusCode::FAILURE; + + const LHCb::CaloCellID& cellID = candidate->id(); + return clusterize(clusters, cellID, level); +} +// ========================================================================== +StatusCode L0CaloFuture2CaloFutureTool::clusterize +( std::vector<LHCb::CaloCluster*>& clusters, + const LHCb::L0CaloCandidate* candidates ) const +{ + return clusterize( clusters, candidates, m_neighbourLevel ); +} +// ========================================================================== +StatusCode L0CaloFuture2CaloFutureTool::makeClusters +( std::vector<LHCb::CaloCluster*>& clusters, + const LHCb::CaloDigits* digits, + const LHCb::CaloCellID& cellID, + const unsigned int level ) const +{ + if ( NULL == digits ) return Error("CaloDigits == NULL (should never happen here)", StatusCode::FAILURE); + clusters.clear(); + + std::vector<LHCb::CaloCellID> seeds = { cellID }; + m_clusterizationTool->clusterize(clusters, *digits, m_calo, seeds, level); + + /** sort the sequence to simplify the comparison + * with other clusterisation techniques + */ + if ( m_sort ){ + error() << " FEATURE NOT implemented! (neither Sort nor SortET)" << endmsg; +/* + if ( !m_sortET ) + { + // sorting criteria: Energy + LHCb::CaloDataFunctor::Less_by_Energy<const LHCb::CaloCluster*> Cmp; + // perform the sorting + std::stable_sort ( clusters.begin() , + clusters.end () , + LHCb::CaloDataFunctor::inverse( Cmp ) ) ; + } + else + { + // sorting criteria : Transverse Energy + LHCb::CaloDataFunctor::Less_by_TransverseEnergy<const LHCb::CaloCluster*, + const DeCalorimeter*> Cmp ( m_detector ) ; + // perform the sorting + std::stable_sort ( clusters.begin() , + clusters.end () , + LHCb::CaloDataFunctor::inverse( Cmp ) ) ; + } +*/ + } + + return StatusCode::SUCCESS; +} +// ========================================================================== +StatusCode L0CaloFuture2CaloFutureTool::putClustersOnTES( std::vector<LHCb::CaloCluster*>& clusters ) const +{ + + + if( !m_clusOnTES )return StatusCode::SUCCESS; + + + LHCb::CaloClusters* output = getOrCreate<LHCb::CaloClusters, LHCb::CaloClusters>( m_clusterLocation ); + output -> setVersion( 2 ); // update the version number (needed for serialization) + if ( msgLevel(MSG::DEBUG) ) + debug() << "0: LHCb::CaloClusters at " << m_clusterLocation << " size = " << (long) output->size() + << " v=" << (int) output->version() << " newly found clusters.size() = " << clusters.size() << endmsg; /////// + + // populate the CaloClusters TS container + for ( std::vector<LHCb::CaloCluster*>::iterator icluster = clusters.begin(); + clusters.end() != icluster; ++icluster){ + LHCb::CaloCluster* cl = *icluster; + if ( 0 == cl ) continue; + + // check that cluster is not yet owned by some container + if ( 0 != cl->parent() ) continue; + + // store everything on TES (allow duplications in case of multiple calls) + output -> insert ( cl ) ; + } + + if ( msgLevel(MSG::DEBUG) ) debug() << "1: LHCb::CaloClusters at " << m_clusterLocation << " size = " << long( output->size() ) << endmsg; + + return StatusCode::SUCCESS; +} +// ========================================================================== +bool L0CaloFuture2CaloFutureTool::isUsable( const LHCb::CaloCellID& cellID ) const +{ + if ( cellID.calo() != m_ecalCaloFutureNum ){ + if ( msgLevel(MSG::DEBUG) ) debug() << "skip non-Ecal cellID = " << cellID << endmsg; + return false; + } + + if ( !m_calo->valid( cellID ) ){ + if ( msgLevel(MSG::DEBUG) ) debug() << "skip ivnalid cellID = " << cellID << endmsg; + return false; + } + + return true; +} +// ========================================================================== +bool L0CaloFuture2CaloFutureTool::isUsable( const LHCb::L0CaloCandidate* candidate ) const +{ + if ( ! candidate ) return false; + + int type = candidate->type(); + if ( type == L0DUBase::CaloType::Electron + || type == L0DUBase::CaloType::Photon ) return true; + + return false; +} +// ========================================================================== +const LHCb::CaloDigits* L0CaloFuture2CaloFutureTool::makeDigits +( const LHCb::CaloCellID& cellID, + const unsigned int level ) const +{ + bool read = exist<LHCb::CaloDigits>( m_digitLocation ); + if ( msgLevel(MSG::VERBOSE) ) verbose() << "0: data at " << m_digitLocation + << " does" << ( read ? "" : " NOT") << " exist" << endmsg; + if ( !read ){ + //m_dataProviderTool->getBanks(); + m_decodedSources.clear(); + } + + LHCb::CaloDigits* digits = getOrCreate<LHCb::CaloDigits, LHCb::CaloDigits>( m_digitLocation ) ; + if ( msgLevel(MSG::DEBUG) ) + debug() << "1: data at " << m_digitLocation << " does" << ( exist<LHCb::CaloDigits>( m_digitLocation ) ? "" : " NOT") << " exist" + << " digits->size() = " << long( digits->size() ) << endmsg; + + if ( m_decodedSources.find( -1 ) != m_decodedSources.end() ){ + if ( msgLevel(MSG::DEBUG) ) debug() << " full Ecal (source =-1) has been already decoded" << endmsg; + return digits; + } + + + std::set<int> tell1s; + if ( m_decodeFullEcal ) + tell1s.insert( -1 ); // single source = -1: decode everything + else + collectTell1s( tell1s, cellID, level ); // loop over neighbour cells, collect corresponding tell1s + + + std::vector<int> sources; + for (std::set<int>::const_iterator it = tell1s.begin(); it != tell1s.end(); ++ it){ + int source = *it; + if ( m_decodedSources.find( source ) == m_decodedSources.end() ){ + sources.push_back( source ); + m_decodedSources.insert( source ); + }else + if ( msgLevel(MSG::DEBUG) ) debug() << " source " << *it << " has been already decoded" << endmsg; + } + + if ( sources.empty() ){ + if ( msgLevel(MSG::DEBUG) ) debug() << " all sources have been already decoded" << endmsg; + return digits; + } + + + const CaloVector<LHCb::CaloDigit>& dgs = m_dataProviderTool->digits( sources ); + + + // populate the CaloDigits TS container + for (CaloVector<LHCb::CaloDigit>::const_iterator it = dgs.begin(); it != dgs.end(); ++ it){ + const LHCb::CaloDigit* found = digits->object ( it->cellID() ) ; + if ( 0 != found ) { continue ; } + digits->insert( new LHCb::CaloDigit(*it) ); + } + if ( msgLevel(MSG::VERBOSE) ) verbose() << "2: digits->size() = " << ( digits ? (long) digits->size() : -1 ) << endmsg; + + return digits; +} +// ============================================================================ +void L0CaloFuture2CaloFutureTool::collectTell1s +( std::set<int>& tell1s, + const LHCb::CaloCellID& cellID, + const unsigned int level ) const +{ + LHCb::CaloCellID::Set out_cells; + std::set<int> cards; + + if ( !m_calo->valid(cellID) ) return; + + // incert the cells corresponding to the L0CaloCandidate + out_cells.insert( cellID ); + + if ( level > 0 ){ + unsigned int area = cellID.area(); + unsigned int row = cellID.row(); + unsigned int col = cellID.col(); + // LHCb::CaloCellID(unsigned int Calo, unsigned int Area, unsigned int Row, unsigned int Column) + LHCb::CaloCellID ul(m_ecalCaloFutureNum, area, row+1, col ); + LHCb::CaloCellID ur(m_ecalCaloFutureNum, area, row+1, col+1); + LHCb::CaloCellID dr(m_ecalCaloFutureNum, area, row , col+1); + + if ( msgLevel(MSG::VERBOSE) ) + verbose() << "seed=" << cellID << ":" << m_calo->cellCenter( cellID ) + << " ul =" << ul << ":" << m_calo->cellCenter( ul ) + << " ur =" << ur << ":" << m_calo->cellCenter( ur ) + << " dr =" << dr << ":" << m_calo->cellCenter( dr ) << endmsg; + + if ( m_calo->valid(ul) ) out_cells.insert( ul ); + else + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "ul cell " << ul << " invalid" << endmsg; + + if ( m_calo->valid(ur) ) out_cells.insert( ur ); + else + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "ur cell " << ur << " invalid" << endmsg; + + if ( m_calo->valid(dr) ) out_cells.insert( dr ); + else + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "dr cell " << dr << " invalid" << endmsg; + + + /** find all neighbours for the given set of cells for the givel level + * @param cells (UPDATE) list of cells + * @param level (INPUT) level + * @param detector (INPUT) the detector + * @return true if neighbours are added + */ + LHCb::CaloFutureFunctors::neighbours(out_cells, level, m_calo); + } + + + for (LHCb::CaloCellID::Set::const_iterator it = out_cells.begin(); + it != out_cells.end(); ++ it){ + if ( ! m_calo->valid( *it ) ){ + warning() << "one of the neighbour cells, " << *it << " turned out to be invalid" << endmsg; + continue; + } + + int card = m_calo->cardNumber( *it ); + if ( card < 0 ){ + warning() << "valid cell " << *it << " corresponds to no FE card" << endmsg; + continue; + } + if ( msgLevel(MSG::DEBUG) ) debug() << " cell " << (*it) << " card = " << card << endmsg; + cards.insert( card ); + } + + for (std::set<int>::const_iterator it = cards.begin(); it != cards.end(); ++ it){ + int source = m_calo->cardToTell1( *it ); + if ( msgLevel(MSG::DEBUG) ) debug() << " card = " << *it << " tell1 ID = " << source << endmsg; + if ( source < 0 ){ + if ( msgLevel(MSG::ERROR) ) warning() << "FE card = " << *it << " corresponds to no Tell1" << endmsg; + continue; + } + tell1s.insert( source ); + } + + return; +} +// ============================================================================ diff --git a/CaloFuture/CaloFutureTools/src/L0CaloFuture2CaloFutureTool.h b/CaloFuture/CaloFutureTools/src/L0CaloFuture2CaloFutureTool.h new file mode 100644 index 0000000000000000000000000000000000000000..6c33570a4aaff8f0df3e0f6f4f1f04f43d6ffe1f --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/L0CaloFuture2CaloFutureTool.h @@ -0,0 +1,258 @@ +#ifndef L0CALOFUTURE2CALOFUTURETOOL_H +#define L0CALOFUTURE2CALOFUTURETOOL_H 1 +// ============================================================================ +#include <string> +#include <iostream> +#include <string> +#include <iostream> +#include "GaudiAlg/GaudiTool.h" +#include "CaloKernel/CaloVector.h" +#include "CaloDet/DeCalorimeter.h" + +#include "CaloFutureInterfaces/IL0CaloFuture2CaloFuture.h" +#include "CaloFutureInterfaces/ICaloFutureClusterization.h" + +#include "CaloFutureDAQ/ICaloFutureDataProvider.h" + +// forward declarations +class DeCalorimeter; + +/** @class L0CaloFuture2CaloFutureTool L0CaloFuture2CaloFutureTool.h + * Tool to get a list of CaloFutureClusters (owned by TES) in the vicinity of the input L0CaloFutureCandidate(s), + * if necessary invoking decoding and clusterization. + * + * Remarks: + * - the returned clusters are owned by TES and should not be deleted by the user; + * - in case of multiple calls of the tool on intersecting zones of Ecal + * - there might appear duplicated clusters on TES, + * - unless the input/output std::vector<LHCb::CaloCluster*> clusters + * is clear()'ed by the user before calling L0CaloFuture2CaloFutureTool::clusterize(), + * this vector also might contain duplicates + * + * @author Dmitry Golubkov + * @date 2009-07-29 + */ +class L0CaloFuture2CaloFutureTool : public extends<GaudiTool,IL0CaloFuture2CaloFuture> +{ + +public: + /// Standard constructor + L0CaloFuture2CaloFutureTool( const std::string& type, + const std::string& name, + const IInterface* parent); + // ========================================================================== + /** obtain CaloFutureClusters corresponding to L0CaloFutureCandidates + * + * Get a list of CaloFutureClusters in the vicinity of the L0CaloFutureCandidate, + * invoke decoding and clusterization if necessary. + * The output clusters are stored in TES location CaloDigitLocation, the + * created CaloDigits are stored on TES in CaloDigitLocation. + * + * @param clusters (OUTPUT) vector of pointers of CaloFuture clusters (output) + * @param candidate (INPUT) pointer to L0CaloFutureCandidate + * @param level (INPUT) number of neigbour levels around the candidate->id() cell + * for the CaloFutureClusterization tool + * @return FAILURE when anything goes wrong, otherwise the return StatusCode of the ICaloFutureClusterization tool used + */ + StatusCode clusterize + ( std::vector<LHCb::CaloCluster*>& clusters , + const LHCb::L0CaloCandidate* candidate, + const unsigned int level ) const override; + // ========================================================================== + /** obtain CaloClusters corresponding to L0CaloCandidate + * + * Get a list of CaloClusters in the vicinity of an L0CaloCandidate, + * if necessary invoke decoding and clusterization. + * + * @param clusters (OUTPUT) vector of pointers of Calo clusters + * @param candidate (INPUT) pointer to L0CaloCandidate + */ + StatusCode clusterize + ( std::vector<LHCb::CaloCluster*>& clusters, + const LHCb::L0CaloCandidate* candidate ) const override; + // ========================================================================== + /** obtain CaloClusters corresponding to L0CaloCandidates + * + * Get a list of CaloClusters in the vicinity of an ObjectVector of L0CaloCandidates, + * invoke decoding and clusterization if necessary. + * @param clusters (OUTPUT) vector of pointers of Calo clusters + * @param candidates (INPUT) pointer to L0CaloCandidates + * @param level (INPUT) number of neigbour levels around cell for the CaloClusterization tool + */ + StatusCode clusterize + ( std::vector<LHCb::CaloCluster*>& clusters, + const LHCb::L0CaloCandidates* candidates, + const unsigned int level ) const override + { + (void) clusters, (void) candidates, (void) level; // avoid compiler warning + fatal() << "L0CaloFuture2CaloFutureTool::clusterize(..., const LHCb::L0CaloCandidates*, ...) NOT IMPLEMENTED" << endmsg; + return StatusCode::FAILURE; + } + // ========================================================================== + /** obtain CaloClusters corresponding to L0CaloCandidates + * + * Get a list of CaloClusters in the vicinity of an ObjectVector of L0CaloCandidates, + * invoke decoding and clusterization if necessary. + * @param clusters (OUTPUT) vector of pointers of Calo clusters + * @param candidates (INPUT) pointer to L0CaloCandidates + */ + StatusCode clusterize + ( std::vector<LHCb::CaloCluster*>& clusters, + const LHCb::L0CaloCandidates* candidates ) const override { return clusterize(clusters, candidates, m_neighbourLevel); } + // ========================================================================== + /** obtain CaloClusters around a CaloCellID + * + * Get a list of CaloClusters in the vicinity of the CaloCellID, + * if necessary invoke decoding and clusterization. + * + * @param clusters (OUTPUT) vector of pointers of Calo clusters + * @param cellID (INPUT) pointer to CaloCellID + * @param level (INPUT) number of neigbour levels around the cell for the ICaloClusterization tool + */ + StatusCode clusterize + ( std::vector<LHCb::CaloCluster*>& clusters , + const LHCb::CaloCellID& cellID, + const unsigned int level ) const override; + // ========================================================================== + /** obtain CaloClusters around a CaloCellID + * + * Get a list of CaloClusters in the vicinity of the CaloCellID, + * if necessary invoke decoding and clusterization. + * + * @param clusters (OUTPUT) vector of pointers of Calo clusters + * @param cellID (INPUT) pointer to CaloCellID + */ + StatusCode clusterize + ( std::vector<LHCb::CaloCluster*>& clusters, + const LHCb::CaloCellID& cellID ) const override; + // ========================================================================== + StatusCode initialize() override; + // ========================================================================== +protected: + // ========================================================================== + /** obtain CaloClusters corresponding to the digits using cellID as a seed + * + * Get a list of CaloClusters in the vicinity of cellID, see makeDigits() + * for explanation of the region used for cluster search. + * + * @param clusters (OUTPUT) vector of pointers to Calo clusters + * @param digits (INPUT) pointer to the CaloDigits + * @param cellID (INPUT) of the L0CaloCandidate seed cell + * @param level (INPUT) the radius of the area to be clusterized + */ + StatusCode makeClusters + ( std::vector<LHCb::CaloCluster*>& clusters, + const LHCb::CaloDigits* digits, + const LHCb::CaloCellID& cellID, + const unsigned int level ) const ; + // ========================================================================== + /** put the vector CaloClutsters on TES + * + * @param clusters (INPUT/OUTPUT) vector of pointers to Calo clusters + * + * NB: in case of multiple calls of the L0Calo2CaloTool on intersecting + * zones of Ecal, there might appear duplicates! + */ + StatusCode putClustersOnTES + ( std::vector<LHCb::CaloCluster*>& clusters ) const ; + // ========================================================================== + /** prepare CaloDigits around the given cellID and store them on TES + * + * @param cellID of the seed cell + * @param level defines the size of the digitized area (see below) + * @return container of CaloDigits corresponding to the TES + * + * The decoding is done for the Tell1's which correspond to the cells + * in the region centered around the seed cellID and having the area of the + * the size ~ 2*(1+Level)x2*(1+Level) as steered by the level parameter. + * The same region of cells is used by the CaloFutureClusterization tool + * invoked by makeClusters(). The area is constructed by recurrent addition of + * DeCalorimeter::neighborCell(...) to the the area starting from the L0CaloFutureCandidate. + * Typical value which should be OK for the NeighbourLevel is ~2. + * + * Below is an illustration for NeighbourLevel = 3: + * -+-+-+-+-+-+-+-+-+-+-+-+- + * .|.|.|.|.|.|.|.|.|.|.|.|. + * -+-+-+-+-+-+-+-+-+-+-+-+- + * .|.|.|*|*|*|*|*|*|*|*|.|.<-- + * -+-+-+-+-+-+-+-+-+-+-+-+- | + * .|.|.|*|*|*|*|*|*|*|*|.|. d + * -+-+-+-+-+-+-+-+-+-+-+-+- | + * .|.|.|*|*|*|*|*|*|*|*|.|.<-- d = level (defaults to the NighbourLevel property) + * -+-+-+-+-+-+-+-+-+-+-+-+- . = Ecal cells + * .|.|.|*|*|*|#|#|*|*|*|.|. * = cells included in the digitization + * -+-+-+-+-+-+-+-+-+-+-+-+- {@,#} = 2x2 cell region of the L0CaloFutureCandidate + * .|.|.|*|*|*|@|#|*|*|*|.|. @ = seed cell + * -+-+-+-+-+-+-+-+-+-+-+-+- + * .|.|.|*|*|*|*|*|*|*|*|.|. <-- + * -+-+-+-+-+-+-+-+-+-+-+-+- | + * .|.|.|*|*|*|*|*|*|*|*|.|. d + * -+-+-+-+-+-+-+-+-+-+-+-+- | + * .|.|.|*|*|*|*|*|*|*|*|.|. <-- + * -+-+-+-+-+-+-+-+-+-+-+-+- + * .|.|.|.|.|.|.|.|.|.|.|.|. + * ^ ^ ^ ^ + * |<-d->| |<-d->| + */ + const LHCb::CaloDigits* makeDigits( const LHCb::CaloCellID &cellID, const unsigned int level ) const ; + // ========================================================================== + /** check if cell ID is usable + * + * A cell is accepted if it corresponds to Ecal + * and if DeCalorimeter::valid( cellID ) is true + * @param cellID of the cell in question + * @return true if the cell is accepted / false otherwise + */ + bool isUsable( const LHCb::CaloCellID &cellID ) const ; + // ========================================================================== + /** check if the L0CaloFutureCandidate is usable + * + * An L0CaloFutureCandidate is accepted if its type() is Electron or Photon (see L0DUBase::CaloFutureType ) + * @param candidate pointer to the tested L0CaloFutureCandidate + * @return true if the candidate is accepted / false otherwise + */ + bool isUsable( const LHCb::L0CaloCandidate *candidate ) const ; + // ========================================================================== + + /** collect the Tell1 numbers corresponding to the given L0CaloFutureCandidate seed cellID + * + * @param tell1s (OUTPUT) set of tell1 IDs + * @param cellID (INPUT) the seed cell of a 2x2 cell L0CaloFutureCandidate + * @param level (INPUT) the neighbour level which defines the size of the area, see makeDigits(...) + */ + void collectTell1s + ( std::set<int>& tell1s, + const LHCb::CaloCellID& cellID, + const unsigned int level ) const ; + // ========================================================================== +private: + Gaudi::Property<std::string> m_clusterizationToolName {this, "CaloFutureClusterizationTool", "CaloFutureClusterizationTool"}; + Gaudi::Property<std::string> m_dataProviderToolName {this, "CaloFutureDataProviderTool" , "CaloFutureDataProvider"}; + + ICaloFutureClusterization* m_clusterizationTool = nullptr; + ICaloFutureDataProvider* m_dataProviderTool = nullptr; + DeCalorimeter* m_calo = nullptr; + + unsigned int m_ecalCaloFutureNum; + + Gaudi::Property<std::string> m_digitLocation {this, "CaloDigitLocation" , LHCb::CaloDigitLocation::Hlt1Ecal}; + Gaudi::Property<std::string> m_clusterLocation{this, "CaloFutureClusterLocation", LHCb::CaloClusterLocation::EcalHlt1}; + + Gaudi::Property<unsigned int> m_neighbourLevel + {this, "NeighbourLevel", 2, "Level parameter for the CaloFutureClusterizationTool, search clusters in (1+2*Level)x(1+2*Level) region around the seed cell"}; + + Gaudi::Property<bool> m_sort + {this, "Sort", false, "sort the clusters due to energy"}; + + Gaudi::Property<bool> m_sortET + {this, "SortET", false, "if Sort: sort the clusters due to transverse energy"}; + + Gaudi::Property<bool> m_decodeFullEcal + {this, "DecodeFullEcal", false, "false = decode only the Tell1s around the L0CaloFutureCandidate cellID"}; + + Gaudi::Property<bool> m_clusOnTES + {this, "ClusterOnTES", false}; + + mutable std::set<int> m_decodedSources; +}; +#endif // L0CALOFUTURE2CALOFUTURETOOL_H diff --git a/CaloFuture/CaloFutureTools/src/Part2CaloFuture.cpp b/CaloFuture/CaloFutureTools/src/Part2CaloFuture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0caef437f63863ed1faea1011b7edba3a84bb3cb --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/Part2CaloFuture.cpp @@ -0,0 +1,65 @@ +// $Id: Part2CaloFuture.cpp,v 1.2 2009-05-19 13:48:22 cattanem Exp $ +// Include files + +// from LHCb +#include "Event/Particle.h" +#include "Kernel/TrackDefaultParticles.h" +// local +#include "Part2CaloFuture.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : Part2CaloFuture +// +// 2006-11-30 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( Part2CaloFuture ) + + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +Part2CaloFuture::Part2CaloFuture( const std::string& type, + const std::string& name, + const IInterface* parent ) + : Track2CaloFuture ( type, name , parent ) + , m_particle ( NULL ) + , m_proto ( NULL ){ + declareInterface<IPart2CaloFuture>(this); +} + +//============================================================================= +StatusCode Part2CaloFuture::initialize(){ + StatusCode sc = Track2CaloFuture::initialize(); + if (sc.isFailure()) return Error("Failed to initialize", sc); + return StatusCode::SUCCESS; +} +//============================================================================= +bool Part2CaloFuture::match(const LHCb::Particle* part, std::string det,CaloPlane::Plane plane , double delta){ + m_status = setting( part ); + if ( m_status ) + return Track2CaloFuture::match( m_track, det, plane, delta, LHCb::Tr::PID( m_particle->particleID().abspid() ) ); + return m_status; +} +//============================================================================= +bool Part2CaloFuture::match(const LHCb::ProtoParticle* proto, std::string det,CaloPlane::Plane plane , double delta){ + m_status = setting( proto ); + if( m_status )return Track2CaloFuture::match(m_track, det, plane, delta); + return m_status; +} +//============================================================================= +bool Part2CaloFuture::setting(const LHCb::Particle* particle){ + m_particle = particle; + if( NULL == m_particle)return false; + const LHCb::ProtoParticle* proto = m_particle -> proto(); + return setting(proto); +} +//============================================================================= +bool Part2CaloFuture::setting(const LHCb::ProtoParticle* proto){ + m_proto = proto; + if( NULL == m_proto)return false; + return Track2CaloFuture::setting( m_proto->track() ); +} +//============================================================================= + diff --git a/CaloFuture/CaloFutureTools/src/Part2CaloFuture.h b/CaloFuture/CaloFutureTools/src/Part2CaloFuture.h new file mode 100644 index 0000000000000000000000000000000000000000..37f69b6d804febf77e9c93463ebe556c31d17137 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/Part2CaloFuture.h @@ -0,0 +1,57 @@ +// $Id: Part2CaloFuture.h,v 1.2 2010-06-10 12:46:38 cattanem Exp $ +#ifndef PART2CALOFUTURE_H +#define PART2CALOFUTURE_H 1 + +// Include files +#include "Track2CaloFuture.h" +#include "Event/ProtoParticle.h" +// from Gaudi +#include "CaloFutureInterfaces/IPart2CaloFuture.h" + + + +/** @class Part2CaloFuture Part2CaloFuture.h + * + * + * @author Olivier Deschamps + * @date 2006-11-30 + */ +class Part2CaloFuture : public Track2CaloFuture, virtual public IPart2CaloFuture { +public: + /// Standard constructor + Part2CaloFuture( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + + using Track2CaloFuture::match; + bool match(const LHCb::ProtoParticle* proto, + std::string det = DeCalorimeterLocation::Ecal, + CaloPlane::Plane plane = CaloPlane::ShowerMax, + double delta = 0. + ) override; + bool match(const LHCb::Particle* part, + std::string det = DeCalorimeterLocation::Ecal, + CaloPlane::Plane plane = CaloPlane::ShowerMax, + double delta = 0. + ) override; + inline bool inAcceptance() override; + + +protected: + bool setting (const LHCb::Particle* part); + bool setting (const LHCb::ProtoParticle* proto); + const LHCb::Particle* m_particle; + const LHCb::ProtoParticle* m_proto; +private: +}; +#endif // PART2CALOFUTURE_H + +inline bool Part2CaloFuture::inAcceptance(){ + if(m_det == DeCalorimeterLocation::Spd) return m_proto->info(LHCb::ProtoParticle::additionalInfo::InAccSpd, 0.)!=0; + if(m_det == DeCalorimeterLocation::Prs) return m_proto->info(LHCb::ProtoParticle::additionalInfo::InAccPrs, 0.)!=0; + if(m_det == DeCalorimeterLocation::Ecal) return m_proto->info(LHCb::ProtoParticle::additionalInfo::InAccEcal, 0.)!=0; + if(m_det == DeCalorimeterLocation::Hcal) return m_proto->info(LHCb::ProtoParticle::additionalInfo::InAccHcal, 0.)!=0; + return false; +} diff --git a/CaloFuture/CaloFutureTools/src/TMV_MLP_E.C b/CaloFuture/CaloFutureTools/src/TMV_MLP_E.C new file mode 100644 index 0000000000000000000000000000000000000000..3411a09e24b4e386d2769c4091598020f9db0c7e --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/TMV_MLP_E.C @@ -0,0 +1,645 @@ +// Class: ReadMLPE +// Automatically generated by MethodBase::MakeClass +// + +/* configuration options ===================================================== + +#GEN -*-*-*-*-*-*-*-*-*-*-*- general info -*-*-*-*-*-*-*-*-*-*-*- + +Method : MLP::MLP +TMVA Release : 4.1.4 [262404] +ROOT Release : 5.34/05 [336389] +Creator : hoballah +Date : Wed Jul 3 22:48:23 2013 +Host : Linux lxbuild175.cern.ch 2.6.18-308.4.1.el5 #1 SMP Wed Apr 18 16:26:27 CEST 2012 x86_64 x86_64 x86_64 GNU/Linux +Dir : /users/divers/lhcb/hoballah/December2012/B2KstG_ana/TMVA-v4.1.2/test/BDTs_PhotonID_new_var/train_test_E +Training events: 1426367 +Analysis type : [Classification] + + +#OPT -*-*-*-*-*-*-*-*-*-*-*-*- options -*-*-*-*-*-*-*-*-*-*-*-*- + +# Set by User: +NCycles: "750" [Number of training cycles] +HiddenLayers: "N+5" [Specification of hidden layer architecture] +NeuronType: "tanh" [Neuron activation function type] +EstimatorType: "CE" [MSE (Mean Square Estimator) for Gaussian Likelihood or CE(Cross-Entropy) for Bernoulli Likelihood] +V: "False" [Verbose output (short form of "VerbosityLevel" below - overrides the latter one)] +VarTransform: "N" [List of variable transformations performed before training, e.g., "D_Background,P_Signal,G,N_AllClasses" for: "Decorrelation, PCA-transformation, Gaussianisation, Normalisation, each for the given class of events ('AllClasses' denotes all events of all classes, if no class indication is given, 'All' is assumed)"] +H: "True" [Print method-specific help message] +TrainingMethod: "BP" [Train with Back-Propagation (BP), BFGS Algorithm (BFGS), or Genetic Algorithm (GA - slower and worse)] +TestRate: "5" [Test for overtraining performed at each #th epochs] +UseRegulator: "False" [Use regulator to avoid over-training] +# Default: +RandomSeed: "1" [Random seed for initial synapse weights (0 means unique seed for each run; default value '1')] +NeuronInputType: "sum" [Neuron input function type] +VerbosityLevel: "Default" [Verbosity level] +CreateMVAPdfs: "False" [Create PDFs for classifier outputs (signal and background)] +IgnoreNegWeightsInTraining: "False" [Events with negative weights are ignored in the training (but are included for testing and performance evaluation)] +LearningRate: "2.000000e-02" [ANN learning rate parameter] +DecayRate: "1.000000e-02" [Decay rate for learning parameter] +EpochMonitoring: "False" [Provide epoch-wise monitoring plots according to TestRate (caution: causes big ROOT output file!)] +Sampling: "1.000000e+00" [Only 'Sampling' (randomly selected) events are trained each epoch] +SamplingEpoch: "1.000000e+00" [Sampling is used for the first 'SamplingEpoch' epochs, afterwards, all events are taken for training] +SamplingImportance: "1.000000e+00" [ The sampling weights of events in epochs which successful (worse estimator than before) are multiplied with SamplingImportance, else they are divided.] +SamplingTraining: "True" [The training sample is sampled] +SamplingTesting: "False" [The testing sample is sampled] +ResetStep: "50" [How often BFGS should reset history] +Tau: "3.000000e+00" [LineSearch "size step"] +BPMode: "sequential" [Back-propagation learning mode: sequential or batch] +BatchSize: "-1" [Batch size: number of events/batch, only set if in Batch Mode, -1 for BatchSize=number_of_events] +ConvergenceImprove: "1.000000e-30" [Minimum improvement which counts as improvement (<0 means automatic convergence check is turned off)] +ConvergenceTests: "-1" [Number of steps (without improvement) required for convergence (<0 means automatic convergence check is turned off)] +UpdateLimit: "10000" [Maximum times of regulator update] +CalculateErrors: "False" [Calculates inverse Hessian matrix at the end of the training to be able to calculate the uncertainties of an MVA value] +WeightRange: "1.000000e+00" [Take the events for the estimator calculations from small deviations from the desired value to large deviations only over the weight range] +## + + +#VAR -*-*-*-*-*-*-*-*-*-*-*-* variables *-*-*-*-*-*-*-*-*-*-*-*- + +NVar 10 +CaloHypo_ClusterMatch CaloHypo_ClusterMatch CaloHypo_ClusterMatch CaloHypo_ClusterMatch units 'F' [0,9999] +CaloHypo_ToPrsE CaloHypo_ToPrsE CaloHypo_ToPrsE CaloHypo_ToPrsE units 'F' [0,280.579986572] +CaloHypo_E19 CaloHypo_E19 CaloHypo_E19 CaloHypo_E19 units 'F' [0,1.73788714409] +CaloHypo_Hcal2Ecal CaloHypo_Hcal2Ecal CaloHypo_Hcal2Ecal CaloHypo_Hcal2Ecal units 'F' [0,94.6786651611] +CaloHypo_PrsE19 CaloHypo_PrsE19 CaloHypo_PrsE19 CaloHypo_PrsE19 units 'F' [0,1] +CaloHypo_PrsE49 CaloHypo_PrsE49 CaloHypo_PrsE49 CaloHypo_PrsE49 units 'F' [0,1] +CaloHypo_Spread CaloHypo_Spread CaloHypo_Spread CaloHypo_Spread units 'F' [0,64433.078125] +CaloHypo_PrsE4Max CaloHypo_PrsE4Max CaloHypo_PrsE4Max CaloHypo_PrsE4Max units 'F' [0,955.837036133] +CaloHypo_HypoPrsM CaloHypo_HypoPrsM CaloHypo_HypoPrsM CaloHypo_HypoPrsM units 'F' [0,10] +CaloHypo_HypoSpdM CaloHypo_HypoSpdM CaloHypo_HypoSpdM CaloHypo_HypoSpdM units 'F' [0,9] +NSpec 0 + + +============================================================================ */ + +#include <vector> +#include <cmath> +#include <string> +#include <iostream> + +#ifndef IClassifierReader__def +#define IClassifierReader__def + +class IClassifierReader { + + public: + + // constructor + IClassifierReader() : fStatusIsClean( true ) {} + virtual ~IClassifierReader() {} + + // return classifier response + virtual double GetMvaValue( const std::vector<double>& inputValues ) const = 0; + + // returns classifier status + bool IsStatusClean() const { return fStatusIsClean; } + + protected: + + bool fStatusIsClean; +}; + +#endif + +class ReadMLPE : public IClassifierReader { + + public: + + // constructor + ReadMLPE( const std::vector<std::string>& theInputVars ) + : IClassifierReader(), + fClassName( "ReadMLPE" ), + fNvars( 10 ), + fIsNormalised( false ) + { + // the training input variables + const char* inputVars[] = { "CaloHypo_ClusterMatch", "CaloHypo_ToPrsE", "CaloHypo_E19", "CaloHypo_Hcal2Ecal", "CaloHypo_PrsE19", "CaloHypo_PrsE49", "CaloHypo_Spread", "CaloHypo_PrsE4Max", "CaloHypo_HypoPrsM", "CaloHypo_HypoSpdM" }; + + // sanity checks + if (theInputVars.size() <= 0) { + std::cout << "Problem in class \"" << fClassName << "\": empty input vector" << std::endl; + fStatusIsClean = false; + } + + if (theInputVars.size() != fNvars) { + std::cout << "Problem in class \"" << fClassName << "\": mismatch in number of input values: " + << theInputVars.size() << " != " << fNvars << std::endl; + fStatusIsClean = false; + } + + // validate input variables + for (size_t ivar = 0; ivar < theInputVars.size(); ivar++) { + if (theInputVars[ivar] != inputVars[ivar]) { + std::cout << "Problem in class \"" << fClassName << "\": mismatch in input variable names" << std::endl + << " for variable [" << ivar << "]: " << theInputVars[ivar].c_str() << " != " << inputVars[ivar] << std::endl; + fStatusIsClean = false; + } + } + + // initialize min and max vectors (for normalisation) + fVmin[0] = -1; + fVmax[0] = 1; + fVmin[1] = -1; + fVmax[1] = 1; + fVmin[2] = -1; + fVmax[2] = 1; + fVmin[3] = -1; + fVmax[3] = 1; + fVmin[4] = -1; + fVmax[4] = 1; + fVmin[5] = -1; + fVmax[5] = 1; + fVmin[6] = -1; + fVmax[6] = 1; + fVmin[7] = -1; + fVmax[7] = 1; + fVmin[8] = -1; + fVmax[8] = 1; + fVmin[9] = -1; + fVmax[9] = 1; + + // initialize input variable types + fType[0] = 'F'; + fType[1] = 'F'; + fType[2] = 'F'; + fType[3] = 'F'; + fType[4] = 'F'; + fType[5] = 'F'; + fType[6] = 'F'; + fType[7] = 'F'; + fType[8] = 'F'; + fType[9] = 'F'; + + // initialize constants + Initialize(); + + // initialize transformation + InitTransform(); + } + + // destructor + virtual ~ReadMLPE() { + Clear(); // method-specific + } + + // the classifier response + // "inputValues" is a vector of input values in the same order as the + // variables given to the constructor + double GetMvaValue( const std::vector<double>& inputValues ) const override; + + private: + + // method-specific destructor + void Clear(); + + // input variable transformation + + double fMin_1[3][10]; + double fMax_1[3][10]; + void InitTransform_1(); + void Transform_1( std::vector<double> & iv, int sigOrBgd ) const; + void InitTransform(); + void Transform( std::vector<double> & iv, int sigOrBgd ) const; + + // common member variables + const char* fClassName; + + const size_t fNvars; + size_t GetNvar() const { return fNvars; } + char GetType( int ivar ) const { return fType[ivar]; } + + // normalisation of input variables + const bool fIsNormalised; + bool IsNormalised() const { return fIsNormalised; } + double fVmin[10]; + double fVmax[10]; + double NormVariable( double x, double xmin, double xmax ) const { + // normalise to output range: [-1, 1] + return 2*(x - xmin)/(xmax - xmin) - 1.0; + } + + // type of input variable: 'F' or 'I' + char fType[10]; + + // initialize internal variables + void Initialize(); + double GetMvaValue__( const std::vector<double>& inputValues ) const; + + // private members (method specific) + + double ActivationFnc(double x) const; + double OutputActivationFnc(double x) const; + + int fLayers; + int fLayerSize[3]; + double fWeightMatrix0to1[16][11]; // weight matrix from layer 0 to 1 + double fWeightMatrix1to2[1][16]; // weight matrix from layer 1 to 2 + + double * fWeights[3]; +}; + +inline void ReadMLPE::Initialize() +{ + // build network structure + fLayers = 3; + fLayerSize[0] = 11; fWeights[0] = new double[11]; + fLayerSize[1] = 16; fWeights[1] = new double[16]; + fLayerSize[2] = 1; fWeights[2] = new double[1]; + // weight matrix from layer 0 to 1 + fWeightMatrix0to1[0][0] = -1.45648454058841; + fWeightMatrix0to1[1][0] = 13.5275343120003; + fWeightMatrix0to1[2][0] = 4.50157418654813; + fWeightMatrix0to1[3][0] = 0.248117194505925; + fWeightMatrix0to1[4][0] = -30.1607689733541; + fWeightMatrix0to1[5][0] = 0.207887274771161; + fWeightMatrix0to1[6][0] = -0.0270888143896361; + fWeightMatrix0to1[7][0] = 3.28884565633882; + fWeightMatrix0to1[8][0] = 0.341967140968008; + fWeightMatrix0to1[9][0] = -0.142593815083237; + fWeightMatrix0to1[10][0] = -0.0398619549131968; + fWeightMatrix0to1[11][0] = -0.0750336597813799; + fWeightMatrix0to1[12][0] = 0.0766911890953704; + fWeightMatrix0to1[13][0] = 0.0672474082833836; + fWeightMatrix0to1[14][0] = 0.867241067793692; + fWeightMatrix0to1[0][1] = -2.83950347374737; + fWeightMatrix0to1[1][1] = -2.15380729271302; + fWeightMatrix0to1[2][1] = 2.04678520389349; + fWeightMatrix0to1[3][1] = -4.12111391036507; + fWeightMatrix0to1[4][1] = 0.0150863236492678; + fWeightMatrix0to1[5][1] = 0.428345073987202; + fWeightMatrix0to1[6][1] = 0.0463806424833402; + fWeightMatrix0to1[7][1] = 3.07927476648953; + fWeightMatrix0to1[8][1] = 1.84528694146504; + fWeightMatrix0to1[9][1] = 4.21001060729693; + fWeightMatrix0to1[10][1] = 0.125225768206075; + fWeightMatrix0to1[11][1] = -2.76188946518049; + fWeightMatrix0to1[12][1] = -0.0535014315276362; + fWeightMatrix0to1[13][1] = 0.516400284788415; + fWeightMatrix0to1[14][1] = -0.641365324376028; + fWeightMatrix0to1[0][2] = 3.59930023956898; + fWeightMatrix0to1[1][2] = 0.828955519329612; + fWeightMatrix0to1[2][2] = -2.47879580185701; + fWeightMatrix0to1[3][2] = -0.236590795083167; + fWeightMatrix0to1[4][2] = -1.50982763020608; + fWeightMatrix0to1[5][2] = 4.15818760208164; + fWeightMatrix0to1[6][2] = -8.64091589704802; + fWeightMatrix0to1[7][2] = -2.03854941931439; + fWeightMatrix0to1[8][2] = -3.80216517204669; + fWeightMatrix0to1[9][2] = 2.07074419257209; + fWeightMatrix0to1[10][2] = -0.112980128346248; + fWeightMatrix0to1[11][2] = -2.27781140020139; + fWeightMatrix0to1[12][2] = -2.20742895752195; + fWeightMatrix0to1[13][2] = 1.17918944322642; + fWeightMatrix0to1[14][2] = -0.34063209631861; + fWeightMatrix0to1[0][3] = -0.456676590112288; + fWeightMatrix0to1[1][3] = 9.23995430720942; + fWeightMatrix0to1[2][3] = 7.78707526858773; + fWeightMatrix0to1[3][3] = 3.10666992076248; + fWeightMatrix0to1[4][3] = 25.400657795185; + fWeightMatrix0to1[5][3] = 1.19475914402133; + fWeightMatrix0to1[6][3] = -10.259338117333; + fWeightMatrix0to1[7][3] = -2.8289776603478; + fWeightMatrix0to1[8][3] = -0.276544824251693; + fWeightMatrix0to1[9][3] = 0.636533773081394; + fWeightMatrix0to1[10][3] = 8.36317018745479; + fWeightMatrix0to1[11][3] = 0.0033823112840708; + fWeightMatrix0to1[12][3] = -6.47144575647071; + fWeightMatrix0to1[13][3] = -6.40138974070392; + fWeightMatrix0to1[14][3] = 0.303751818575856; + fWeightMatrix0to1[0][4] = -0.457668810659899; + fWeightMatrix0to1[1][4] = 0.0227435339391494; + fWeightMatrix0to1[2][4] = 0.211414374850054; + fWeightMatrix0to1[3][4] = 0.733620726547089; + fWeightMatrix0to1[4][4] = 0.261596419101059; + fWeightMatrix0to1[5][4] = -0.717768402421295; + fWeightMatrix0to1[6][4] = 0.266747237202821; + fWeightMatrix0to1[7][4] = -0.415143840087982; + fWeightMatrix0to1[8][4] = 4.02900893008418; + fWeightMatrix0to1[9][4] = -0.314682275367909; + fWeightMatrix0to1[10][4] = -0.0307347748362473; + fWeightMatrix0to1[11][4] = 0.613657242423933; + fWeightMatrix0to1[12][4] = 1.54201548560833; + fWeightMatrix0to1[13][4] = -0.362297119846357; + fWeightMatrix0to1[14][4] = 0.892655907466491; + fWeightMatrix0to1[0][5] = 0.386851226624331; + fWeightMatrix0to1[1][5] = -0.393755454843198; + fWeightMatrix0to1[2][5] = -3.65324036626828; + fWeightMatrix0to1[3][5] = -2.19060232755643; + fWeightMatrix0to1[4][5] = -0.22524696359375; + fWeightMatrix0to1[5][5] = 1.36257093161029; + fWeightMatrix0to1[6][5] = 0.363400888976796; + fWeightMatrix0to1[7][5] = -0.327091014001851; + fWeightMatrix0to1[8][5] = -5.82025096621046; + fWeightMatrix0to1[9][5] = -0.0316361303312077; + fWeightMatrix0to1[10][5] = -0.11716442899143; + fWeightMatrix0to1[11][5] = 1.33146796426964; + fWeightMatrix0to1[12][5] = -0.529955608822344; + fWeightMatrix0to1[13][5] = 0.123392969661865; + fWeightMatrix0to1[14][5] = -0.688495531727211; + fWeightMatrix0to1[0][6] = 2.37511639017605; + fWeightMatrix0to1[1][6] = 13.8495115369364; + fWeightMatrix0to1[2][6] = -7.11038514530497; + fWeightMatrix0to1[3][6] = 1.57600408446741; + fWeightMatrix0to1[4][6] = -0.305469633566612; + fWeightMatrix0to1[5][6] = -0.802970329702063; + fWeightMatrix0to1[6][6] = 7.80532583827627; + fWeightMatrix0to1[7][6] = -27.3313128479119; + fWeightMatrix0to1[8][6] = -4.11021126234451; + fWeightMatrix0to1[9][6] = -18.9906582510047; + fWeightMatrix0to1[10][6] = 0.0752865468142167; + fWeightMatrix0to1[11][6] = -1.00673535273197; + fWeightMatrix0to1[12][6] = 5.70715403491534; + fWeightMatrix0to1[13][6] = 0.0661267698956959; + fWeightMatrix0to1[14][6] = 0.117595918123508; + fWeightMatrix0to1[0][7] = 7.18849787403715; + fWeightMatrix0to1[1][7] = 3.01783645520403; + fWeightMatrix0to1[2][7] = -8.01492216503647; + fWeightMatrix0to1[3][7] = -3.52555327456571; + fWeightMatrix0to1[4][7] = -2.13682500505441; + fWeightMatrix0to1[5][7] = -1.3873824489972; + fWeightMatrix0to1[6][7] = -1.32329585761102; + fWeightMatrix0to1[7][7] = 8.33522721197895; + fWeightMatrix0to1[8][7] = -2.95536416620716; + fWeightMatrix0to1[9][7] = -17.8822135849987; + fWeightMatrix0to1[10][7] = 1.01359329792805; + fWeightMatrix0to1[11][7] = -1.23283825442966; + fWeightMatrix0to1[12][7] = -0.24986091785677; + fWeightMatrix0to1[13][7] = -25.2043259727962; + fWeightMatrix0to1[14][7] = 0.971731397100306; + fWeightMatrix0to1[0][8] = -1.15525751237527; + fWeightMatrix0to1[1][8] = -0.446772573082124; + fWeightMatrix0to1[2][8] = 1.43962517859237; + fWeightMatrix0to1[3][8] = 0.163589949982915; + fWeightMatrix0to1[4][8] = -0.284672904616579; + fWeightMatrix0to1[5][8] = 0.157955132004244; + fWeightMatrix0to1[6][8] = 0.249634201604772; + fWeightMatrix0to1[7][8] = -1.25578487906979; + fWeightMatrix0to1[8][8] = -0.193703455708801; + fWeightMatrix0to1[9][8] = 0.398145692537802; + fWeightMatrix0to1[10][8] = 0.358898792890607; + fWeightMatrix0to1[11][8] = 2.94684386609079; + fWeightMatrix0to1[12][8] = -1.45650642135418; + fWeightMatrix0to1[13][8] = -1.0747199316049; + fWeightMatrix0to1[14][8] = -1.23091320072982; + fWeightMatrix0to1[0][9] = 5.52742374052167; + fWeightMatrix0to1[1][9] = 0.331953730686133; + fWeightMatrix0to1[2][9] = -19.5847265608038; + fWeightMatrix0to1[3][9] = -1.53913124664622; + fWeightMatrix0to1[4][9] = 0.215609305342047; + fWeightMatrix0to1[5][9] = -0.608411498454232; + fWeightMatrix0to1[6][9] = -0.430741226777065; + fWeightMatrix0to1[7][9] = 2.14822277825618; + fWeightMatrix0to1[8][9] = -0.0258283278933676; + fWeightMatrix0to1[9][9] = 0.146374631346389; + fWeightMatrix0to1[10][9] = 15.6754813951346; + fWeightMatrix0to1[11][9] = -0.135240317838916; + fWeightMatrix0to1[12][9] = -0.0996438883507816; + fWeightMatrix0to1[13][9] = 0.420040389884772; + fWeightMatrix0to1[14][9] = -0.0954172987569679; + fWeightMatrix0to1[0][10] = 7.57622222724628; + fWeightMatrix0to1[1][10] = 10.3762954958289; + fWeightMatrix0to1[2][10] = -11.5886090386582; + fWeightMatrix0to1[3][10] = -1.68832794007581; + fWeightMatrix0to1[4][10] = -7.04481172830748; + fWeightMatrix0to1[5][10] = 0.277012281276143; + fWeightMatrix0to1[6][10] = -4.61480527480798; + fWeightMatrix0to1[7][10] = -14.6265242510637; + fWeightMatrix0to1[8][10] = 3.20790832876608; + fWeightMatrix0to1[9][10] = -29.867543619819; + fWeightMatrix0to1[10][10] = 25.5515399649744; + fWeightMatrix0to1[11][10] = -3.56288755880943; + fWeightMatrix0to1[12][10] = -2.59069026666014; + fWeightMatrix0to1[13][10] = -31.7144780979234; + fWeightMatrix0to1[14][10] = 2.02367723120475; + // weight matrix from layer 1 to 2 + fWeightMatrix1to2[0][0] = -0.212000262813969; + fWeightMatrix1to2[0][1] = -0.927630312796793; + fWeightMatrix1to2[0][2] = 0.224665001966; + fWeightMatrix1to2[0][3] = 0.464526112961554; + fWeightMatrix1to2[0][4] = -0.401309586628313; + fWeightMatrix1to2[0][5] = 0.647264786628303; + fWeightMatrix1to2[0][6] = 0.720374144356743; + fWeightMatrix1to2[0][7] = 0.529024374814799; + fWeightMatrix1to2[0][8] = 0.448318829129643; + fWeightMatrix1to2[0][9] = 0.593470222390118; + fWeightMatrix1to2[0][10] = -3.30389673548254; + fWeightMatrix1to2[0][11] = 0.514169636701892; + fWeightMatrix1to2[0][12] = 0.424253407230348; + fWeightMatrix1to2[0][13] = 2.90636527932807; + fWeightMatrix1to2[0][14] = -0.300066009969093; + fWeightMatrix1to2[0][15] = 3.9644881274639; +} + +inline double ReadMLPE::GetMvaValue__( const std::vector<double>& inputValues ) const +{ + if (inputValues.size() != (unsigned int)fLayerSize[0]-1) { + std::cout << "Input vector needs to be of size " << fLayerSize[0]-1 << std::endl; + return 0; + } + + for (int l=0; l<fLayers; l++) + for (int i=0; i<fLayerSize[l]; i++) fWeights[l][i]=0; + + for (int l=0; l<fLayers-1; l++) + fWeights[l][fLayerSize[l]-1]=1; + + for (int i=0; i<fLayerSize[0]-1; i++) + fWeights[0][i]=inputValues[i]; + + // layer 0 to 1 + for (int o=0; o<fLayerSize[1]-1; o++) { + for (int i=0; i<fLayerSize[0]; i++) { + double inputVal = fWeightMatrix0to1[o][i] * fWeights[0][i]; + fWeights[1][o] += inputVal; + } + fWeights[1][o] = ActivationFnc(fWeights[1][o]); + } + // layer 1 to 2 + for (int o=0; o<fLayerSize[2]; o++) { + for (int i=0; i<fLayerSize[1]; i++) { + double inputVal = fWeightMatrix1to2[o][i] * fWeights[1][i]; + fWeights[2][o] += inputVal; + } + fWeights[2][o] = OutputActivationFnc(fWeights[2][o]); + } + + return fWeights[2][0]; +} + +double ReadMLPE::ActivationFnc(double x) const { + // hyperbolic tan + return tanh(x); +} +double ReadMLPE::OutputActivationFnc(double x) const { + // sigmoid + return 1.0/(1.0+exp(-x)); +} + +// Clean up +inline void ReadMLPE::Clear() +{ + // nothing to clear +} + inline double ReadMLPE::GetMvaValue( const std::vector<double>& inputValues ) const + { + // classifier response value + double retval = 0; + + // classifier response, sanity check first + if (!IsStatusClean()) { + std::cout << "Problem in class \"" << fClassName << "\": cannot return classifier response" + << " because status is dirty" << std::endl; + retval = 0; + } + else { + if (IsNormalised()) { + // normalise variables + std::vector<double> iV; + int ivar = 0; + for (std::vector<double>::const_iterator varIt = inputValues.begin(); + varIt != inputValues.end(); varIt++, ivar++) { + iV.push_back(NormVariable( *varIt, fVmin[ivar], fVmax[ivar] )); + } + Transform( iV, -1 ); + retval = GetMvaValue__( iV ); + } + else { + std::vector<double> iV; + int ivar = 0; + for (std::vector<double>::const_iterator varIt = inputValues.begin(); + varIt != inputValues.end(); varIt++, ivar++) { + iV.push_back(*varIt); + } + Transform( iV, -1 ); + retval = GetMvaValue__( iV ); + } + } + + return retval; + } + +//_______________________________________________________________________ +inline void ReadMLPE::InitTransform_1() +{ + // Normalization transformation, initialisation + fMin_1[0][0] = 0; + fMax_1[0][0] = 9999; + fMin_1[1][0] = 5.03054889123e-06; + fMax_1[1][0] = 9999; + fMin_1[2][0] = 0; + fMax_1[2][0] = 9999; + fMin_1[0][1] = 0; + fMax_1[0][1] = 280.579986572; + fMin_1[1][1] = 0; + fMax_1[1][1] = 280.579986572; + fMin_1[2][1] = 0; + fMax_1[2][1] = 280.579986572; + fMin_1[0][2] = 0; + fMax_1[0][2] = 1.73788714409; + fMin_1[1][2] = 0.140638813376; + fMax_1[1][2] = 1.41030442715; + fMin_1[2][2] = 0; + fMax_1[2][2] = 1.73788714409; + fMin_1[0][3] = 0; + fMax_1[0][3] = 41.9832572937; + fMin_1[1][3] = 0; + fMax_1[1][3] = 94.6786651611; + fMin_1[2][3] = 0; + fMax_1[2][3] = 94.6786651611; + fMin_1[0][4] = 0; + fMax_1[0][4] = 1; + fMin_1[1][4] = 0; + fMax_1[1][4] = 1; + fMin_1[2][4] = 0; + fMax_1[2][4] = 1; + fMin_1[0][5] = 0; + fMax_1[0][5] = 1; + fMin_1[1][5] = 0; + fMax_1[1][5] = 1; + fMin_1[2][5] = 0; + fMax_1[2][5] = 1; + fMin_1[0][6] = 0; + fMax_1[0][6] = 64433.078125; + fMin_1[1][6] = 165.730712891; + fMax_1[1][6] = 52884.8945312; + fMin_1[2][6] = 0; + fMax_1[2][6] = 64433.078125; + fMin_1[0][7] = 0; + fMax_1[0][7] = 853.807983398; + fMin_1[1][7] = 0; + fMax_1[1][7] = 955.837036133; + fMin_1[2][7] = 0; + fMax_1[2][7] = 955.837036133; + fMin_1[0][8] = 0; + fMax_1[0][8] = 10; + fMin_1[1][8] = 0; + fMax_1[1][8] = 9; + fMin_1[2][8] = 0; + fMax_1[2][8] = 10; + fMin_1[0][9] = 0; + fMax_1[0][9] = 9; + fMin_1[1][9] = 0; + fMax_1[1][9] = 9; + fMin_1[2][9] = 0; + fMax_1[2][9] = 9; +} + +//_______________________________________________________________________ +inline void ReadMLPE::Transform_1( std::vector<double>& iv, int cls) const +{ + // Normalization transformation + if (cls < 0 || cls > 2) { + if (2 > 1 ) cls = 2; + else cls = 2; + } + const int nVar = 10; + + // get indices of used variables + + // define the indices of the variables which are transformed by this transformation + std::vector<int> indicesGet; + std::vector<int> indicesPut; + + indicesGet.push_back( 0); + indicesGet.push_back( 1); + indicesGet.push_back( 2); + indicesGet.push_back( 3); + indicesGet.push_back( 4); + indicesGet.push_back( 5); + indicesGet.push_back( 6); + indicesGet.push_back( 7); + indicesGet.push_back( 8); + indicesGet.push_back( 9); + indicesPut.push_back( 0); + indicesPut.push_back( 1); + indicesPut.push_back( 2); + indicesPut.push_back( 3); + indicesPut.push_back( 4); + indicesPut.push_back( 5); + indicesPut.push_back( 6); + indicesPut.push_back( 7); + indicesPut.push_back( 8); + indicesPut.push_back( 9); + + std::vector<double> dv(nVar); + for (int ivar=0; ivar<nVar; ivar++) dv[ivar] = iv[indicesGet.at(ivar)]; + for (int ivar=0;ivar<10;ivar++) { + double offset = fMin_1[cls][ivar]; + double scale = 1.0/(fMax_1[cls][ivar]-fMin_1[cls][ivar]); + iv[indicesPut.at(ivar)] = (dv[ivar]-offset)*scale * 2 - 1; + } +} + +//_______________________________________________________________________ +inline void ReadMLPE::InitTransform() +{ + InitTransform_1(); +} + +//_______________________________________________________________________ +inline void ReadMLPE::Transform( std::vector<double>& iv, int sigOrBgd ) const +{ + Transform_1( iv, sigOrBgd ); +} diff --git a/CaloFuture/CaloFutureTools/src/TMV_MLP_H.C b/CaloFuture/CaloFutureTools/src/TMV_MLP_H.C new file mode 100644 index 0000000000000000000000000000000000000000..ccbff1f4e8380c7c9a94f01d30a27b69321e2e8e --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/TMV_MLP_H.C @@ -0,0 +1,645 @@ +// Class: ReadMLPH +// Automatically generated by MethodBase::MakeClass +// + +/* configuration options ===================================================== + +#GEN -*-*-*-*-*-*-*-*-*-*-*- general info -*-*-*-*-*-*-*-*-*-*-*- + +Method : MLP::MLP +TMVA Release : 4.1.4 [262404] +ROOT Release : 5.34/05 [336389] +Creator : hoballah +Date : Thu Jul 4 13:08:41 2013 +Host : Linux lxbuild175.cern.ch 2.6.18-308.4.1.el5 #1 SMP Wed Apr 18 16:26:27 CEST 2012 x86_64 x86_64 x86_64 GNU/Linux +Dir : /users/divers/lhcb/hoballah/December2012/B2KstG_ana/TMVA-v4.1.2/test/BDTs_PhotonID_new_var/train_test_noGnoPnoE +Training events: 3902103 +Analysis type : [Classification] + + +#OPT -*-*-*-*-*-*-*-*-*-*-*-*- options -*-*-*-*-*-*-*-*-*-*-*-*- + +# Set by User: +NCycles: "750" [Number of training cycles] +HiddenLayers: "N+5" [Specification of hidden layer architecture] +NeuronType: "tanh" [Neuron activation function type] +EstimatorType: "CE" [MSE (Mean Square Estimator) for Gaussian Likelihood or CE(Cross-Entropy) for Bernoulli Likelihood] +V: "False" [Verbose output (short form of "VerbosityLevel" below - overrides the latter one)] +VarTransform: "N" [List of variable transformations performed before training, e.g., "D_Background,P_Signal,G,N_AllClasses" for: "Decorrelation, PCA-transformation, Gaussianisation, Normalisation, each for the given class of events ('AllClasses' denotes all events of all classes, if no class indication is given, 'All' is assumed)"] +H: "True" [Print method-specific help message] +TrainingMethod: "BP" [Train with Back-Propagation (BP), BFGS Algorithm (BFGS), or Genetic Algorithm (GA - slower and worse)] +TestRate: "5" [Test for overtraining performed at each #th epochs] +UseRegulator: "False" [Use regulator to avoid over-training] +# Default: +RandomSeed: "1" [Random seed for initial synapse weights (0 means unique seed for each run; default value '1')] +NeuronInputType: "sum" [Neuron input function type] +VerbosityLevel: "Default" [Verbosity level] +CreateMVAPdfs: "False" [Create PDFs for classifier outputs (signal and background)] +IgnoreNegWeightsInTraining: "False" [Events with negative weights are ignored in the training (but are included for testing and performance evaluation)] +LearningRate: "2.000000e-02" [ANN learning rate parameter] +DecayRate: "1.000000e-02" [Decay rate for learning parameter] +EpochMonitoring: "False" [Provide epoch-wise monitoring plots according to TestRate (caution: causes big ROOT output file!)] +Sampling: "1.000000e+00" [Only 'Sampling' (randomly selected) events are trained each epoch] +SamplingEpoch: "1.000000e+00" [Sampling is used for the first 'SamplingEpoch' epochs, afterwards, all events are taken for training] +SamplingImportance: "1.000000e+00" [ The sampling weights of events in epochs which successful (worse estimator than before) are multiplied with SamplingImportance, else they are divided.] +SamplingTraining: "True" [The training sample is sampled] +SamplingTesting: "False" [The testing sample is sampled] +ResetStep: "50" [How often BFGS should reset history] +Tau: "3.000000e+00" [LineSearch "size step"] +BPMode: "sequential" [Back-propagation learning mode: sequential or batch] +BatchSize: "-1" [Batch size: number of events/batch, only set if in Batch Mode, -1 for BatchSize=number_of_events] +ConvergenceImprove: "1.000000e-30" [Minimum improvement which counts as improvement (<0 means automatic convergence check is turned off)] +ConvergenceTests: "-1" [Number of steps (without improvement) required for convergence (<0 means automatic convergence check is turned off)] +UpdateLimit: "10000" [Maximum times of regulator update] +CalculateErrors: "False" [Calculates inverse Hessian matrix at the end of the training to be able to calculate the uncertainties of an MVA value] +WeightRange: "1.000000e+00" [Take the events for the estimator calculations from small deviations from the desired value to large deviations only over the weight range] +## + + +#VAR -*-*-*-*-*-*-*-*-*-*-*-* variables *-*-*-*-*-*-*-*-*-*-*-*- + +NVar 10 +TMath::TanH(CaloHypo_ClusterMatch/2000) TMath_TanH_CaloHypo_ClusterMatch_D_2000_ TMath::TanH(CaloHypo_ClusterMatch/2000) CaloHypo_ClusterMatch units 'F' [0,0.999909102917] +CaloHypo_ToPrsE CaloHypo_ToPrsE CaloHypo_ToPrsE CaloHypo_ToPrsE units 'F' [0,280.579986572] +CaloHypo_E19 CaloHypo_E19 CaloHypo_E19 CaloHypo_E19 units 'F' [0,2.09823441505] +CaloHypo_Hcal2Ecal CaloHypo_Hcal2Ecal CaloHypo_Hcal2Ecal CaloHypo_Hcal2Ecal units 'F' [0,65.5371170044] +CaloHypo_PrsE19 CaloHypo_PrsE19 CaloHypo_PrsE19 CaloHypo_PrsE19 units 'F' [0,1] +CaloHypo_PrsE49 CaloHypo_PrsE49 CaloHypo_PrsE49 CaloHypo_PrsE49 units 'F' [0,1] +CaloHypo_Spread CaloHypo_Spread CaloHypo_Spread CaloHypo_Spread units 'F' [0,72525.4921875] +CaloHypo_PrsE4Max CaloHypo_PrsE4Max CaloHypo_PrsE4Max CaloHypo_PrsE4Max units 'F' [0,865.601623535] +CaloHypo_HypoPrsM CaloHypo_HypoPrsM CaloHypo_HypoPrsM CaloHypo_HypoPrsM units 'F' [0,10] +CaloHypo_HypoSpdM CaloHypo_HypoSpdM CaloHypo_HypoSpdM CaloHypo_HypoSpdM units 'F' [0,9] +NSpec 0 + + +============================================================================ */ + +#include <vector> +#include <cmath> +#include <string> +#include <iostream> + +#ifndef IClassifierReader__def +#define IClassifierReader__def + +class IClassifierReader { + + public: + + // constructor + IClassifierReader() : fStatusIsClean( true ) {} + virtual ~IClassifierReader() {} + + // return classifier response + virtual double GetMvaValue( const std::vector<double>& inputValues ) const = 0; + + // returns classifier status + bool IsStatusClean() const { return fStatusIsClean; } + + protected: + + bool fStatusIsClean; +}; + +#endif + +class ReadMLPH : public IClassifierReader { + + public: + + // constructor + ReadMLPH( std::vector<std::string>& theInputVars ) + : IClassifierReader(), + fClassName( "ReadMLPH" ), + fNvars( 10 ), + fIsNormalised( false ) + { + // the training input variables + const char* inputVars[] = { "TMath::TanH(CaloHypo_ClusterMatch/2000)", "CaloHypo_ToPrsE", "CaloHypo_E19", "CaloHypo_Hcal2Ecal", "CaloHypo_PrsE19", "CaloHypo_PrsE49", "CaloHypo_Spread", "CaloHypo_PrsE4Max", "CaloHypo_HypoPrsM", "CaloHypo_HypoSpdM" }; + + // sanity checks + if (theInputVars.size() <= 0) { + std::cout << "Problem in class \"" << fClassName << "\": empty input vector" << std::endl; + fStatusIsClean = false; + } + + if (theInputVars.size() != fNvars) { + std::cout << "Problem in class \"" << fClassName << "\": mismatch in number of input values: " + << theInputVars.size() << " != " << fNvars << std::endl; + fStatusIsClean = false; + } + + // validate input variables + for (size_t ivar = 0; ivar < theInputVars.size(); ivar++) { + if (theInputVars[ivar] != inputVars[ivar]) { + std::cout << "Problem in class \"" << fClassName << "\": mismatch in input variable names" << std::endl + << " for variable [" << ivar << "]: " << theInputVars[ivar].c_str() << " != " << inputVars[ivar] << std::endl; + fStatusIsClean = false; + } + } + + // initialize min and max vectors (for normalisation) + fVmin[0] = -1; + fVmax[0] = 1; + fVmin[1] = -1; + fVmax[1] = 1; + fVmin[2] = -1; + fVmax[2] = 1; + fVmin[3] = -1; + fVmax[3] = 1; + fVmin[4] = -1; + fVmax[4] = 1; + fVmin[5] = -1; + fVmax[5] = 1; + fVmin[6] = -1; + fVmax[6] = 1; + fVmin[7] = -1; + fVmax[7] = 1; + fVmin[8] = -1; + fVmax[8] = 1; + fVmin[9] = -1; + fVmax[9] = 1; + + // initialize input variable types + fType[0] = 'F'; + fType[1] = 'F'; + fType[2] = 'F'; + fType[3] = 'F'; + fType[4] = 'F'; + fType[5] = 'F'; + fType[6] = 'F'; + fType[7] = 'F'; + fType[8] = 'F'; + fType[9] = 'F'; + + // initialize constants + Initialize(); + + // initialize transformation + InitTransform(); + } + + // destructor + virtual ~ReadMLPH() { + Clear(); // method-specific + } + + // the classifier response + // "inputValues" is a vector of input values in the same order as the + // variables given to the constructor + double GetMvaValue( const std::vector<double>& inputValues ) const override; + + private: + + // method-specific destructor + void Clear(); + + // input variable transformation + + double fMin_1[3][10]; + double fMax_1[3][10]; + void InitTransform_1(); + void Transform_1( std::vector<double> & iv, int sigOrBgd ) const; + void InitTransform(); + void Transform( std::vector<double> & iv, int sigOrBgd ) const; + + // common member variables + const char* fClassName; + + const size_t fNvars; + size_t GetNvar() const { return fNvars; } + char GetType( int ivar ) const { return fType[ivar]; } + + // normalisation of input variables + const bool fIsNormalised; + bool IsNormalised() const { return fIsNormalised; } + double fVmin[10]; + double fVmax[10]; + double NormVariable( double x, double xmin, double xmax ) const { + // normalise to output range: [-1, 1] + return 2*(x - xmin)/(xmax - xmin) - 1.0; + } + + // type of input variable: 'F' or 'I' + char fType[10]; + + // initialize internal variables + void Initialize(); + double GetMvaValue__( const std::vector<double>& inputValues ) const; + + // private members (method specific) + + double ActivationFnc(double x) const; + double OutputActivationFnc(double x) const; + + int fLayers; + int fLayerSize[3]; + double fWeightMatrix0to1[16][11]; // weight matrix from layer 0 to 1 + double fWeightMatrix1to2[1][16]; // weight matrix from layer 1 to 2 + + double * fWeights[3]; +}; + +inline void ReadMLPH::Initialize() +{ + // build network structure + fLayers = 3; + fLayerSize[0] = 11; fWeights[0] = new double[11]; + fLayerSize[1] = 16; fWeights[1] = new double[16]; + fLayerSize[2] = 1; fWeights[2] = new double[1]; + // weight matrix from layer 0 to 1 + fWeightMatrix0to1[0][0] = 0.499791697169584; + fWeightMatrix0to1[1][0] = 0.0156937346966104; + fWeightMatrix0to1[2][0] = -0.369738840814315; + fWeightMatrix0to1[3][0] = 0.0484564925536612; + fWeightMatrix0to1[4][0] = -54.8356074198757; + fWeightMatrix0to1[5][0] = -0.0517232909505474; + fWeightMatrix0to1[6][0] = 0.269922710629987; + fWeightMatrix0to1[7][0] = 0.310507069564427; + fWeightMatrix0to1[8][0] = -0.31650124056531; + fWeightMatrix0to1[9][0] = -0.0452735528566461; + fWeightMatrix0to1[10][0] = -0.120523769099234; + fWeightMatrix0to1[11][0] = 0.046729826572728; + fWeightMatrix0to1[12][0] = -0.425197776585007; + fWeightMatrix0to1[13][0] = 0.139322438251145; + fWeightMatrix0to1[14][0] = 0.418958254799384; + fWeightMatrix0to1[0][1] = 4.07414005138199; + fWeightMatrix0to1[1][1] = -0.963589475727424; + fWeightMatrix0to1[2][1] = 20.1439661887903; + fWeightMatrix0to1[3][1] = 47.2015659342842; + fWeightMatrix0to1[4][1] = -0.496248377016052; + fWeightMatrix0to1[5][1] = -10.0462143213249; + fWeightMatrix0to1[6][1] = -3.07091129501229; + fWeightMatrix0to1[7][1] = -4.69426919570706; + fWeightMatrix0to1[8][1] = 0.70997164035673; + fWeightMatrix0to1[9][1] = 0.207635460256797; + fWeightMatrix0to1[10][1] = -1.3393513051332; + fWeightMatrix0to1[11][1] = 17.6758445921793; + fWeightMatrix0to1[12][1] = -10.138950676665; + fWeightMatrix0to1[13][1] = 0.431077189278333; + fWeightMatrix0to1[14][1] = 7.86583179460318; + fWeightMatrix0to1[0][2] = -0.145339067450411; + fWeightMatrix0to1[1][2] = 9.14181522823495; + fWeightMatrix0to1[2][2] = 0.203611887473639; + fWeightMatrix0to1[3][2] = -0.984192833381782; + fWeightMatrix0to1[4][2] = 1.15902596596526; + fWeightMatrix0to1[5][2] = 0.256278952248491; + fWeightMatrix0to1[6][2] = -2.46517971938777; + fWeightMatrix0to1[7][2] = 1.73605933033758; + fWeightMatrix0to1[8][2] = -8.02145443971624; + fWeightMatrix0to1[9][2] = 5.88010305867704; + fWeightMatrix0to1[10][2] = -0.713758870173103; + fWeightMatrix0to1[11][2] = 3.01072943804073; + fWeightMatrix0to1[12][2] = 0.0533090280598065; + fWeightMatrix0to1[13][2] = 0.475632001289167; + fWeightMatrix0to1[14][2] = -0.691552860221979; + fWeightMatrix0to1[0][3] = -3.25378744785488; + fWeightMatrix0to1[1][3] = -3.82910122715278; + fWeightMatrix0to1[2][3] = -25.0393347618618; + fWeightMatrix0to1[3][3] = -21.3553290079127; + fWeightMatrix0to1[4][3] = -37.9042574373599; + fWeightMatrix0to1[5][3] = 26.8912335875977; + fWeightMatrix0to1[6][3] = -5.84669874070948; + fWeightMatrix0to1[7][3] = 5.80638668429173; + fWeightMatrix0to1[8][3] = -1.98926386954341; + fWeightMatrix0to1[9][3] = 0.346537600846161; + fWeightMatrix0to1[10][3] = -1.15664693253549; + fWeightMatrix0to1[11][3] = -50.2125820478813; + fWeightMatrix0to1[12][3] = 6.5161456101295; + fWeightMatrix0to1[13][3] = -87.4184704653966; + fWeightMatrix0to1[14][3] = 2.26483551195462; + fWeightMatrix0to1[0][4] = -43.9690955900493; + fWeightMatrix0to1[1][4] = -0.00225311038605974; + fWeightMatrix0to1[2][4] = -0.304541297298231; + fWeightMatrix0to1[3][4] = 0.436386077708362; + fWeightMatrix0to1[4][4] = -0.0400773986570103; + fWeightMatrix0to1[5][4] = 0.262851086255125; + fWeightMatrix0to1[6][4] = 0.0494690293025466; + fWeightMatrix0to1[7][4] = -0.417767855824149; + fWeightMatrix0to1[8][4] = 0.0719745683747573; + fWeightMatrix0to1[9][4] = -0.557349960187241; + fWeightMatrix0to1[10][4] = -0.0697771327167742; + fWeightMatrix0to1[11][4] = -0.458996772175548; + fWeightMatrix0to1[12][4] = 2.54490124785549; + fWeightMatrix0to1[13][4] = 0.0160307456364636; + fWeightMatrix0to1[14][4] = -4.52218092140512; + fWeightMatrix0to1[0][5] = 0.0932681130451425; + fWeightMatrix0to1[1][5] = 0.175053708713905; + fWeightMatrix0to1[2][5] = -0.516198186699607; + fWeightMatrix0to1[3][5] = 0.180969941357541; + fWeightMatrix0to1[4][5] = 0.0609761788795187; + fWeightMatrix0to1[5][5] = 1.19584038070839; + fWeightMatrix0to1[6][5] = -0.759516914525722; + fWeightMatrix0to1[7][5] = 0.259604893242667; + fWeightMatrix0to1[8][5] = -0.552814273242625; + fWeightMatrix0to1[9][5] = -0.801307378689026; + fWeightMatrix0to1[10][5] = -0.512274728868527; + fWeightMatrix0to1[11][5] = 0.0391452676436715; + fWeightMatrix0to1[12][5] = -2.61761232216897; + fWeightMatrix0to1[13][5] = -0.030282187902499; + fWeightMatrix0to1[14][5] = -12.0787509544782; + fWeightMatrix0to1[0][6] = 32.7142611290786; + fWeightMatrix0to1[1][6] = 24.4537365543701; + fWeightMatrix0to1[2][6] = -0.852556540766488; + fWeightMatrix0to1[3][6] = 1.94432767673914; + fWeightMatrix0to1[4][6] = -1.10789872051392; + fWeightMatrix0to1[5][6] = -9.11148002855678; + fWeightMatrix0to1[6][6] = -3.60134573550497; + fWeightMatrix0to1[7][6] = 1.3476123210162; + fWeightMatrix0to1[8][6] = 5.76955728794814; + fWeightMatrix0to1[9][6] = -1.75770941068646; + fWeightMatrix0to1[10][6] = -0.258737946670854; + fWeightMatrix0to1[11][6] = -0.516104689067491; + fWeightMatrix0to1[12][6] = 0.867922930289291; + fWeightMatrix0to1[13][6] = -9.68509335114876; + fWeightMatrix0to1[14][6] = 0.162915322984271; + fWeightMatrix0to1[0][7] = 6.21848032482677; + fWeightMatrix0to1[1][7] = 2.43681171109174; + fWeightMatrix0to1[2][7] = 88.9538966037031; + fWeightMatrix0to1[3][7] = 2.2812617164849; + fWeightMatrix0to1[4][7] = 0.770377225014678; + fWeightMatrix0to1[5][7] = -1.37936902365579; + fWeightMatrix0to1[6][7] = 15.4919755959471; + fWeightMatrix0to1[7][7] = 27.2798331216326; + fWeightMatrix0to1[8][7] = -3.66140454553024; + fWeightMatrix0to1[9][7] = -4.94761965200881; + fWeightMatrix0to1[10][7] = 10.5910544025928; + fWeightMatrix0to1[11][7] = 26.6998445644734; + fWeightMatrix0to1[12][7] = 5.07993714680639; + fWeightMatrix0to1[13][7] = 0.568443695348981; + fWeightMatrix0to1[14][7] = -15.551498252802; + fWeightMatrix0to1[0][8] = -2.772411193299; + fWeightMatrix0to1[1][8] = -1.21555924450806; + fWeightMatrix0to1[2][8] = 0.36314443999594; + fWeightMatrix0to1[3][8] = 1.86934585858521; + fWeightMatrix0to1[4][8] = -0.33870914534062; + fWeightMatrix0to1[5][8] = 1.63913510921973; + fWeightMatrix0to1[6][8] = -0.940327258142375; + fWeightMatrix0to1[7][8] = -0.451351657789086; + fWeightMatrix0to1[8][8] = -0.802023741933935; + fWeightMatrix0to1[9][8] = 0.142686199701208; + fWeightMatrix0to1[10][8] = -0.0367383893101886; + fWeightMatrix0to1[11][8] = -1.47027790584272; + fWeightMatrix0to1[12][8] = -0.201137434248754; + fWeightMatrix0to1[13][8] = -0.0663662609421771; + fWeightMatrix0to1[14][8] = -9.2876284037384; + fWeightMatrix0to1[0][9] = -0.864965735173749; + fWeightMatrix0to1[1][9] = -0.0528064176926219; + fWeightMatrix0to1[2][9] = 0.470761720052231; + fWeightMatrix0to1[3][9] = -4.15161668908394; + fWeightMatrix0to1[4][9] = -0.313730029263097; + fWeightMatrix0to1[5][9] = 1.20854286758679; + fWeightMatrix0to1[6][9] = 0.959470209803684; + fWeightMatrix0to1[7][9] = -0.098415051066843; + fWeightMatrix0to1[8][9] = -0.338435591709211; + fWeightMatrix0to1[9][9] = 0.417338282361433; + fWeightMatrix0to1[10][9] = 21.5291749107274; + fWeightMatrix0to1[11][9] = 0.0625450793356017; + fWeightMatrix0to1[12][9] = -0.329884751871271; + fWeightMatrix0to1[13][9] = -0.269901631767981; + fWeightMatrix0to1[14][9] = 3.69925918255513; + fWeightMatrix0to1[0][10] = -8.36898295190574; + fWeightMatrix0to1[1][10] = 19.881856870813; + fWeightMatrix0to1[2][10] = 83.3644105603813; + fWeightMatrix0to1[3][10] = 25.7312740108938; + fWeightMatrix0to1[4][10] = -93.7775079760724; + fWeightMatrix0to1[5][10] = 8.9818733871343; + fWeightMatrix0to1[6][10] = 2.02986019149266; + fWeightMatrix0to1[7][10] = 29.7198945745259; + fWeightMatrix0to1[8][10] = -0.102145738286132; + fWeightMatrix0to1[9][10] = 0.43180772162006; + fWeightMatrix0to1[10][10] = 29.782079447293; + fWeightMatrix0to1[11][10] = -7.56631264091967; + fWeightMatrix0to1[12][10] = 4.01881367733937; + fWeightMatrix0to1[13][10] = -96.4690887810243; + fWeightMatrix0to1[14][10] = 7.4227530669183; + // weight matrix from layer 1 to 2 + fWeightMatrix1to2[0][0] = -0.477770126699446; + fWeightMatrix1to2[0][1] = -0.715648296234819; + fWeightMatrix1to2[0][2] = 1.42004899380744; + fWeightMatrix1to2[0][3] = 0.632464097448029; + fWeightMatrix1to2[0][4] = -3.61744120798587; + fWeightMatrix1to2[0][5] = -0.614858988134529; + fWeightMatrix1to2[0][6] = -0.718414740687336; + fWeightMatrix1to2[0][7] = 1.54245599661198; + fWeightMatrix1to2[0][8] = 1.7146854728026; + fWeightMatrix1to2[0][9] = 1.74904842763901; + fWeightMatrix1to2[0][10] = -2.86792997268243; + fWeightMatrix1to2[0][11] = 0.527811346593655; + fWeightMatrix1to2[0][12] = 0.715192997629513; + fWeightMatrix1to2[0][13] = 4.24688162871256; + fWeightMatrix1to2[0][14] = -0.360776619570363; + fWeightMatrix1to2[0][15] = -3.90430570227444; +} + +inline double ReadMLPH::GetMvaValue__( const std::vector<double>& inputValues ) const +{ + if (inputValues.size() != (unsigned int)fLayerSize[0]-1) { + std::cout << "Input vector needs to be of size " << fLayerSize[0]-1 << std::endl; + return 0; + } + + for (int l=0; l<fLayers; l++) + for (int i=0; i<fLayerSize[l]; i++) fWeights[l][i]=0; + + for (int l=0; l<fLayers-1; l++) + fWeights[l][fLayerSize[l]-1]=1; + + for (int i=0; i<fLayerSize[0]-1; i++) + fWeights[0][i]=inputValues[i]; + + // layer 0 to 1 + for (int o=0; o<fLayerSize[1]-1; o++) { + for (int i=0; i<fLayerSize[0]; i++) { + double inputVal = fWeightMatrix0to1[o][i] * fWeights[0][i]; + fWeights[1][o] += inputVal; + } + fWeights[1][o] = ActivationFnc(fWeights[1][o]); + } + // layer 1 to 2 + for (int o=0; o<fLayerSize[2]; o++) { + for (int i=0; i<fLayerSize[1]; i++) { + double inputVal = fWeightMatrix1to2[o][i] * fWeights[1][i]; + fWeights[2][o] += inputVal; + } + fWeights[2][o] = OutputActivationFnc(fWeights[2][o]); + } + + return fWeights[2][0]; +} + +double ReadMLPH::ActivationFnc(double x) const { + // hyperbolic tan + return tanh(x); +} +double ReadMLPH::OutputActivationFnc(double x) const { + // sigmoid + return 1.0/(1.0+exp(-x)); +} + +// Clean up +inline void ReadMLPH::Clear() +{ + // nothing to clear +} + inline double ReadMLPH::GetMvaValue( const std::vector<double>& inputValues ) const + { + // classifier response value + double retval = 0; + + // classifier response, sanity check first + if (!IsStatusClean()) { + std::cout << "Problem in class \"" << fClassName << "\": cannot return classifier response" + << " because status is dirty" << std::endl; + retval = 0; + } + else { + if (IsNormalised()) { + // normalise variables + std::vector<double> iV; + int ivar = 0; + for (std::vector<double>::const_iterator varIt = inputValues.begin(); + varIt != inputValues.end(); varIt++, ivar++) { + iV.push_back(NormVariable( *varIt, fVmin[ivar], fVmax[ivar] )); + } + Transform( iV, -1 ); + retval = GetMvaValue__( iV ); + } + else { + std::vector<double> iV; + int ivar = 0; + for (std::vector<double>::const_iterator varIt = inputValues.begin(); + varIt != inputValues.end(); varIt++, ivar++) { + iV.push_back(*varIt); + } + Transform( iV, -1 ); + retval = GetMvaValue__( iV ); + } + } + + return retval; + } + +//_______________________________________________________________________ +inline void ReadMLPH::InitTransform_1() +{ + // Normalization transformation, initialisation + fMin_1[0][0] = 0; + fMax_1[0][0] = 0.999909102917; + fMin_1[1][0] = 2.9958599157e-08; + fMax_1[1][0] = 0.999909102917; + fMin_1[2][0] = 0; + fMax_1[2][0] = 0.999909102917; + fMin_1[0][1] = 0; + fMax_1[0][1] = 280.579986572; + fMin_1[1][1] = 0; + fMax_1[1][1] = 280.579986572; + fMin_1[2][1] = 0; + fMax_1[2][1] = 280.579986572; + fMin_1[0][2] = 0; + fMax_1[0][2] = 1.73788714409; + fMin_1[1][2] = 0.115419611335; + fMax_1[1][2] = 2.09823441505; + fMin_1[2][2] = 0; + fMax_1[2][2] = 2.09823441505; + fMin_1[0][3] = 0; + fMax_1[0][3] = 41.9832572937; + fMin_1[1][3] = 0; + fMax_1[1][3] = 65.5371170044; + fMin_1[2][3] = 0; + fMax_1[2][3] = 65.5371170044; + fMin_1[0][4] = 0; + fMax_1[0][4] = 1; + fMin_1[1][4] = 0; + fMax_1[1][4] = 1; + fMin_1[2][4] = 0; + fMax_1[2][4] = 1; + fMin_1[0][5] = 0; + fMax_1[0][5] = 1; + fMin_1[1][5] = 0; + fMax_1[1][5] = 1; + fMin_1[2][5] = 0; + fMax_1[2][5] = 1; + fMin_1[0][6] = 0; + fMax_1[0][6] = 64433.078125; + fMin_1[1][6] = 155.35319519; + fMax_1[1][6] = 72525.4921875; + fMin_1[2][6] = 0; + fMax_1[2][6] = 72525.4921875; + fMin_1[0][7] = 0; + fMax_1[0][7] = 853.807983398; + fMin_1[1][7] = 0; + fMax_1[1][7] = 865.601623535; + fMin_1[2][7] = 0; + fMax_1[2][7] = 865.601623535; + fMin_1[0][8] = 0; + fMax_1[0][8] = 10; + fMin_1[1][8] = 0; + fMax_1[1][8] = 9; + fMin_1[2][8] = 0; + fMax_1[2][8] = 10; + fMin_1[0][9] = 0; + fMax_1[0][9] = 9; + fMin_1[1][9] = 0; + fMax_1[1][9] = 9; + fMin_1[2][9] = 0; + fMax_1[2][9] = 9; +} + +//_______________________________________________________________________ +inline void ReadMLPH::Transform_1( std::vector<double>& iv, int cls) const +{ + // Normalization transformation + if (cls < 0 || cls > 2) { + if (2 > 1 ) cls = 2; + else cls = 2; + } + const int nVar = 10; + + // get indices of used variables + + // define the indices of the variables which are transformed by this transformation + std::vector<int> indicesGet; + std::vector<int> indicesPut; + + indicesGet.push_back( 0); + indicesGet.push_back( 1); + indicesGet.push_back( 2); + indicesGet.push_back( 3); + indicesGet.push_back( 4); + indicesGet.push_back( 5); + indicesGet.push_back( 6); + indicesGet.push_back( 7); + indicesGet.push_back( 8); + indicesGet.push_back( 9); + indicesPut.push_back( 0); + indicesPut.push_back( 1); + indicesPut.push_back( 2); + indicesPut.push_back( 3); + indicesPut.push_back( 4); + indicesPut.push_back( 5); + indicesPut.push_back( 6); + indicesPut.push_back( 7); + indicesPut.push_back( 8); + indicesPut.push_back( 9); + + std::vector<double> dv(nVar); + for (int ivar=0; ivar<nVar; ivar++) dv[ivar] = iv[indicesGet.at(ivar)]; + for (int ivar=0;ivar<10;ivar++) { + double offset = fMin_1[cls][ivar]; + double scale = 1.0/(fMax_1[cls][ivar]-fMin_1[cls][ivar]); + iv[indicesPut.at(ivar)] = (dv[ivar]-offset)*scale * 2 - 1; + } +} + +//_______________________________________________________________________ +inline void ReadMLPH::InitTransform() +{ + InitTransform_1(); +} + +//_______________________________________________________________________ +inline void ReadMLPH::Transform( std::vector<double>& iv, int sigOrBgd ) const +{ + Transform_1( iv, sigOrBgd ); +} diff --git a/CaloFuture/CaloFutureTools/src/TMV_MLP_inner.C b/CaloFuture/CaloFutureTools/src/TMV_MLP_inner.C new file mode 100644 index 0000000000000000000000000000000000000000..6447cd6db58c3f5bfdd9ef329bdd68efd1cd7682 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/TMV_MLP_inner.C @@ -0,0 +1,817 @@ +// Class: ReadMLPInner +// Automatically generated by MethodBase::MakeClass +// + +/* configuration options ===================================================== + +#GEN -*-*-*-*-*-*-*-*-*-*-*- general info -*-*-*-*-*-*-*-*-*-*-*- + +Method : MLP::MLP +TMVA Release : 4.1.2 [262402] +ROOT Release : 5.30/00 [335360] +Creator : calvom +Date : Tue Nov 8 16:41:52 2011 +Host : Linux lxbuild148.cern.ch 2.6.18-194.26.1.el5 #1 SMP Wed Nov 10 09:45:46 CET 2010 x86_64 x86_64 x86_64 GNU/Linux +Dir : /afs/cern.ch/user/c/calvom/w0/GammaPi0/tmva_calib +Training events: 27236 +Analysis type : [Classification] + + +#OPT -*-*-*-*-*-*-*-*-*-*-*-*- options -*-*-*-*-*-*-*-*-*-*-*-*- + +# Set by User: +NCycles: "600" [Number of training cycles] +HiddenLayers: "N+5" [Specification of hidden layer architecture] +NeuronType: "tanh" [Neuron activation function type] +V: "False" [Verbose output (short form of "VerbosityLevel" below - overrides the latter one)] +VarTransform: "N" [List of variable transformations performed before training, e.g., "D_Background,P_Signal,G,N_AllClasses" for: "Decorrelation, PCA-transformation, Gaussianisation, Normalisation, each for the given class of events ('AllClasses' denotes all events of all classes, if no class indication is given, 'All' is assumed)"] +H: "True" [Print method-specific help message] +TestRate: "5" [Test for overtraining performed at each #th epochs] +# Default: +RandomSeed: "1" [Random seed for initial synapse weights (0 means unique seed for each run; default value '1')] +EstimatorType: "MSE" [MSE (Mean Square Estimator) for Gaussian Likelihood or CE(Cross-Entropy) for Bernoulli Likelihood] +NeuronInputType: "sum" [Neuron input function type] +VerbosityLevel: "Default" [Verbosity level] +CreateMVAPdfs: "False" [Create PDFs for classifier outputs (signal and background)] +IgnoreNegWeightsInTraining: "False" [Events with negative weights are ignored in the training (but are included for testing and performance evaluation)] +TrainingMethod: "BP" [Train with Back-Propagation (BP), BFGS Algorithm (BFGS), or Genetic Algorithm (GA - slower and worse)] +LearningRate: "2.000000e-02" [ANN learning rate parameter] +DecayRate: "1.000000e-02" [Decay rate for learning parameter] +EpochMonitoring: "False" [Provide epoch-wise monitoring plots according to TestRate (caution: causes big ROOT output file!)] +Sampling: "1.000000e+00" [Only 'Sampling' (randomly selected) events are trained each epoch] +SamplingEpoch: "1.000000e+00" [Sampling is used for the first 'SamplingEpoch' epochs, afterwards, all events are taken for training] +SamplingImportance: "1.000000e+00" [ The sampling weights of events in epochs which successful (worse estimator than before) are multiplied with SamplingImportance, else they are divided.] +SamplingTraining: "True" [The training sample is sampled] +SamplingTesting: "False" [The testing sample is sampled] +ResetStep: "50" [How often BFGS should reset history] +Tau: "3.000000e+00" [LineSearch "size step"] +BPMode: "sequential" [Back-propagation learning mode: sequential or batch] +BatchSize: "-1" [Batch size: number of events/batch, only set if in Batch Mode, -1 for BatchSize=number_of_events] +ConvergenceImprove: "1.000000e-30" [Minimum improvement which counts as improvement (<0 means automatic convergence check is turned off)] +ConvergenceTests: "-1" [Number of steps (without improvement) required for convergence (<0 means automatic convergence check is turned off)] +UseRegulator: "False" [Use regulator to avoid over-training] +UpdateLimit: "10000" [Maximum times of regulator update] +CalculateErrors: "False" [Calculates inverse Hessian matrix at the end of the training to be able to calculate the uncertainties of an MVA value] +WeightRange: "1.000000e+00" [Take the events for the estimator calculations from small deviations from the desired value to large deviations only over the weight range] +## + + +#VAR -*-*-*-*-*-*-*-*-*-*-*-* variables *-*-*-*-*-*-*-*-*-*-*-*- + +NVar 14 +fr2 fr2 fr2 fr2 'F' [256.407440186,5158.10546875] +fr2r4 fr2r4 fr2r4 fr2r4 'F' [0.340296119452,0.940254509449] +abs(asym) abs_asym_ abs(asym) abs(asym) 'F' [1.20151833016e-06,0.7383441329] +kappa kappa kappa kappa 'F' [0.00133013306186,0.77249121666] +Eseed/Ecl Eseed_D_Ecl Eseed/Ecl Eseed/Ecl 'F' [0.209150001407,0.919608473778] +(E2+Eseed)/Ecl _E2_P_Eseed__D_Ecl (E2+Eseed)/Ecl (E2+Eseed)/Ecl 'F' [0.399627387524,0.9744130373] +eSumPS>0?eMaxPS/eSumPS:0 eSumPS_0_eMaxPS_D_eSumPS:0 eSumPS>0?eMaxPS/eSumPS:0 eSumPS>0?eMaxPS/eSumPS:0 'F' [0,1] +eSumPS>0?e2ndPS/eSumPS:0 eSumPS_0_e2ndPS_D_eSumPS:0 eSumPS>0?e2ndPS/eSumPS:0 eSumPS>0?e2ndPS/eSumPS:0 'F' [0,0.496332526207] +r2PS r2PS r2PS r2PS 'F' [0,1.99933886528] +abs(asymPS) abs_asymPS_ abs(asymPS) abs(asymPS) 'F' [0,1] +multiPS multiPS multiPS multiPS 'F' [0,9] +multiPS15 multiPS15 multiPS15 multiPS15 'F' [0,6] +multiPS30 multiPS30 multiPS30 multiPS30 'F' [0,6] +multiPS45 multiPS45 multiPS45 multiPS45 'F' [0,5] +NSpec 0 + + +============================================================================ */ + +#include <vector> +#include <cmath> +#include <string> +#include <iostream> + +#ifndef IClassifierReader__def +#define IClassifierReader__def + +class IClassifierReader { + + public: + + // constructor + IClassifierReader() : fStatusIsClean( true ) {} + virtual ~IClassifierReader() {} + + // return classifier response + virtual double GetMvaValue( const std::vector<double>& inputValues ) const = 0; + + // returns classifier status + bool IsStatusClean() const { return fStatusIsClean; } + + protected: + + bool fStatusIsClean; +}; + +#endif + +class ReadMLPInner : public IClassifierReader { + + public: + + // constructor + ReadMLPInner( const std::vector<std::string>& theInputVars ) + : IClassifierReader(), + fClassName( "ReadMLPInner" ), + fNvars( 14 ), + fIsNormalised( false ) + { + // the training input variables + const char* inputVars[] = { "fr2", "fr2r4", "abs(asym)", "kappa", "Eseed/Ecl", "(E2+Eseed)/Ecl", "eSumPS>0?eMaxPS/eSumPS:0", "eSumPS>0?e2ndPS/eSumPS:0", "r2PS", "abs(asymPS)", "multiPS", "multiPS15", "multiPS30", "multiPS45" }; + + // sanity checks + if (theInputVars.size() <= 0) { + std::cout << "Problem in class \"" << fClassName << "\": empty input vector" << std::endl; + fStatusIsClean = false; + } + + if (theInputVars.size() != fNvars) { + std::cout << "Problem in class \"" << fClassName << "\": mismatch in number of input values: " + << theInputVars.size() << " != " << fNvars << std::endl; + fStatusIsClean = false; + } + + // validate input variables + for (size_t ivar = 0; ivar < theInputVars.size(); ivar++) { + if (theInputVars[ivar] != inputVars[ivar]) { + std::cout << "Problem in class \"" << fClassName << "\": mismatch in input variable names" << std::endl + << " for variable [" << ivar << "]: " << theInputVars[ivar].c_str() << " != " << inputVars[ivar] << std::endl; + fStatusIsClean = false; + } + } + + // initialize min and max vectors (for normalisation) + fVmin[0] = -1; + fVmax[0] = 1; + fVmin[1] = -1; + fVmax[1] = 1; + fVmin[2] = -1; + fVmax[2] = 1; + fVmin[3] = -1; + fVmax[3] = 0.99999988079071; + fVmin[4] = -1; + fVmax[4] = 1; + fVmin[5] = -1; + fVmax[5] = 1; + fVmin[6] = -1; + fVmax[6] = 1; + fVmin[7] = -1; + fVmax[7] = 1; + fVmin[8] = -1; + fVmax[8] = 1; + fVmin[9] = -1; + fVmax[9] = 1; + fVmin[10] = -1; + fVmax[10] = 1; + fVmin[11] = -1; + fVmax[11] = 1; + fVmin[12] = -1; + fVmax[12] = 1; + fVmin[13] = -1; + fVmax[13] = 1; + + // initialize input variable types + fType[0] = 'F'; + fType[1] = 'F'; + fType[2] = 'F'; + fType[3] = 'F'; + fType[4] = 'F'; + fType[5] = 'F'; + fType[6] = 'F'; + fType[7] = 'F'; + fType[8] = 'F'; + fType[9] = 'F'; + fType[10] = 'F'; + fType[11] = 'F'; + fType[12] = 'F'; + fType[13] = 'F'; + + // initialize constants + Initialize(); + + // initialize transformation + InitTransform(); + } + + // destructor + virtual ~ReadMLPInner() { + Clear(); // method-specific + } + + // the classifier response + // "inputValues" is a vector of input values in the same order as the + // variables given to the constructor + double GetMvaValue( const std::vector<double>& inputValues ) const override; + + private: + + // method-specific destructor + void Clear(); + + // input variable transformation + + double fMin_1[3][14]; + double fMax_1[3][14]; + void InitTransform_1(); + void Transform_1( std::vector<double> & iv, int sigOrBgd ) const; + void InitTransform(); + void Transform( std::vector<double> & iv, int sigOrBgd ) const; + + // common member variables + const char* fClassName; + + const size_t fNvars; + size_t GetNvar() const { return fNvars; } + char GetType( int ivar ) const { return fType[ivar]; } + + // normalisation of input variables + const bool fIsNormalised; + bool IsNormalised() const { return fIsNormalised; } + double fVmin[14]; + double fVmax[14]; + double NormVariable( double x, double xmin, double xmax ) const { + // normalise to output range: [-1, 1] + return 2*(x - xmin)/(xmax - xmin) - 1.0; + } + + // type of input variable: 'F' or 'I' + char fType[14]; + + // initialize internal variables + void Initialize(); + double GetMvaValue__( const std::vector<double>& inputValues ) const; + + // private members (method specific) + + double ActivationFnc(double x) const; + double OutputActivationFnc(double x) const; + + int fLayers; + int fLayerSize[3]; + double fWeightMatrix0to1[20][15]; // weight matrix from layer 0 to 1 + double fWeightMatrix1to2[1][20]; // weight matrix from layer 1 to 2 + + double * fWeights[3]; +}; + +inline void ReadMLPInner::Initialize() +{ + // build network structure + fLayers = 3; + fLayerSize[0] = 15; fWeights[0] = new double[15]; + fLayerSize[1] = 20; fWeights[1] = new double[20]; + fLayerSize[2] = 1; fWeights[2] = new double[1]; + // weight matrix from layer 0 to 1 + fWeightMatrix0to1[0][0] = -1.04290737527736; + fWeightMatrix0to1[1][0] = 2.70473526006312; + fWeightMatrix0to1[2][0] = 0.842724629892599; + fWeightMatrix0to1[3][0] = 2.26361521268781; + fWeightMatrix0to1[4][0] = -2.50890641104074; + fWeightMatrix0to1[5][0] = -0.846059312068215; + fWeightMatrix0to1[6][0] = -0.495414196093438; + fWeightMatrix0to1[7][0] = 2.64669025173505; + fWeightMatrix0to1[8][0] = -2.08512389745182; + fWeightMatrix0to1[9][0] = -1.32731998771946; + fWeightMatrix0to1[10][0] = -1.76369356867673; + fWeightMatrix0to1[11][0] = 0.0715211314613232; + fWeightMatrix0to1[12][0] = -0.369323557681417; + fWeightMatrix0to1[13][0] = -0.308104834419547; + fWeightMatrix0to1[14][0] = -1.46194920849862; + fWeightMatrix0to1[15][0] = 1.01388083906704; + fWeightMatrix0to1[16][0] = -0.688359487549371; + fWeightMatrix0to1[17][0] = 2.10005606938448; + fWeightMatrix0to1[18][0] = 0.21059023322323; + fWeightMatrix0to1[0][1] = 0.837073531436717; + fWeightMatrix0to1[1][1] = 0.0976385447684772; + fWeightMatrix0to1[2][1] = -1.64258403122012; + fWeightMatrix0to1[3][1] = 0.525861831096759; + fWeightMatrix0to1[4][1] = 0.687652967600606; + fWeightMatrix0to1[5][1] = -0.826070743174519; + fWeightMatrix0to1[6][1] = -0.232208661875282; + fWeightMatrix0to1[7][1] = 0.659261751404932; + fWeightMatrix0to1[8][1] = -1.57228734837995; + fWeightMatrix0to1[9][1] = -1.82014057521236; + fWeightMatrix0to1[10][1] = 0.384976761578452; + fWeightMatrix0to1[11][1] = 0.459553043196147; + fWeightMatrix0to1[12][1] = 1.27425198975868; + fWeightMatrix0to1[13][1] = -1.13086944167455; + fWeightMatrix0to1[14][1] = -2.96296349862317; + fWeightMatrix0to1[15][1] = -0.112078673860112; + fWeightMatrix0to1[16][1] = -0.364895039620327; + fWeightMatrix0to1[17][1] = -2.0433661174012; + fWeightMatrix0to1[18][1] = 1.54624548320321; + fWeightMatrix0to1[0][2] = -0.637671435862953; + fWeightMatrix0to1[1][2] = 0.397278940196906; + fWeightMatrix0to1[2][2] = 0.277972173520998; + fWeightMatrix0to1[3][2] = 1.31034307637501; + fWeightMatrix0to1[4][2] = 1.08237245822997; + fWeightMatrix0to1[5][2] = 1.92430164089826; + fWeightMatrix0to1[6][2] = -0.615430183398319; + fWeightMatrix0to1[7][2] = -0.575223577050631; + fWeightMatrix0to1[8][2] = 0.158409883281879; + fWeightMatrix0to1[9][2] = -0.178322855564784; + fWeightMatrix0to1[10][2] = 0.953159662758702; + fWeightMatrix0to1[11][2] = 1.58766160896782; + fWeightMatrix0to1[12][2] = 2.25712788264313; + fWeightMatrix0to1[13][2] = 2.38047728401168; + fWeightMatrix0to1[14][2] = -0.549580407122151; + fWeightMatrix0to1[15][2] = 1.05640851708416; + fWeightMatrix0to1[16][2] = -2.0559354676541; + fWeightMatrix0to1[17][2] = 0.0323101610937663; + fWeightMatrix0to1[18][2] = -0.892003791450972; + fWeightMatrix0to1[0][3] = -2.89424971334362; + fWeightMatrix0to1[1][3] = 1.26746721164734; + fWeightMatrix0to1[2][3] = -0.0762248316342091; + fWeightMatrix0to1[3][3] = -1.21441731817952; + fWeightMatrix0to1[4][3] = -0.250090311316658; + fWeightMatrix0to1[5][3] = -0.353695590021927; + fWeightMatrix0to1[6][3] = 0.566897065530219; + fWeightMatrix0to1[7][3] = 0.367598832532309; + fWeightMatrix0to1[8][3] = -0.97998644736544; + fWeightMatrix0to1[9][3] = -0.839734090224558; + fWeightMatrix0to1[10][3] = -1.13443817816697; + fWeightMatrix0to1[11][3] = 0.795613322993873; + fWeightMatrix0to1[12][3] = -0.36128332798357; + fWeightMatrix0to1[13][3] = 0.791435019948385; + fWeightMatrix0to1[14][3] = -0.972677060580533; + fWeightMatrix0to1[15][3] = 0.765038950589299; + fWeightMatrix0to1[16][3] = 0.78268350889215; + fWeightMatrix0to1[17][3] = 1.12945205131092; + fWeightMatrix0to1[18][3] = -0.445399279135853; + fWeightMatrix0to1[0][4] = -1.77770807762748; + fWeightMatrix0to1[1][4] = -0.632357676106347; + fWeightMatrix0to1[2][4] = 0.36317389912568; + fWeightMatrix0to1[3][4] = 0.894415041886562; + fWeightMatrix0to1[4][4] = 2.36637904519226; + fWeightMatrix0to1[5][4] = 1.16813909044691; + fWeightMatrix0to1[6][4] = 0.957092840127218; + fWeightMatrix0to1[7][4] = -1.30836798446254; + fWeightMatrix0to1[8][4] = -0.595420753901453; + fWeightMatrix0to1[9][4] = -0.614732883419485; + fWeightMatrix0to1[10][4] = 0.942790131176385; + fWeightMatrix0to1[11][4] = -1.02368950468983; + fWeightMatrix0to1[12][4] = -1.68076385296451; + fWeightMatrix0to1[13][4] = -1.23324912228085; + fWeightMatrix0to1[14][4] = 0.415592104701746; + fWeightMatrix0to1[15][4] = -0.17872879341687; + fWeightMatrix0to1[16][4] = 1.13361004021582; + fWeightMatrix0to1[17][4] = -1.20050470223068; + fWeightMatrix0to1[18][4] = -1.1104728542419; + fWeightMatrix0to1[0][5] = 2.05797225374773; + fWeightMatrix0to1[1][5] = -0.696162390135965; + fWeightMatrix0to1[2][5] = -2.21770021810581; + fWeightMatrix0to1[3][5] = -1.04718674389046; + fWeightMatrix0to1[4][5] = 0.862452877331307; + fWeightMatrix0to1[5][5] = -1.06419801692172; + fWeightMatrix0to1[6][5] = -1.76968728079571; + fWeightMatrix0to1[7][5] = -0.555996843115734; + fWeightMatrix0to1[8][5] = 1.18249132828029; + fWeightMatrix0to1[9][5] = -1.53431472191485; + fWeightMatrix0to1[10][5] = 1.57909174709495; + fWeightMatrix0to1[11][5] = -1.19669832089179; + fWeightMatrix0to1[12][5] = -1.29760121275024; + fWeightMatrix0to1[13][5] = 0.19270020308523; + fWeightMatrix0to1[14][5] = 1.24880029341451; + fWeightMatrix0to1[15][5] = -1.88188502955362; + fWeightMatrix0to1[16][5] = -0.159437524078109; + fWeightMatrix0to1[17][5] = 0.0348243191319361; + fWeightMatrix0to1[18][5] = 0.20743091300093; + fWeightMatrix0to1[0][6] = -0.764981614221069; + fWeightMatrix0to1[1][6] = -0.0788912101468469; + fWeightMatrix0to1[2][6] = 0.0831227210927517; + fWeightMatrix0to1[3][6] = -0.775775264233783; + fWeightMatrix0to1[4][6] = 0.39768218578583; + fWeightMatrix0to1[5][6] = -0.193922755794659; + fWeightMatrix0to1[6][6] = -1.58925719839167; + fWeightMatrix0to1[7][6] = -0.889817928434628; + fWeightMatrix0to1[8][6] = 0.649938955471886; + fWeightMatrix0to1[9][6] = 0.867709763850432; + fWeightMatrix0to1[10][6] = 0.740468306185537; + fWeightMatrix0to1[11][6] = -0.590596027104339; + fWeightMatrix0to1[12][6] = -0.533604230893194; + fWeightMatrix0to1[13][6] = 0.671730556997688; + fWeightMatrix0to1[14][6] = -0.449052784218705; + fWeightMatrix0to1[15][6] = 0.71912421638838; + fWeightMatrix0to1[16][6] = 0.423547719616505; + fWeightMatrix0to1[17][6] = -1.23294651339297; + fWeightMatrix0to1[18][6] = 0.722728624277078; + fWeightMatrix0to1[0][7] = -0.658192334225956; + fWeightMatrix0to1[1][7] = 0.196528618013865; + fWeightMatrix0to1[2][7] = 1.13680440873838; + fWeightMatrix0to1[3][7] = 1.20693801607716; + fWeightMatrix0to1[4][7] = -1.3096837025049; + fWeightMatrix0to1[5][7] = -0.37136771300458; + fWeightMatrix0to1[6][7] = 1.435180853539; + fWeightMatrix0to1[7][7] = 0.901601754691063; + fWeightMatrix0to1[8][7] = -0.25174077192635; + fWeightMatrix0to1[9][7] = -0.604725647208693; + fWeightMatrix0to1[10][7] = -0.16884086080176; + fWeightMatrix0to1[11][7] = -0.906755800255; + fWeightMatrix0to1[12][7] = 1.35317789869573; + fWeightMatrix0to1[13][7] = 0.174270227756606; + fWeightMatrix0to1[14][7] = -0.280830891638428; + fWeightMatrix0to1[15][7] = -0.362098577847321; + fWeightMatrix0to1[16][7] = 0.335214223040219; + fWeightMatrix0to1[17][7] = -0.702921687211048; + fWeightMatrix0to1[18][7] = 0.166031955217452; + fWeightMatrix0to1[0][8] = 0.91939746258453; + fWeightMatrix0to1[1][8] = -0.13387556855178; + fWeightMatrix0to1[2][8] = 0.43066585397933; + fWeightMatrix0to1[3][8] = 0.0811478903004244; + fWeightMatrix0to1[4][8] = 0.90799694626677; + fWeightMatrix0to1[5][8] = 0.384352609340622; + fWeightMatrix0to1[6][8] = 1.05363849430897; + fWeightMatrix0to1[7][8] = -1.45217522191468; + fWeightMatrix0to1[8][8] = 0.865684583886025; + fWeightMatrix0to1[9][8] = 1.00932821334351; + fWeightMatrix0to1[10][8] = 0.155860197767314; + fWeightMatrix0to1[11][8] = 1.10414192697408; + fWeightMatrix0to1[12][8] = 1.64353618478304; + fWeightMatrix0to1[13][8] = 0.388125070845243; + fWeightMatrix0to1[14][8] = 0.0693610841952537; + fWeightMatrix0to1[15][8] = 1.28650684566217; + fWeightMatrix0to1[16][8] = -1.32106134412902; + fWeightMatrix0to1[17][8] = 0.104715889241616; + fWeightMatrix0to1[18][8] = 1.34803140000267; + fWeightMatrix0to1[0][9] = 0.320934088411829; + fWeightMatrix0to1[1][9] = 0.0834251158725143; + fWeightMatrix0to1[2][9] = 1.07271749799617; + fWeightMatrix0to1[3][9] = 0.964961284465372; + fWeightMatrix0to1[4][9] = -1.14160729387509; + fWeightMatrix0to1[5][9] = 0.612322237162634; + fWeightMatrix0to1[6][9] = 0.376295371866361; + fWeightMatrix0to1[7][9] = 0.778169478111247; + fWeightMatrix0to1[8][9] = -0.10591272925161; + fWeightMatrix0to1[9][9] = -0.233317739206228; + fWeightMatrix0to1[10][9] = 0.533176446007596; + fWeightMatrix0to1[11][9] = 1.38047512736593; + fWeightMatrix0to1[12][9] = -0.792662013406803; + fWeightMatrix0to1[13][9] = -0.0448794496386986; + fWeightMatrix0to1[14][9] = -0.16388482687671; + fWeightMatrix0to1[15][9] = 0.13076205026299; + fWeightMatrix0to1[16][9] = 1.25466844492722; + fWeightMatrix0to1[17][9] = 0.398292697037867; + fWeightMatrix0to1[18][9] = -0.23951655977468; + fWeightMatrix0to1[0][10] = -0.614254353793099; + fWeightMatrix0to1[1][10] = 0.0992869101139523; + fWeightMatrix0to1[2][10] = 1.61730569546926; + fWeightMatrix0to1[3][10] = 1.26425380427585; + fWeightMatrix0to1[4][10] = -0.321855013094085; + fWeightMatrix0to1[5][10] = -0.304541636476265; + fWeightMatrix0to1[6][10] = -1.93469077724026; + fWeightMatrix0to1[7][10] = 0.694282106776582; + fWeightMatrix0to1[8][10] = -0.293506864969838; + fWeightMatrix0to1[9][10] = -0.747045982083812; + fWeightMatrix0to1[10][10] = -0.403618510687764; + fWeightMatrix0to1[11][10] = 0.465629196247161; + fWeightMatrix0to1[12][10] = 0.125535542687423; + fWeightMatrix0to1[13][10] = -0.696282568972736; + fWeightMatrix0to1[14][10] = -0.372381961976462; + fWeightMatrix0to1[15][10] = 0.489641588971278; + fWeightMatrix0to1[16][10] = -0.520374148494733; + fWeightMatrix0to1[17][10] = -0.156690025365887; + fWeightMatrix0to1[18][10] = 0.416977419039458; + fWeightMatrix0to1[0][11] = 0.531942145530533; + fWeightMatrix0to1[1][11] = 0.409193317682443; + fWeightMatrix0to1[2][11] = 0.609554237515943; + fWeightMatrix0to1[3][11] = -1.1461979146281; + fWeightMatrix0to1[4][11] = -0.929191100547892; + fWeightMatrix0to1[5][11] = 1.39878797426212; + fWeightMatrix0to1[6][11] = 1.29271120429798; + fWeightMatrix0to1[7][11] = 0.650842576125176; + fWeightMatrix0to1[8][11] = 0.490789613294808; + fWeightMatrix0to1[9][11] = 1.66405994659327; + fWeightMatrix0to1[10][11] = -1.56433357937701; + fWeightMatrix0to1[11][11] = -0.677257565580712; + fWeightMatrix0to1[12][11] = 0.356943018030898; + fWeightMatrix0to1[13][11] = -0.221601144251902; + fWeightMatrix0to1[14][11] = -0.441791343669387; + fWeightMatrix0to1[15][11] = 1.68219766495838; + fWeightMatrix0to1[16][11] = -0.911141573775065; + fWeightMatrix0to1[17][11] = 0.770791025979587; + fWeightMatrix0to1[18][11] = -0.608790648593897; + fWeightMatrix0to1[0][12] = -1.74063301540399; + fWeightMatrix0to1[1][12] = 0.52280179904318; + fWeightMatrix0to1[2][12] = 1.45741000134962; + fWeightMatrix0to1[3][12] = 0.811717591914303; + fWeightMatrix0to1[4][12] = 0.423631349618857; + fWeightMatrix0to1[5][12] = 0.442233458535246; + fWeightMatrix0to1[6][12] = 1.72245022080012; + fWeightMatrix0to1[7][12] = -0.155482463527143; + fWeightMatrix0to1[8][12] = 0.169078815586972; + fWeightMatrix0to1[9][12] = 0.0957820641921989; + fWeightMatrix0to1[10][12] = -1.51404378847068; + fWeightMatrix0to1[11][12] = -0.636428157748913; + fWeightMatrix0to1[12][12] = -1.06689847495217; + fWeightMatrix0to1[13][12] = 0.378085649705563; + fWeightMatrix0to1[14][12] = -0.363961181698494; + fWeightMatrix0to1[15][12] = -0.894073578739959; + fWeightMatrix0to1[16][12] = -1.99562899137367; + fWeightMatrix0to1[17][12] = 0.230784059961214; + fWeightMatrix0to1[18][12] = -0.910978195783922; + fWeightMatrix0to1[0][13] = -0.581029428272472; + fWeightMatrix0to1[1][13] = 0.396648153766494; + fWeightMatrix0to1[2][13] = 0.33856189243156; + fWeightMatrix0to1[3][13] = 0.694846470145189; + fWeightMatrix0to1[4][13] = -1.84211918628018; + fWeightMatrix0to1[5][13] = 0.395698508557705; + fWeightMatrix0to1[6][13] = 1.90696371770364; + fWeightMatrix0to1[7][13] = 0.858858159782207; + fWeightMatrix0to1[8][13] = -0.508233975106343; + fWeightMatrix0to1[9][13] = -1.525458318142; + fWeightMatrix0to1[10][13] = -1.32290040002494; + fWeightMatrix0to1[11][13] = -0.184942051859762; + fWeightMatrix0to1[12][13] = -0.820528765038721; + fWeightMatrix0to1[13][13] = 0.306878829145374; + fWeightMatrix0to1[14][13] = -0.0502141851753634; + fWeightMatrix0to1[15][13] = 2.09942361551934; + fWeightMatrix0to1[16][13] = -0.430310029954266; + fWeightMatrix0to1[17][13] = 0.76726047475096; + fWeightMatrix0to1[18][13] = -0.664806348367783; + fWeightMatrix0to1[0][14] = -2.3675555746175; + fWeightMatrix0to1[1][14] = 2.71805249000109; + fWeightMatrix0to1[2][14] = 0.167833726041457; + fWeightMatrix0to1[3][14] = -2.00895180390179; + fWeightMatrix0to1[4][14] = -0.236589279078717; + fWeightMatrix0to1[5][14] = 1.48854633506328; + fWeightMatrix0to1[6][14] = 0.925436530280765; + fWeightMatrix0to1[7][14] = -0.0484617956023451; + fWeightMatrix0to1[8][14] = -1.28694490057139; + fWeightMatrix0to1[9][14] = 0.455263024018376; + fWeightMatrix0to1[10][14] = 2.21527202105756; + fWeightMatrix0to1[11][14] = 0.179882944329227; + fWeightMatrix0to1[12][14] = -0.158021644420472; + fWeightMatrix0to1[13][14] = -0.412791984233319; + fWeightMatrix0to1[14][14] = 0.0848395939820601; + fWeightMatrix0to1[15][14] = -1.17233717764294; + fWeightMatrix0to1[16][14] = -0.995490564204621; + fWeightMatrix0to1[17][14] = -1.84487083160762; + fWeightMatrix0to1[18][14] = -1.39733709135126; + // weight matrix from layer 1 to 2 + fWeightMatrix1to2[0][0] = 0.12776681158065; + fWeightMatrix1to2[0][1] = -0.343909009882047; + fWeightMatrix1to2[0][2] = 0.169120833034602; + fWeightMatrix1to2[0][3] = -0.662219696453423; + fWeightMatrix1to2[0][4] = -0.287408263365878; + fWeightMatrix1to2[0][5] = -0.161420501035208; + fWeightMatrix1to2[0][6] = -0.0169827742543512; + fWeightMatrix1to2[0][7] = -0.496489571516043; + fWeightMatrix1to2[0][8] = 0.183344828615848; + fWeightMatrix1to2[0][9] = -0.091373308557532; + fWeightMatrix1to2[0][10] = -0.0497970968197627; + fWeightMatrix1to2[0][11] = 0.00744973924889008; + fWeightMatrix1to2[0][12] = 0.0216840381575276; + fWeightMatrix1to2[0][13] = -0.117687189532725; + fWeightMatrix1to2[0][14] = -0.510808312092356; + fWeightMatrix1to2[0][15] = -0.320428567141753; + fWeightMatrix1to2[0][16] = 0.00849073423000328; + fWeightMatrix1to2[0][17] = 0.416128149278602; + fWeightMatrix1to2[0][18] = -0.0863910437997606; + fWeightMatrix1to2[0][19] = 0.210750861731697; +} + +inline double ReadMLPInner::GetMvaValue__( const std::vector<double>& inputValues ) const +{ + if (inputValues.size() != (unsigned int)fLayerSize[0]-1) { + std::cout << "Input vector needs to be of size " << fLayerSize[0]-1 << std::endl; + return 0; + } + + for (int l=0; l<fLayers; l++) + for (int i=0; i<fLayerSize[l]; i++) fWeights[l][i]=0; + + for (int l=0; l<fLayers-1; l++) + fWeights[l][fLayerSize[l]-1]=1; + + for (int i=0; i<fLayerSize[0]-1; i++) + fWeights[0][i]=inputValues[i]; + + // layer 0 to 1 + for (int o=0; o<fLayerSize[1]-1; o++) { + for (int i=0; i<fLayerSize[0]; i++) { + double inputVal = fWeightMatrix0to1[o][i] * fWeights[0][i]; + fWeights[1][o] += inputVal; + } + fWeights[1][o] = ActivationFnc(fWeights[1][o]); + } + // layer 1 to 2 + for (int o=0; o<fLayerSize[2]; o++) { + for (int i=0; i<fLayerSize[1]; i++) { + double inputVal = fWeightMatrix1to2[o][i] * fWeights[1][i]; + fWeights[2][o] += inputVal; + } + fWeights[2][o] = OutputActivationFnc(fWeights[2][o]); + } + + return fWeights[2][0]; +} + +double ReadMLPInner::ActivationFnc(double x) const { + // hyperbolic tan + return tanh(x); +} +double ReadMLPInner::OutputActivationFnc(double x) const { + // identity + return x; +} + +// Clean up +inline void ReadMLPInner::Clear() +{ + // nothing to clear +} + inline double ReadMLPInner::GetMvaValue( const std::vector<double>& inputValues ) const + { + // classifier response value + double retval = 0; + + // classifier response, sanity check first + if (!IsStatusClean()) { + std::cout << "Problem in class \"" << fClassName << "\": cannot return classifier response" + << " because status is dirty" << std::endl; + retval = 0; + } + else { + if (IsNormalised()) { + // normalise variables + std::vector<double> iV; + int ivar = 0; + for (std::vector<double>::const_iterator varIt = inputValues.begin(); + varIt != inputValues.end(); varIt++, ivar++) { + iV.push_back(NormVariable( *varIt, fVmin[ivar], fVmax[ivar] )); + } + Transform( iV, -1 ); + retval = GetMvaValue__( iV ); + } + else { + std::vector<double> iV; + int ivar = 0; + for (std::vector<double>::const_iterator varIt = inputValues.begin(); + varIt != inputValues.end(); varIt++, ivar++) { + iV.push_back(*varIt); + } + Transform( iV, -1 ); + retval = GetMvaValue__( iV ); + } + } + + return retval; + } + +//_______________________________________________________________________ +inline void ReadMLPInner::InitTransform_1() +{ + // Normalization transformation, initialisation + fMin_1[0][0] = 256.407440186; + fMax_1[0][0] = 5158.10546875; + fMin_1[1][0] = 266.212738037; + fMax_1[1][0] = 3459.59375; + fMin_1[2][0] = 256.407440186; + fMax_1[2][0] = 5158.10546875; + fMin_1[0][1] = 0.340296119452; + fMax_1[0][1] = 0.940254509449; + fMin_1[1][1] = 0.423948228359; + fMax_1[1][1] = 0.930988788605; + fMin_1[2][1] = 0.340296119452; + fMax_1[2][1] = 0.940254509449; + fMin_1[0][2] = 1.20151833016e-06; + fMax_1[0][2] = 0.7383441329; + fMin_1[1][2] = 0.000120857454021; + fMax_1[1][2] = 0.687674760818; + fMin_1[2][2] = 1.20151833016e-06; + fMax_1[2][2] = 0.7383441329; + fMin_1[0][3] = 0.00158494454809; + fMax_1[0][3] = 0.77249121666; + fMin_1[1][3] = 0.00133013306186; + fMax_1[1][3] = 0.745648443699; + fMin_1[2][3] = 0.00133013306186; + fMax_1[2][3] = 0.77249121666; + fMin_1[0][4] = 0.261401534081; + fMax_1[0][4] = 0.919608473778; + fMin_1[1][4] = 0.209150001407; + fMax_1[1][4] = 0.898594379425; + fMin_1[2][4] = 0.209150001407; + fMax_1[2][4] = 0.919608473778; + fMin_1[0][5] = 0.514432489872; + fMax_1[0][5] = 0.9744130373; + fMin_1[1][5] = 0.399627387524; + fMax_1[1][5] = 0.962903857231; + fMin_1[2][5] = 0.399627387524; + fMax_1[2][5] = 0.9744130373; + fMin_1[0][6] = 0; + fMax_1[0][6] = 1; + fMin_1[1][6] = 0; + fMax_1[1][6] = 1; + fMin_1[2][6] = 0; + fMax_1[2][6] = 1; + fMin_1[0][7] = 0; + fMax_1[0][7] = 0.496332526207; + fMin_1[1][7] = 0; + fMax_1[1][7] = 0.491525411606; + fMin_1[2][7] = 0; + fMax_1[2][7] = 0.496332526207; + fMin_1[0][8] = 0; + fMax_1[0][8] = 1.99933886528; + fMin_1[1][8] = 0; + fMax_1[1][8] = 1.52447521687; + fMin_1[2][8] = 0; + fMax_1[2][8] = 1.99933886528; + fMin_1[0][9] = 0; + fMax_1[0][9] = 1; + fMin_1[1][9] = 0; + fMax_1[1][9] = 1; + fMin_1[2][9] = 0; + fMax_1[2][9] = 1; + fMin_1[0][10] = 0; + fMax_1[0][10] = 9; + fMin_1[1][10] = 0; + fMax_1[1][10] = 9; + fMin_1[2][10] = 0; + fMax_1[2][10] = 9; + fMin_1[0][11] = 0; + fMax_1[0][11] = 6; + fMin_1[1][11] = 0; + fMax_1[1][11] = 6; + fMin_1[2][11] = 0; + fMax_1[2][11] = 6; + fMin_1[0][12] = 0; + fMax_1[0][12] = 5; + fMin_1[1][12] = 0; + fMax_1[1][12] = 6; + fMin_1[2][12] = 0; + fMax_1[2][12] = 6; + fMin_1[0][13] = 0; + fMax_1[0][13] = 5; + fMin_1[1][13] = 0; + fMax_1[1][13] = 4; + fMin_1[2][13] = 0; + fMax_1[2][13] = 5; +} + +//_______________________________________________________________________ +inline void ReadMLPInner::Transform_1( std::vector<double>& iv, int cls) const +{ + // Normalization transformation + if (cls < 0 || cls > 2) { + if (2 > 1 ) cls = 2; + else cls = 2; + } + const int nVar = 14; + + // get indices of used variables + + // define the indices of the variables which are transformed by this transformation + std::vector<int> indicesGet; + std::vector<int> indicesPut; + + indicesGet.push_back( 0); + indicesGet.push_back( 1); + indicesGet.push_back( 2); + indicesGet.push_back( 3); + indicesGet.push_back( 4); + indicesGet.push_back( 5); + indicesGet.push_back( 6); + indicesGet.push_back( 7); + indicesGet.push_back( 8); + indicesGet.push_back( 9); + indicesGet.push_back( 10); + indicesGet.push_back( 11); + indicesGet.push_back( 12); + indicesGet.push_back( 13); + indicesPut.push_back( 0); + indicesPut.push_back( 1); + indicesPut.push_back( 2); + indicesPut.push_back( 3); + indicesPut.push_back( 4); + indicesPut.push_back( 5); + indicesPut.push_back( 6); + indicesPut.push_back( 7); + indicesPut.push_back( 8); + indicesPut.push_back( 9); + indicesPut.push_back( 10); + indicesPut.push_back( 11); + indicesPut.push_back( 12); + indicesPut.push_back( 13); + + std::vector<double> dv(nVar); + for (int ivar=0; ivar<nVar; ivar++) dv[ivar] = iv[indicesGet.at(ivar)]; + for (int ivar=0;ivar<14;ivar++) { + double offset = fMin_1[cls][ivar]; + double scale = 1.0/(fMax_1[cls][ivar]-fMin_1[cls][ivar]); + iv[indicesPut.at(ivar)] = (dv[ivar]-offset)*scale * 2 - 1; + } +} + +//_______________________________________________________________________ +inline void ReadMLPInner::InitTransform() +{ + InitTransform_1(); +} + +//_______________________________________________________________________ +inline void ReadMLPInner::Transform( std::vector<double>& iv, int sigOrBgd ) const +{ + Transform_1( iv, sigOrBgd ); +} diff --git a/CaloFuture/CaloFutureTools/src/TMV_MLP_middle.C b/CaloFuture/CaloFutureTools/src/TMV_MLP_middle.C new file mode 100644 index 0000000000000000000000000000000000000000..814fe5b0e070566a2b3d230a878b234e65d8efcb --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/TMV_MLP_middle.C @@ -0,0 +1,817 @@ +// Class: ReadMLPMiddle +// Automatically generated by MethodBase::MakeClass +// + +/* configuration options ===================================================== + +#GEN -*-*-*-*-*-*-*-*-*-*-*- general info -*-*-*-*-*-*-*-*-*-*-*- + +Method : MLP::MLP +TMVA Release : 4.1.2 [262402] +ROOT Release : 5.30/00 [335360] +Creator : calvom +Date : Tue Nov 8 16:53:17 2011 +Host : Linux lxbuild148.cern.ch 2.6.18-194.26.1.el5 #1 SMP Wed Nov 10 09:45:46 CET 2010 x86_64 x86_64 x86_64 GNU/Linux +Dir : /afs/cern.ch/user/c/calvom/w0/GammaPi0/tmva_calib +Training events: 24786 +Analysis type : [Classification] + + +#OPT -*-*-*-*-*-*-*-*-*-*-*-*- options -*-*-*-*-*-*-*-*-*-*-*-*- + +# Set by User: +NCycles: "600" [Number of training cycles] +HiddenLayers: "N+5" [Specification of hidden layer architecture] +NeuronType: "tanh" [Neuron activation function type] +V: "False" [Verbose output (short form of "VerbosityLevel" below - overrides the latter one)] +VarTransform: "N" [List of variable transformations performed before training, e.g., "D_Background,P_Signal,G,N_AllClasses" for: "Decorrelation, PCA-transformation, Gaussianisation, Normalisation, each for the given class of events ('AllClasses' denotes all events of all classes, if no class indication is given, 'All' is assumed)"] +H: "True" [Print method-specific help message] +TestRate: "5" [Test for overtraining performed at each #th epochs] +# Default: +RandomSeed: "1" [Random seed for initial synapse weights (0 means unique seed for each run; default value '1')] +EstimatorType: "MSE" [MSE (Mean Square Estimator) for Gaussian Likelihood or CE(Cross-Entropy) for Bernoulli Likelihood] +NeuronInputType: "sum" [Neuron input function type] +VerbosityLevel: "Default" [Verbosity level] +CreateMVAPdfs: "False" [Create PDFs for classifier outputs (signal and background)] +IgnoreNegWeightsInTraining: "False" [Events with negative weights are ignored in the training (but are included for testing and performance evaluation)] +TrainingMethod: "BP" [Train with Back-Propagation (BP), BFGS Algorithm (BFGS), or Genetic Algorithm (GA - slower and worse)] +LearningRate: "2.000000e-02" [ANN learning rate parameter] +DecayRate: "1.000000e-02" [Decay rate for learning parameter] +EpochMonitoring: "False" [Provide epoch-wise monitoring plots according to TestRate (caution: causes big ROOT output file!)] +Sampling: "1.000000e+00" [Only 'Sampling' (randomly selected) events are trained each epoch] +SamplingEpoch: "1.000000e+00" [Sampling is used for the first 'SamplingEpoch' epochs, afterwards, all events are taken for training] +SamplingImportance: "1.000000e+00" [ The sampling weights of events in epochs which successful (worse estimator than before) are multiplied with SamplingImportance, else they are divided.] +SamplingTraining: "True" [The training sample is sampled] +SamplingTesting: "False" [The testing sample is sampled] +ResetStep: "50" [How often BFGS should reset history] +Tau: "3.000000e+00" [LineSearch "size step"] +BPMode: "sequential" [Back-propagation learning mode: sequential or batch] +BatchSize: "-1" [Batch size: number of events/batch, only set if in Batch Mode, -1 for BatchSize=number_of_events] +ConvergenceImprove: "1.000000e-30" [Minimum improvement which counts as improvement (<0 means automatic convergence check is turned off)] +ConvergenceTests: "-1" [Number of steps (without improvement) required for convergence (<0 means automatic convergence check is turned off)] +UseRegulator: "False" [Use regulator to avoid over-training] +UpdateLimit: "10000" [Maximum times of regulator update] +CalculateErrors: "False" [Calculates inverse Hessian matrix at the end of the training to be able to calculate the uncertainties of an MVA value] +WeightRange: "1.000000e+00" [Take the events for the estimator calculations from small deviations from the desired value to large deviations only over the weight range] +## + + +#VAR -*-*-*-*-*-*-*-*-*-*-*-* variables *-*-*-*-*-*-*-*-*-*-*-*- + +NVar 14 +fr2 fr2 fr2 fr2 'F' [396.177398682,13764.8271484] +fr2r4 fr2r4 fr2r4 fr2r4 'F' [0.301807701588,0.965358257294] +abs(asym) abs_asym_ abs(asym) abs(asym) 'F' [-0,0.782861948013] +kappa kappa kappa kappa 'F' [0,0.843120634556] +Eseed/Ecl Eseed_D_Ecl Eseed/Ecl Eseed/Ecl 'F' [0.244072809815,0.92901545763] +(E2+Eseed)/Ecl _E2_P_Eseed__D_Ecl (E2+Eseed)/Ecl (E2+Eseed)/Ecl 'F' [0.460556000471,0.964079260826] +eSumPS>0?eMaxPS/eSumPS:0 eSumPS_0_eMaxPS_D_eSumPS:0 eSumPS>0?eMaxPS/eSumPS:0 eSumPS>0?eMaxPS/eSumPS:0 'F' [0,1] +eSumPS>0?e2ndPS/eSumPS:0 eSumPS_0_e2ndPS_D_eSumPS:0 eSumPS>0?e2ndPS/eSumPS:0 eSumPS>0?e2ndPS/eSumPS:0 'F' [0,0.498583585024] +r2PS r2PS r2PS r2PS 'F' [0,1.97231829166] +abs(asymPS) abs_asymPS_ abs(asymPS) abs(asymPS) 'F' [0,1] +multiPS multiPS multiPS multiPS 'F' [0,9] +multiPS15 multiPS15 multiPS15 multiPS15 'F' [0,6] +multiPS30 multiPS30 multiPS30 multiPS30 'F' [0,6] +multiPS45 multiPS45 multiPS45 multiPS45 'F' [0,4] +NSpec 0 + + +============================================================================ */ + +#include <vector> +#include <cmath> +#include <string> +#include <iostream> + +#ifndef IClassifierReader__def +#define IClassifierReader__def + +class IClassifierReader { + + public: + + // constructor + IClassifierReader() : fStatusIsClean( true ) {} + virtual ~IClassifierReader() {} + + // return classifier response + virtual double GetMvaValue( const std::vector<double>& inputValues ) const = 0; + + // returns classifier status + bool IsStatusClean() const { return fStatusIsClean; } + + protected: + + bool fStatusIsClean; +}; + +#endif + +class ReadMLPMiddle : public IClassifierReader { + + public: + + // constructor + ReadMLPMiddle( const std::vector<std::string>& theInputVars ) + : IClassifierReader(), + fClassName( "ReadMLPMiddle" ), + fNvars( 14 ), + fIsNormalised( false ) + { + // the training input variables + const char* inputVars[] = { "fr2", "fr2r4", "abs(asym)", "kappa", "Eseed/Ecl", "(E2+Eseed)/Ecl", "eSumPS>0?eMaxPS/eSumPS:0", "eSumPS>0?e2ndPS/eSumPS:0", "r2PS", "abs(asymPS)", "multiPS", "multiPS15", "multiPS30", "multiPS45" }; + + // sanity checks + if (theInputVars.size() <= 0) { + std::cout << "Problem in class \"" << fClassName << "\": empty input vector" << std::endl; + fStatusIsClean = false; + } + + if (theInputVars.size() != fNvars) { + std::cout << "Problem in class \"" << fClassName << "\": mismatch in number of input values: " + << theInputVars.size() << " != " << fNvars << std::endl; + fStatusIsClean = false; + } + + // validate input variables + for (size_t ivar = 0; ivar < theInputVars.size(); ivar++) { + if (theInputVars[ivar] != inputVars[ivar]) { + std::cout << "Problem in class \"" << fClassName << "\": mismatch in input variable names" << std::endl + << " for variable [" << ivar << "]: " << theInputVars[ivar].c_str() << " != " << inputVars[ivar] << std::endl; + fStatusIsClean = false; + } + } + + // initialize min and max vectors (for normalisation) + fVmin[0] = -1; + fVmax[0] = 1; + fVmin[1] = -1; + fVmax[1] = 1; + fVmin[2] = -1; + fVmax[2] = 0.99999988079071; + fVmin[3] = -1; + fVmax[3] = 0.99999988079071; + fVmin[4] = -1; + fVmax[4] = 1; + fVmin[5] = -1; + fVmax[5] = 1; + fVmin[6] = -1; + fVmax[6] = 1; + fVmin[7] = -1; + fVmax[7] = 1; + fVmin[8] = -1; + fVmax[8] = 1; + fVmin[9] = -1; + fVmax[9] = 1; + fVmin[10] = -1; + fVmax[10] = 1; + fVmin[11] = -1; + fVmax[11] = 1; + fVmin[12] = -1; + fVmax[12] = 1; + fVmin[13] = -1; + fVmax[13] = 1; + + // initialize input variable types + fType[0] = 'F'; + fType[1] = 'F'; + fType[2] = 'F'; + fType[3] = 'F'; + fType[4] = 'F'; + fType[5] = 'F'; + fType[6] = 'F'; + fType[7] = 'F'; + fType[8] = 'F'; + fType[9] = 'F'; + fType[10] = 'F'; + fType[11] = 'F'; + fType[12] = 'F'; + fType[13] = 'F'; + + // initialize constants + Initialize(); + + // initialize transformation + InitTransform(); + } + + // destructor + virtual ~ReadMLPMiddle() { + Clear(); // method-specific + } + + // the classifier response + // "inputValues" is a vector of input values in the same order as the + // variables given to the constructor + double GetMvaValue( const std::vector<double>& inputValues ) const override; + + private: + + // method-specific destructor + void Clear(); + + // input variable transformation + + double fMin_1[3][14]; + double fMax_1[3][14]; + void InitTransform_1(); + void Transform_1( std::vector<double> & iv, int sigOrBgd ) const; + void InitTransform(); + void Transform( std::vector<double> & iv, int sigOrBgd ) const; + + // common member variables + const char* fClassName; + + const size_t fNvars; + size_t GetNvar() const { return fNvars; } + char GetType( int ivar ) const { return fType[ivar]; } + + // normalisation of input variables + const bool fIsNormalised; + bool IsNormalised() const { return fIsNormalised; } + double fVmin[14]; + double fVmax[14]; + double NormVariable( double x, double xmin, double xmax ) const { + // normalise to output range: [-1, 1] + return 2*(x - xmin)/(xmax - xmin) - 1.0; + } + + // type of input variable: 'F' or 'I' + char fType[14]; + + // initialize internal variables + void Initialize(); + double GetMvaValue__( const std::vector<double>& inputValues ) const; + + // private members (method specific) + + double ActivationFnc(double x) const; + double OutputActivationFnc(double x) const; + + int fLayers; + int fLayerSize[3]; + double fWeightMatrix0to1[20][15]; // weight matrix from layer 0 to 1 + double fWeightMatrix1to2[1][20]; // weight matrix from layer 1 to 2 + + double * fWeights[3]; +}; + +inline void ReadMLPMiddle::Initialize() +{ + // build network structure + fLayers = 3; + fLayerSize[0] = 15; fWeights[0] = new double[15]; + fLayerSize[1] = 20; fWeights[1] = new double[20]; + fLayerSize[2] = 1; fWeights[2] = new double[1]; + // weight matrix from layer 0 to 1 + fWeightMatrix0to1[0][0] = -0.867416606481198; + fWeightMatrix0to1[1][0] = 1.52892005921573; + fWeightMatrix0to1[2][0] = 0.928852393643837; + fWeightMatrix0to1[3][0] = 2.7044598593846; + fWeightMatrix0to1[4][0] = -2.61144685740294; + fWeightMatrix0to1[5][0] = -1.54822294568981; + fWeightMatrix0to1[6][0] = -0.69991092080064; + fWeightMatrix0to1[7][0] = 2.49183388807665; + fWeightMatrix0to1[8][0] = -1.82778992022997; + fWeightMatrix0to1[9][0] = -1.23480074738712; + fWeightMatrix0to1[10][0] = -2.32999130862363; + fWeightMatrix0to1[11][0] = -0.0619355352938491; + fWeightMatrix0to1[12][0] = -0.648084451209581; + fWeightMatrix0to1[13][0] = -1.29854810659858; + fWeightMatrix0to1[14][0] = -0.964059869212921; + fWeightMatrix0to1[15][0] = 1.14709660666656; + fWeightMatrix0to1[16][0] = -0.659108613746082; + fWeightMatrix0to1[17][0] = 1.29220704129439; + fWeightMatrix0to1[18][0] = 0.219218314861889; + fWeightMatrix0to1[0][1] = -0.313579360837127; + fWeightMatrix0to1[1][1] = 1.4024752642764; + fWeightMatrix0to1[2][1] = -1.19851673123826; + fWeightMatrix0to1[3][1] = 0.58037365026283; + fWeightMatrix0to1[4][1] = -0.482629449494083; + fWeightMatrix0to1[5][1] = -0.31680037372708; + fWeightMatrix0to1[6][1] = -1.19146380571644; + fWeightMatrix0to1[7][1] = 1.92978194401728; + fWeightMatrix0to1[8][1] = -1.09175173970591; + fWeightMatrix0to1[9][1] = -1.35914101764875; + fWeightMatrix0to1[10][1] = 0.200995577667252; + fWeightMatrix0to1[11][1] = 0.571906415712693; + fWeightMatrix0to1[12][1] = 1.62065462400511; + fWeightMatrix0to1[13][1] = -0.0341372481003341; + fWeightMatrix0to1[14][1] = -3.45658380189554; + fWeightMatrix0to1[15][1] = -0.0126196639343866; + fWeightMatrix0to1[16][1] = -0.0844980421550597; + fWeightMatrix0to1[17][1] = -1.24243112895568; + fWeightMatrix0to1[18][1] = 1.45033544424252; + fWeightMatrix0to1[0][2] = -1.17333744144131; + fWeightMatrix0to1[1][2] = 0.537958601883077; + fWeightMatrix0to1[2][2] = 0.759383983445813; + fWeightMatrix0to1[3][2] = 1.17226490140808; + fWeightMatrix0to1[4][2] = 0.669805141472939; + fWeightMatrix0to1[5][2] = 2.1449085813314; + fWeightMatrix0to1[6][2] = -0.631284550782466; + fWeightMatrix0to1[7][2] = -1.33446196411931; + fWeightMatrix0to1[8][2] = 0.410131181532878; + fWeightMatrix0to1[9][2] = -0.301361359526247; + fWeightMatrix0to1[10][2] = 0.303260629430208; + fWeightMatrix0to1[11][2] = 1.16387977664382; + fWeightMatrix0to1[12][2] = 1.6108322347009; + fWeightMatrix0to1[13][2] = 0.601082221553922; + fWeightMatrix0to1[14][2] = -0.547264267034139; + fWeightMatrix0to1[15][2] = 1.06078483419717; + fWeightMatrix0to1[16][2] = -1.77078835600063; + fWeightMatrix0to1[17][2] = -1.11210936585844; + fWeightMatrix0to1[18][2] = -0.867334884904254; + fWeightMatrix0to1[0][3] = -2.02853398910341; + fWeightMatrix0to1[1][3] = 1.69808147897346; + fWeightMatrix0to1[2][3] = -0.113305678415982; + fWeightMatrix0to1[3][3] = -1.36826385097943; + fWeightMatrix0to1[4][3] = -0.00989162999579154; + fWeightMatrix0to1[5][3] = 1.2472433318308; + fWeightMatrix0to1[6][3] = 0.941667976489114; + fWeightMatrix0to1[7][3] = 1.60666277674855; + fWeightMatrix0to1[8][3] = -0.915602832375179; + fWeightMatrix0to1[9][3] = -0.855690366526691; + fWeightMatrix0to1[10][3] = -1.13509871477241; + fWeightMatrix0to1[11][3] = 0.568553603554666; + fWeightMatrix0to1[12][3] = -0.851252539277957; + fWeightMatrix0to1[13][3] = -1.14686594593269; + fWeightMatrix0to1[14][3] = -1.014280536591; + fWeightMatrix0to1[15][3] = 0.712750937101043; + fWeightMatrix0to1[16][3] = 1.31830506114039; + fWeightMatrix0to1[17][3] = 0.97980829511593; + fWeightMatrix0to1[18][3] = -0.418515378973496; + fWeightMatrix0to1[0][4] = -1.97483930490001; + fWeightMatrix0to1[1][4] = -0.687793978174217; + fWeightMatrix0to1[2][4] = 0.89010583052141; + fWeightMatrix0to1[3][4] = 0.421725240737996; + fWeightMatrix0to1[4][4] = 1.57425684241013; + fWeightMatrix0to1[5][4] = -1.02485739171261; + fWeightMatrix0to1[6][4] = 0.352037043029585; + fWeightMatrix0to1[7][4] = -0.989990502973038; + fWeightMatrix0to1[8][4] = -0.918626623275508; + fWeightMatrix0to1[9][4] = -0.00627843764882833; + fWeightMatrix0to1[10][4] = 0.650127824423305; + fWeightMatrix0to1[11][4] = -0.889425021440891; + fWeightMatrix0to1[12][4] = -1.54026365988138; + fWeightMatrix0to1[13][4] = -1.63539216705696; + fWeightMatrix0to1[14][4] = 0.290389593393486; + fWeightMatrix0to1[15][4] = 0.205094248586933; + fWeightMatrix0to1[16][4] = 1.91268676453227; + fWeightMatrix0to1[17][4] = -1.502890234018; + fWeightMatrix0to1[18][4] = -0.963493203028935; + fWeightMatrix0to1[0][5] = 2.18036935570376; + fWeightMatrix0to1[1][5] = -1.92424311845546; + fWeightMatrix0to1[2][5] = -2.26674800851725; + fWeightMatrix0to1[3][5] = -1.71287792152807; + fWeightMatrix0to1[4][5] = 0.480932583928402; + fWeightMatrix0to1[5][5] = -1.20230577451749; + fWeightMatrix0to1[6][5] = -1.84842005108065; + fWeightMatrix0to1[7][5] = -0.718821462004105; + fWeightMatrix0to1[8][5] = 1.1974718960183; + fWeightMatrix0to1[9][5] = -1.50619374498669; + fWeightMatrix0to1[10][5] = 1.66134007975805; + fWeightMatrix0to1[11][5] = -1.08016642459962; + fWeightMatrix0to1[12][5] = -1.42182870299292; + fWeightMatrix0to1[13][5] = 0.34073109703492; + fWeightMatrix0to1[14][5] = 1.40217161194194; + fWeightMatrix0to1[15][5] = -1.71243250173402; + fWeightMatrix0to1[16][5] = 2.22715053357944; + fWeightMatrix0to1[17][5] = 0.527332352536044; + fWeightMatrix0to1[18][5] = 0.0648949570041376; + fWeightMatrix0to1[0][6] = -0.738841533745263; + fWeightMatrix0to1[1][6] = 0.346812228849947; + fWeightMatrix0to1[2][6] = 0.121009510965812; + fWeightMatrix0to1[3][6] = -0.849131082595975; + fWeightMatrix0to1[4][6] = 1.09740015742468; + fWeightMatrix0to1[5][6] = -0.544087730510457; + fWeightMatrix0to1[6][6] = -1.45742111418507; + fWeightMatrix0to1[7][6] = -0.323638445325328; + fWeightMatrix0to1[8][6] = 0.215008383977184; + fWeightMatrix0to1[9][6] = 0.757553950948554; + fWeightMatrix0to1[10][6] = 0.502897133789601; + fWeightMatrix0to1[11][6] = -0.356301970061779; + fWeightMatrix0to1[12][6] = -0.404294467047688; + fWeightMatrix0to1[13][6] = 0.340934465825974; + fWeightMatrix0to1[14][6] = -0.115059503627307; + fWeightMatrix0to1[15][6] = 0.860186328731439; + fWeightMatrix0to1[16][6] = -0.233774549376029; + fWeightMatrix0to1[17][6] = -1.26886700798678; + fWeightMatrix0to1[18][6] = 0.83852481025036; + fWeightMatrix0to1[0][7] = -1.26627056537021; + fWeightMatrix0to1[1][7] = 0.470753417418729; + fWeightMatrix0to1[2][7] = 1.63852583469858; + fWeightMatrix0to1[3][7] = 0.911455600002474; + fWeightMatrix0to1[4][7] = -1.30875327753522; + fWeightMatrix0to1[5][7] = 0.00970511213226444; + fWeightMatrix0to1[6][7] = 1.41834501270918; + fWeightMatrix0to1[7][7] = 1.6763955185333; + fWeightMatrix0to1[8][7] = -0.234904810568052; + fWeightMatrix0to1[9][7] = -0.675588633320613; + fWeightMatrix0to1[10][7] = -0.0262219284880216; + fWeightMatrix0to1[11][7] = -1.1719793450669; + fWeightMatrix0to1[12][7] = 0.755016319470702; + fWeightMatrix0to1[13][7] = 0.608192764034871; + fWeightMatrix0to1[14][7] = -0.188706738103988; + fWeightMatrix0to1[15][7] = -0.406885447080173; + fWeightMatrix0to1[16][7] = 0.148507511443218; + fWeightMatrix0to1[17][7] = -1.13443049209833; + fWeightMatrix0to1[18][7] = -0.190033405151551; + fWeightMatrix0to1[0][8] = 1.16653770171993; + fWeightMatrix0to1[1][8] = 0.104060672308803; + fWeightMatrix0to1[2][8] = 0.0011134129235443; + fWeightMatrix0to1[3][8] = 0.312063793194653; + fWeightMatrix0to1[4][8] = 0.704245030963736; + fWeightMatrix0to1[5][8] = 0.531708176868196; + fWeightMatrix0to1[6][8] = 1.03663834583442; + fWeightMatrix0to1[7][8] = -0.953420977046398; + fWeightMatrix0to1[8][8] = 0.961357552027267; + fWeightMatrix0to1[9][8] = 0.973059383499368; + fWeightMatrix0to1[10][8] = 0.0861079214520543; + fWeightMatrix0to1[11][8] = 1.12377079068739; + fWeightMatrix0to1[12][8] = 1.31340672815188; + fWeightMatrix0to1[13][8] = -1.15902944629629; + fWeightMatrix0to1[14][8] = -0.110697574871031; + fWeightMatrix0to1[15][8] = 1.3734188670324; + fWeightMatrix0to1[16][8] = -0.772975126256126; + fWeightMatrix0to1[17][8] = -0.949931599449223; + fWeightMatrix0to1[18][8] = 1.25003799183296; + fWeightMatrix0to1[0][9] = 0.00967602377087132; + fWeightMatrix0to1[1][9] = 0.0182382384949106; + fWeightMatrix0to1[2][9] = 1.23469219755964; + fWeightMatrix0to1[3][9] = 0.674635594054856; + fWeightMatrix0to1[4][9] = -1.78482755411435; + fWeightMatrix0to1[5][9] = -0.0217177118607022; + fWeightMatrix0to1[6][9] = 0.498060817982423; + fWeightMatrix0to1[7][9] = 0.432790908814506; + fWeightMatrix0to1[8][9] = -0.373167835048286; + fWeightMatrix0to1[9][9] = -0.832502791655382; + fWeightMatrix0to1[10][9] = 0.456667494152143; + fWeightMatrix0to1[11][9] = 1.02336751171567; + fWeightMatrix0to1[12][9] = -1.35163437936133; + fWeightMatrix0to1[13][9] = -1.17684235069197; + fWeightMatrix0to1[14][9] = -0.00878962094541198; + fWeightMatrix0to1[15][9] = -0.156529612004041; + fWeightMatrix0to1[16][9] = 0.88002169679633; + fWeightMatrix0to1[17][9] = -0.166820217641056; + fWeightMatrix0to1[18][9] = -0.663361630193172; + fWeightMatrix0to1[0][10] = -0.793098436338315; + fWeightMatrix0to1[1][10] = 0.100571779785801; + fWeightMatrix0to1[2][10] = 1.06529019318474; + fWeightMatrix0to1[3][10] = 0.992082837071785; + fWeightMatrix0to1[4][10] = -0.152973848691906; + fWeightMatrix0to1[5][10] = 0.0710755177270902; + fWeightMatrix0to1[6][10] = -1.95362769307301; + fWeightMatrix0to1[7][10] = 0.652377333328601; + fWeightMatrix0to1[8][10] = 0.0119366823426579; + fWeightMatrix0to1[9][10] = -0.874841265727433; + fWeightMatrix0to1[10][10] = -0.229977508467751; + fWeightMatrix0to1[11][10] = 0.44277338795919; + fWeightMatrix0to1[12][10] = 0.0650852375841939; + fWeightMatrix0to1[13][10] = -1.30132930651378; + fWeightMatrix0to1[14][10] = -0.369724159139221; + fWeightMatrix0to1[15][10] = 0.703767772268532; + fWeightMatrix0to1[16][10] = -0.0626130221598321; + fWeightMatrix0to1[17][10] = -0.100930629477247; + fWeightMatrix0to1[18][10] = 1.02621196952924; + fWeightMatrix0to1[0][11] = 0.92546693417593; + fWeightMatrix0to1[1][11] = 0.503938931621139; + fWeightMatrix0to1[2][11] = 0.0858937656196619; + fWeightMatrix0to1[3][11] = -1.59045525533957; + fWeightMatrix0to1[4][11] = -1.73489993547179; + fWeightMatrix0to1[5][11] = 0.564318577651265; + fWeightMatrix0to1[6][11] = 1.15739834523708; + fWeightMatrix0to1[7][11] = 1.15618489964227; + fWeightMatrix0to1[8][11] = 0.266592672289452; + fWeightMatrix0to1[9][11] = 1.81241803610749; + fWeightMatrix0to1[10][11] = -1.6762844956494; + fWeightMatrix0to1[11][11] = -0.940592315799515; + fWeightMatrix0to1[12][11] = -0.0142765211246494; + fWeightMatrix0to1[13][11] = -1.51350023770462; + fWeightMatrix0to1[14][11] = 0.274862103942864; + fWeightMatrix0to1[15][11] = 1.63413020292962; + fWeightMatrix0to1[16][11] = -0.874633583035442; + fWeightMatrix0to1[17][11] = 0.661407739822478; + fWeightMatrix0to1[18][11] = -0.434044171339045; + fWeightMatrix0to1[0][12] = -2.16304509617558; + fWeightMatrix0to1[1][12] = 0.725610167020035; + fWeightMatrix0to1[2][12] = 0.696598971951744; + fWeightMatrix0to1[3][12] = 0.471111955041938; + fWeightMatrix0to1[4][12] = 0.0859924682021416; + fWeightMatrix0to1[5][12] = 0.450480677018801; + fWeightMatrix0to1[6][12] = 1.31243380720041; + fWeightMatrix0to1[7][12] = -0.393309031056374; + fWeightMatrix0to1[8][12] = -0.335482753900041; + fWeightMatrix0to1[9][12] = 0.184436808445052; + fWeightMatrix0to1[10][12] = -1.36214641840382; + fWeightMatrix0to1[11][12] = -0.792105372631398; + fWeightMatrix0to1[12][12] = -1.20997377555831; + fWeightMatrix0to1[13][12] = -0.441865451770537; + fWeightMatrix0to1[14][12] = -0.455845441390649; + fWeightMatrix0to1[15][12] = -1.00734698553553; + fWeightMatrix0to1[16][12] = -1.32117772087793; + fWeightMatrix0to1[17][12] = -0.310478331944271; + fWeightMatrix0to1[18][12] = -0.840833259846518; + fWeightMatrix0to1[0][13] = -0.337122150022944; + fWeightMatrix0to1[1][13] = 0.218655506674274; + fWeightMatrix0to1[2][13] = -0.154368567075649; + fWeightMatrix0to1[3][13] = 0.237691471305213; + fWeightMatrix0to1[4][13] = -1.32734322819975; + fWeightMatrix0to1[5][13] = 0.898254759266311; + fWeightMatrix0to1[6][13] = 1.96349493188879; + fWeightMatrix0to1[7][13] = 1.44498369546106; + fWeightMatrix0to1[8][13] = -0.63102230191847; + fWeightMatrix0to1[9][13] = -1.77504421027533; + fWeightMatrix0to1[10][13] = -0.853698426031734; + fWeightMatrix0to1[11][13] = -0.531542047187409; + fWeightMatrix0to1[12][13] = -1.10738840214253; + fWeightMatrix0to1[13][13] = -0.184267539610476; + fWeightMatrix0to1[14][13] = -0.317923292009617; + fWeightMatrix0to1[15][13] = 2.04610576511013; + fWeightMatrix0to1[16][13] = -0.208448079974731; + fWeightMatrix0to1[17][13] = 0.146612809162846; + fWeightMatrix0to1[18][13] = -0.483493639255675; + fWeightMatrix0to1[0][14] = -1.9290184065958; + fWeightMatrix0to1[1][14] = 2.77842901867793; + fWeightMatrix0to1[2][14] = 0.722315069412496; + fWeightMatrix0to1[3][14] = -1.99803885369666; + fWeightMatrix0to1[4][14] = -0.737012752883904; + fWeightMatrix0to1[5][14] = 0.637970306915431; + fWeightMatrix0to1[6][14] = 0.895943391331503; + fWeightMatrix0to1[7][14] = 0.276247873858507; + fWeightMatrix0to1[8][14] = -1.10558994405963; + fWeightMatrix0to1[9][14] = 0.383021074024618; + fWeightMatrix0to1[10][14] = 2.603676011013; + fWeightMatrix0to1[11][14] = 0.487155687196025; + fWeightMatrix0to1[12][14] = 0.349758905360271; + fWeightMatrix0to1[13][14] = 0.925365632231932; + fWeightMatrix0to1[14][14] = 0.357705150227094; + fWeightMatrix0to1[15][14] = -1.24031635175521; + fWeightMatrix0to1[16][14] = -0.690835412708456; + fWeightMatrix0to1[17][14] = -0.0828410602933603; + fWeightMatrix0to1[18][14] = -1.38640604196602; + // weight matrix from layer 1 to 2 + fWeightMatrix1to2[0][0] = 0.0782498789202482; + fWeightMatrix1to2[0][1] = -0.250875309083546; + fWeightMatrix1to2[0][2] = 0.122602291610441; + fWeightMatrix1to2[0][3] = -1.3488789386558; + fWeightMatrix1to2[0][4] = 0.133379843710428; + fWeightMatrix1to2[0][5] = -0.311638983583305; + fWeightMatrix1to2[0][6] = 0.129042787301883; + fWeightMatrix1to2[0][7] = -0.164813815424402; + fWeightMatrix1to2[0][8] = 0.191821611847282; + fWeightMatrix1to2[0][9] = -0.0593658577582407; + fWeightMatrix1to2[0][10] = -0.862948789674314; + fWeightMatrix1to2[0][11] = -0.0470652379333911; + fWeightMatrix1to2[0][12] = -0.034632651943513; + fWeightMatrix1to2[0][13] = -0.353586449539869; + fWeightMatrix1to2[0][14] = -0.436294927850531; + fWeightMatrix1to2[0][15] = -0.30198913360629; + fWeightMatrix1to2[0][16] = -0.158425108422285; + fWeightMatrix1to2[0][17] = -0.0162157085346477; + fWeightMatrix1to2[0][18] = -0.0623532303058598; + fWeightMatrix1to2[0][19] = 0.354911694175998; +} + +inline double ReadMLPMiddle::GetMvaValue__( const std::vector<double>& inputValues ) const +{ + if (inputValues.size() != (unsigned int)fLayerSize[0]-1) { + std::cout << "Input vector needs to be of size " << fLayerSize[0]-1 << std::endl; + return 0; + } + + for (int l=0; l<fLayers; l++) + for (int i=0; i<fLayerSize[l]; i++) fWeights[l][i]=0; + + for (int l=0; l<fLayers-1; l++) + fWeights[l][fLayerSize[l]-1]=1; + + for (int i=0; i<fLayerSize[0]-1; i++) + fWeights[0][i]=inputValues[i]; + + // layer 0 to 1 + for (int o=0; o<fLayerSize[1]-1; o++) { + for (int i=0; i<fLayerSize[0]; i++) { + double inputVal = fWeightMatrix0to1[o][i] * fWeights[0][i]; + fWeights[1][o] += inputVal; + } + fWeights[1][o] = ActivationFnc(fWeights[1][o]); + } + // layer 1 to 2 + for (int o=0; o<fLayerSize[2]; o++) { + for (int i=0; i<fLayerSize[1]; i++) { + double inputVal = fWeightMatrix1to2[o][i] * fWeights[1][i]; + fWeights[2][o] += inputVal; + } + fWeights[2][o] = OutputActivationFnc(fWeights[2][o]); + } + + return fWeights[2][0]; +} + +double ReadMLPMiddle::ActivationFnc(double x) const { + // hyperbolic tan + return tanh(x); +} +double ReadMLPMiddle::OutputActivationFnc(double x) const { + // identity + return x; +} + +// Clean up +inline void ReadMLPMiddle::Clear() +{ + // nothing to clear +} + inline double ReadMLPMiddle::GetMvaValue( const std::vector<double>& inputValues ) const + { + // classifier response value + double retval = 0; + + // classifier response, sanity check first + if (!IsStatusClean()) { + std::cout << "Problem in class \"" << fClassName << "\": cannot return classifier response" + << " because status is dirty" << std::endl; + retval = 0; + } + else { + if (IsNormalised()) { + // normalise variables + std::vector<double> iV; + int ivar = 0; + for (std::vector<double>::const_iterator varIt = inputValues.begin(); + varIt != inputValues.end(); varIt++, ivar++) { + iV.push_back(NormVariable( *varIt, fVmin[ivar], fVmax[ivar] )); + } + Transform( iV, -1 ); + retval = GetMvaValue__( iV ); + } + else { + std::vector<double> iV; + int ivar = 0; + for (std::vector<double>::const_iterator varIt = inputValues.begin(); + varIt != inputValues.end(); varIt++, ivar++) { + iV.push_back(*varIt); + } + Transform( iV, -1 ); + retval = GetMvaValue__( iV ); + } + } + + return retval; + } + +//_______________________________________________________________________ +inline void ReadMLPMiddle::InitTransform_1() +{ + // Normalization transformation, initialisation + fMin_1[0][0] = 396.177398682; + fMax_1[0][0] = 13764.8271484; + fMin_1[1][0] = 489.128509521; + fMax_1[1][0] = 12811.4384766; + fMin_1[2][0] = 396.177398682; + fMax_1[2][0] = 13764.8271484; + fMin_1[0][1] = 0.301807701588; + fMax_1[0][1] = 0.965358257294; + fMin_1[1][1] = 0.348349481821; + fMax_1[1][1] = 0.949014008045; + fMin_1[2][1] = 0.301807701588; + fMax_1[2][1] = 0.965358257294; + fMin_1[0][2] = -0; + fMax_1[0][2] = 0.740151584148; + fMin_1[1][2] = 3.28147143591e-05; + fMax_1[1][2] = 0.782861948013; + fMin_1[2][2] = -0; + fMax_1[2][2] = 0.782861948013; + fMin_1[0][3] = 0; + fMax_1[0][3] = 0.843120634556; + fMin_1[1][3] = 0.0138616990298; + fMax_1[1][3] = 0.811695218086; + fMin_1[2][3] = 0; + fMax_1[2][3] = 0.843120634556; + fMin_1[0][4] = 0.271574378014; + fMax_1[0][4] = 0.92901545763; + fMin_1[1][4] = 0.244072809815; + fMax_1[1][4] = 0.907343685627; + fMin_1[2][4] = 0.244072809815; + fMax_1[2][4] = 0.92901545763; + fMin_1[0][5] = 0.526907742023; + fMax_1[0][5] = 0.963463187218; + fMin_1[1][5] = 0.460556000471; + fMax_1[1][5] = 0.964079260826; + fMin_1[2][5] = 0.460556000471; + fMax_1[2][5] = 0.964079260826; + fMin_1[0][6] = 0; + fMax_1[0][6] = 1; + fMin_1[1][6] = 0; + fMax_1[1][6] = 1; + fMin_1[2][6] = 0; + fMax_1[2][6] = 1; + fMin_1[0][7] = 0; + fMax_1[0][7] = 0.498583585024; + fMin_1[1][7] = 0; + fMax_1[1][7] = 0.497716933489; + fMin_1[2][7] = 0; + fMax_1[2][7] = 0.498583585024; + fMin_1[0][8] = 0; + fMax_1[0][8] = 1.97231829166; + fMin_1[1][8] = 0; + fMax_1[1][8] = 1.69394040108; + fMin_1[2][8] = 0; + fMax_1[2][8] = 1.97231829166; + fMin_1[0][9] = 0; + fMax_1[0][9] = 1; + fMin_1[1][9] = 0; + fMax_1[1][9] = 1; + fMin_1[2][9] = 0; + fMax_1[2][9] = 1; + fMin_1[0][10] = 0; + fMax_1[0][10] = 9; + fMin_1[1][10] = 0; + fMax_1[1][10] = 9; + fMin_1[2][10] = 0; + fMax_1[2][10] = 9; + fMin_1[0][11] = 0; + fMax_1[0][11] = 6; + fMin_1[1][11] = 0; + fMax_1[1][11] = 5; + fMin_1[2][11] = 0; + fMax_1[2][11] = 6; + fMin_1[0][12] = 0; + fMax_1[0][12] = 6; + fMin_1[1][12] = 0; + fMax_1[1][12] = 4; + fMin_1[2][12] = 0; + fMax_1[2][12] = 6; + fMin_1[0][13] = 0; + fMax_1[0][13] = 4; + fMin_1[1][13] = 0; + fMax_1[1][13] = 4; + fMin_1[2][13] = 0; + fMax_1[2][13] = 4; +} + +//_______________________________________________________________________ +inline void ReadMLPMiddle::Transform_1( std::vector<double>& iv, int cls) const +{ + // Normalization transformation + if (cls < 0 || cls > 2) { + if (2 > 1 ) cls = 2; + else cls = 2; + } + const int nVar = 14; + + // get indices of used variables + + // define the indices of the variables which are transformed by this transformation + std::vector<int> indicesGet; + std::vector<int> indicesPut; + + indicesGet.push_back( 0); + indicesGet.push_back( 1); + indicesGet.push_back( 2); + indicesGet.push_back( 3); + indicesGet.push_back( 4); + indicesGet.push_back( 5); + indicesGet.push_back( 6); + indicesGet.push_back( 7); + indicesGet.push_back( 8); + indicesGet.push_back( 9); + indicesGet.push_back( 10); + indicesGet.push_back( 11); + indicesGet.push_back( 12); + indicesGet.push_back( 13); + indicesPut.push_back( 0); + indicesPut.push_back( 1); + indicesPut.push_back( 2); + indicesPut.push_back( 3); + indicesPut.push_back( 4); + indicesPut.push_back( 5); + indicesPut.push_back( 6); + indicesPut.push_back( 7); + indicesPut.push_back( 8); + indicesPut.push_back( 9); + indicesPut.push_back( 10); + indicesPut.push_back( 11); + indicesPut.push_back( 12); + indicesPut.push_back( 13); + + std::vector<double> dv(nVar); + for (int ivar=0; ivar<nVar; ivar++) dv[ivar] = iv[indicesGet.at(ivar)]; + for (int ivar=0;ivar<14;ivar++) { + double offset = fMin_1[cls][ivar]; + double scale = 1.0/(fMax_1[cls][ivar]-fMin_1[cls][ivar]); + iv[indicesPut.at(ivar)] = (dv[ivar]-offset)*scale * 2 - 1; + } +} + +//_______________________________________________________________________ +inline void ReadMLPMiddle::InitTransform() +{ + InitTransform_1(); +} + +//_______________________________________________________________________ +inline void ReadMLPMiddle::Transform( std::vector<double>& iv, int sigOrBgd ) const +{ + Transform_1( iv, sigOrBgd ); +} diff --git a/CaloFuture/CaloFutureTools/src/TMV_MLP_outer.C b/CaloFuture/CaloFutureTools/src/TMV_MLP_outer.C new file mode 100644 index 0000000000000000000000000000000000000000..1b74144f6b869522bd22aee9260cd3f6216386da --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/TMV_MLP_outer.C @@ -0,0 +1,817 @@ +// Class: ReadMLPOuter +// Automatically generated by MethodBase::MakeClass +// + +/* configuration options ===================================================== + +#GEN -*-*-*-*-*-*-*-*-*-*-*- general info -*-*-*-*-*-*-*-*-*-*-*- + +Method : MLP::MLP +TMVA Release : 4.1.2 [262402] +ROOT Release : 5.30/00 [335360] +Creator : calvom +Date : Tue Nov 8 17:09:32 2011 +Host : Linux lxbuild148.cern.ch 2.6.18-194.26.1.el5 #1 SMP Wed Nov 10 09:45:46 CET 2010 x86_64 x86_64 x86_64 GNU/Linux +Dir : /afs/cern.ch/user/c/calvom/w0/GammaPi0/tmva_calib +Training events: 31890 +Analysis type : [Classification] + + +#OPT -*-*-*-*-*-*-*-*-*-*-*-*- options -*-*-*-*-*-*-*-*-*-*-*-*- + +# Set by User: +NCycles: "600" [Number of training cycles] +HiddenLayers: "N+5" [Specification of hidden layer architecture] +NeuronType: "tanh" [Neuron activation function type] +V: "False" [Verbose output (short form of "VerbosityLevel" below - overrides the latter one)] +VarTransform: "N" [List of variable transformations performed before training, e.g., "D_Background,P_Signal,G,N_AllClasses" for: "Decorrelation, PCA-transformation, Gaussianisation, Normalisation, each for the given class of events ('AllClasses' denotes all events of all classes, if no class indication is given, 'All' is assumed)"] +H: "True" [Print method-specific help message] +TestRate: "5" [Test for overtraining performed at each #th epochs] +# Default: +RandomSeed: "1" [Random seed for initial synapse weights (0 means unique seed for each run; default value '1')] +EstimatorType: "MSE" [MSE (Mean Square Estimator) for Gaussian Likelihood or CE(Cross-Entropy) for Bernoulli Likelihood] +NeuronInputType: "sum" [Neuron input function type] +VerbosityLevel: "Default" [Verbosity level] +CreateMVAPdfs: "False" [Create PDFs for classifier outputs (signal and background)] +IgnoreNegWeightsInTraining: "False" [Events with negative weights are ignored in the training (but are included for testing and performance evaluation)] +TrainingMethod: "BP" [Train with Back-Propagation (BP), BFGS Algorithm (BFGS), or Genetic Algorithm (GA - slower and worse)] +LearningRate: "2.000000e-02" [ANN learning rate parameter] +DecayRate: "1.000000e-02" [Decay rate for learning parameter] +EpochMonitoring: "False" [Provide epoch-wise monitoring plots according to TestRate (caution: causes big ROOT output file!)] +Sampling: "1.000000e+00" [Only 'Sampling' (randomly selected) events are trained each epoch] +SamplingEpoch: "1.000000e+00" [Sampling is used for the first 'SamplingEpoch' epochs, afterwards, all events are taken for training] +SamplingImportance: "1.000000e+00" [ The sampling weights of events in epochs which successful (worse estimator than before) are multiplied with SamplingImportance, else they are divided.] +SamplingTraining: "True" [The training sample is sampled] +SamplingTesting: "False" [The testing sample is sampled] +ResetStep: "50" [How often BFGS should reset history] +Tau: "3.000000e+00" [LineSearch "size step"] +BPMode: "sequential" [Back-propagation learning mode: sequential or batch] +BatchSize: "-1" [Batch size: number of events/batch, only set if in Batch Mode, -1 for BatchSize=number_of_events] +ConvergenceImprove: "1.000000e-30" [Minimum improvement which counts as improvement (<0 means automatic convergence check is turned off)] +ConvergenceTests: "-1" [Number of steps (without improvement) required for convergence (<0 means automatic convergence check is turned off)] +UseRegulator: "False" [Use regulator to avoid over-training] +UpdateLimit: "10000" [Maximum times of regulator update] +CalculateErrors: "False" [Calculates inverse Hessian matrix at the end of the training to be able to calculate the uncertainties of an MVA value] +WeightRange: "1.000000e+00" [Take the events for the estimator calculations from small deviations from the desired value to large deviations only over the weight range] +## + + +#VAR -*-*-*-*-*-*-*-*-*-*-*-* variables *-*-*-*-*-*-*-*-*-*-*-*- + +NVar 14 +fr2 fr2 fr2 fr2 'F' [1262.8170166,25870.0039062] +fr2r4 fr2r4 fr2r4 fr2r4 'F' [-4.7790851593,0.974924445152] +abs(asym) abs_asym_ abs(asym) abs(asym) 'F' [-0,0.870256125927] +kappa kappa kappa kappa 'F' [0,0.902063071728] +Eseed/Ecl Eseed_D_Ecl Eseed/Ecl Eseed/Ecl 'F' [0.228343188763,0.998945295811] +(E2+Eseed)/Ecl _E2_P_Eseed__D_Ecl (E2+Eseed)/Ecl (E2+Eseed)/Ecl 'F' [0.452791303396,1.00381207466] +eSumPS>0?eMaxPS/eSumPS:0 eSumPS_0_eMaxPS_D_eSumPS:0 eSumPS>0?eMaxPS/eSumPS:0 eSumPS>0?eMaxPS/eSumPS:0 'F' [0,1] +eSumPS>0?e2ndPS/eSumPS:0 eSumPS_0_e2ndPS_D_eSumPS:0 eSumPS>0?e2ndPS/eSumPS:0 eSumPS>0?e2ndPS/eSumPS:0 'F' [0,0.499058365822] +r2PS r2PS r2PS r2PS 'F' [0,1.95918369293] +abs(asymPS) abs_asymPS_ abs(asymPS) abs(asymPS) 'F' [0,1] +multiPS multiPS multiPS multiPS 'F' [0,8] +multiPS15 multiPS15 multiPS15 multiPS15 'F' [0,5] +multiPS30 multiPS30 multiPS30 multiPS30 'F' [0,4] +multiPS45 multiPS45 multiPS45 multiPS45 'F' [0,3] +NSpec 0 + + +============================================================================ */ + +#include <vector> +#include <cmath> +#include <string> +#include <iostream> + +#ifndef IClassifierReader__def +#define IClassifierReader__def + +class IClassifierReader { + + public: + + // constructor + IClassifierReader() : fStatusIsClean( true ) {} + virtual ~IClassifierReader() {} + + // return classifier response + virtual double GetMvaValue( const std::vector<double>& inputValues ) const = 0; + + // returns classifier status + bool IsStatusClean() const { return fStatusIsClean; } + + protected: + + bool fStatusIsClean; +}; + +#endif + +class ReadMLPOuter : public IClassifierReader { + + public: + + // constructor + ReadMLPOuter( const std::vector<std::string>& theInputVars ) + : IClassifierReader(), + fClassName( "ReadMLPOuter" ), + fNvars( 14 ), + fIsNormalised( false ) + { + // the training input variables + const char* inputVars[] = { "fr2", "fr2r4", "abs(asym)", "kappa", "Eseed/Ecl", "(E2+Eseed)/Ecl", "eSumPS>0?eMaxPS/eSumPS:0", "eSumPS>0?e2ndPS/eSumPS:0", "r2PS", "abs(asymPS)", "multiPS", "multiPS15", "multiPS30", "multiPS45" }; + + // sanity checks + if (theInputVars.size() <= 0) { + std::cout << "Problem in class \"" << fClassName << "\": empty input vector" << std::endl; + fStatusIsClean = false; + } + + if (theInputVars.size() != fNvars) { + std::cout << "Problem in class \"" << fClassName << "\": mismatch in number of input values: " + << theInputVars.size() << " != " << fNvars << std::endl; + fStatusIsClean = false; + } + + // validate input variables + for (size_t ivar = 0; ivar < theInputVars.size(); ivar++) { + if (theInputVars[ivar] != inputVars[ivar]) { + std::cout << "Problem in class \"" << fClassName << "\": mismatch in input variable names" << std::endl + << " for variable [" << ivar << "]: " << theInputVars[ivar].c_str() << " != " << inputVars[ivar] << std::endl; + fStatusIsClean = false; + } + } + + // initialize min and max vectors (for normalisation) + fVmin[0] = -1; + fVmax[0] = 1; + fVmin[1] = -1; + fVmax[1] = 1; + fVmin[2] = -1; + fVmax[2] = 0.99999988079071; + fVmin[3] = -1; + fVmax[3] = 1; + fVmin[4] = -1; + fVmax[4] = 1; + fVmin[5] = -1; + fVmax[5] = 1; + fVmin[6] = -1; + fVmax[6] = 1; + fVmin[7] = -1; + fVmax[7] = 1; + fVmin[8] = -1; + fVmax[8] = 1; + fVmin[9] = -1; + fVmax[9] = 1; + fVmin[10] = -1; + fVmax[10] = 1; + fVmin[11] = -1; + fVmax[11] = 1; + fVmin[12] = -1; + fVmax[12] = 1; + fVmin[13] = -1; + fVmax[13] = 1; + + // initialize input variable types + fType[0] = 'F'; + fType[1] = 'F'; + fType[2] = 'F'; + fType[3] = 'F'; + fType[4] = 'F'; + fType[5] = 'F'; + fType[6] = 'F'; + fType[7] = 'F'; + fType[8] = 'F'; + fType[9] = 'F'; + fType[10] = 'F'; + fType[11] = 'F'; + fType[12] = 'F'; + fType[13] = 'F'; + + // initialize constants + Initialize(); + + // initialize transformation + InitTransform(); + } + + // destructor + virtual ~ReadMLPOuter() { + Clear(); // method-specific + } + + // the classifier response + // "inputValues" is a vector of input values in the same order as the + // variables given to the constructor + double GetMvaValue( const std::vector<double>& inputValues ) const override; + + private: + + // method-specific destructor + void Clear(); + + // input variable transformation + + double fMin_1[3][14]; + double fMax_1[3][14]; + void InitTransform_1(); + void Transform_1( std::vector<double> & iv, int sigOrBgd ) const; + void InitTransform(); + void Transform( std::vector<double> & iv, int sigOrBgd ) const; + + // common member variables + const char* fClassName; + + const size_t fNvars; + size_t GetNvar() const { return fNvars; } + char GetType( int ivar ) const { return fType[ivar]; } + + // normalisation of input variables + const bool fIsNormalised; + bool IsNormalised() const { return fIsNormalised; } + double fVmin[14]; + double fVmax[14]; + double NormVariable( double x, double xmin, double xmax ) const { + // normalise to output range: [-1, 1] + return 2*(x - xmin)/(xmax - xmin) - 1.0; + } + + // type of input variable: 'F' or 'I' + char fType[14]; + + // initialize internal variables + void Initialize(); + double GetMvaValue__( const std::vector<double>& inputValues ) const; + + // private members (method specific) + + double ActivationFnc(double x) const; + double OutputActivationFnc(double x) const; + + int fLayers; + int fLayerSize[3]; + double fWeightMatrix0to1[20][15]; // weight matrix from layer 0 to 1 + double fWeightMatrix1to2[1][20]; // weight matrix from layer 1 to 2 + + double * fWeights[3]; +}; + +inline void ReadMLPOuter::Initialize() +{ + // build network structure + fLayers = 3; + fLayerSize[0] = 15; fWeights[0] = new double[15]; + fLayerSize[1] = 20; fWeights[1] = new double[20]; + fLayerSize[2] = 1; fWeights[2] = new double[1]; + // weight matrix from layer 0 to 1 + fWeightMatrix0to1[0][0] = -0.803078780002077; + fWeightMatrix0to1[1][0] = 2.46852247389318; + fWeightMatrix0to1[2][0] = 1.13186843505129; + fWeightMatrix0to1[3][0] = 2.08289280349423; + fWeightMatrix0to1[4][0] = -2.02637667542277; + fWeightMatrix0to1[5][0] = -0.986243417218828; + fWeightMatrix0to1[6][0] = -0.244082833973297; + fWeightMatrix0to1[7][0] = 2.49486110312933; + fWeightMatrix0to1[8][0] = -1.53730331140634; + fWeightMatrix0to1[9][0] = -1.37630248429394; + fWeightMatrix0to1[10][0] = -1.89736835486016; + fWeightMatrix0to1[11][0] = 0.223034156937693; + fWeightMatrix0to1[12][0] = -1.0383802938468; + fWeightMatrix0to1[13][0] = -0.759650512986243; + fWeightMatrix0to1[14][0] = 1.82811900974975; + fWeightMatrix0to1[15][0] = 0.762919621719025; + fWeightMatrix0to1[16][0] = 0.157029807974629; + fWeightMatrix0to1[17][0] = 1.93320941809115; + fWeightMatrix0to1[18][0] = 0.143405923217408; + fWeightMatrix0to1[0][1] = 1.26209002843162; + fWeightMatrix0to1[1][1] = 0.800837943079452; + fWeightMatrix0to1[2][1] = -1.76747369204177; + fWeightMatrix0to1[3][1] = -0.361564528432957; + fWeightMatrix0to1[4][1] = 0.366761004922902; + fWeightMatrix0to1[5][1] = -1.96471302666455; + fWeightMatrix0to1[6][1] = -0.00863043940634471; + fWeightMatrix0to1[7][1] = 1.1002970997226; + fWeightMatrix0to1[8][1] = -0.897301827109627; + fWeightMatrix0to1[9][1] = -1.4370443331252; + fWeightMatrix0to1[10][1] = 0.726929486996826; + fWeightMatrix0to1[11][1] = 0.144972630146927; + fWeightMatrix0to1[12][1] = 1.01974710573241; + fWeightMatrix0to1[13][1] = -0.271869349873447; + fWeightMatrix0to1[14][1] = 1.42228166666045; + fWeightMatrix0to1[15][1] = 0.0104573774641417; + fWeightMatrix0to1[16][1] = -0.308118244670233; + fWeightMatrix0to1[17][1] = -2.30235230921859; + fWeightMatrix0to1[18][1] = 1.91747762926562; + fWeightMatrix0to1[0][2] = -1.40370127713885; + fWeightMatrix0to1[1][2] = 0.423607211765278; + fWeightMatrix0to1[2][2] = 0.818760843055836; + fWeightMatrix0to1[3][2] = 1.20387982860113; + fWeightMatrix0to1[4][2] = 1.35919685062478; + fWeightMatrix0to1[5][2] = 1.21540008848762; + fWeightMatrix0to1[6][2] = -0.544187659835051; + fWeightMatrix0to1[7][2] = -1.14357919480641; + fWeightMatrix0to1[8][2] = 0.297378412632497; + fWeightMatrix0to1[9][2] = -0.526383709761007; + fWeightMatrix0to1[10][2] = 0.883604311753331; + fWeightMatrix0to1[11][2] = 1.82479487589162; + fWeightMatrix0to1[12][2] = 1.99527911898016; + fWeightMatrix0to1[13][2] = 1.06309599550614; + fWeightMatrix0to1[14][2] = -2.17771385898406; + fWeightMatrix0to1[15][2] = 0.883578959090106; + fWeightMatrix0to1[16][2] = -1.10142776710941; + fWeightMatrix0to1[17][2] = -0.199074231499796; + fWeightMatrix0to1[18][2] = -0.406107007509069; + fWeightMatrix0to1[0][3] = -2.25938238908665; + fWeightMatrix0to1[1][3] = 2.10412597063301; + fWeightMatrix0to1[2][3] = 0.229288650958736; + fWeightMatrix0to1[3][3] = -1.31954297657338; + fWeightMatrix0to1[4][3] = -0.0592391931970953; + fWeightMatrix0to1[5][3] = -0.295338498057784; + fWeightMatrix0to1[6][3] = 0.883241506059367; + fWeightMatrix0to1[7][3] = 1.23103118599503; + fWeightMatrix0to1[8][3] = 0.609359545198016; + fWeightMatrix0to1[9][3] = 0.242221316928949; + fWeightMatrix0to1[10][3] = -1.18771134421954; + fWeightMatrix0to1[11][3] = 0.938633848501122; + fWeightMatrix0to1[12][3] = -0.451346424105564; + fWeightMatrix0to1[13][3] = -0.755660347351227; + fWeightMatrix0to1[14][3] = -1.13856736163619; + fWeightMatrix0to1[15][3] = 0.689854778538881; + fWeightMatrix0to1[16][3] = 1.15812394661006; + fWeightMatrix0to1[17][3] = 0.902214429609987; + fWeightMatrix0to1[18][3] = -0.0347518471475436; + fWeightMatrix0to1[0][4] = -1.84653992230033; + fWeightMatrix0to1[1][4] = -0.559554214433256; + fWeightMatrix0to1[2][4] = 1.34280927296906; + fWeightMatrix0to1[3][4] = 0.680455223703724; + fWeightMatrix0to1[4][4] = 2.27099267569362; + fWeightMatrix0to1[5][4] = 0.875384790055415; + fWeightMatrix0to1[6][4] = 1.07689800262901; + fWeightMatrix0to1[7][4] = -0.618591196087963; + fWeightMatrix0to1[8][4] = 0.00940997991751735; + fWeightMatrix0to1[9][4] = 0.119960051927709; + fWeightMatrix0to1[10][4] = 0.959392274846952; + fWeightMatrix0to1[11][4] = -1.16638883179262; + fWeightMatrix0to1[12][4] = -1.7460933444306; + fWeightMatrix0to1[13][4] = -0.755219386538928; + fWeightMatrix0to1[14][4] = 1.8648451240955; + fWeightMatrix0to1[15][4] = 0.382708379534019; + fWeightMatrix0to1[16][4] = 1.02893269952448; + fWeightMatrix0to1[17][4] = -1.33248833851209; + fWeightMatrix0to1[18][4] = -0.370452044508549; + fWeightMatrix0to1[0][5] = 1.80184695297776; + fWeightMatrix0to1[1][5] = -1.03783778224495; + fWeightMatrix0to1[2][5] = -1.87587461123689; + fWeightMatrix0to1[3][5] = -1.57428576422228; + fWeightMatrix0to1[4][5] = 0.346407925429289; + fWeightMatrix0to1[5][5] = -2.00403685431281; + fWeightMatrix0to1[6][5] = -1.90077807488318; + fWeightMatrix0to1[7][5] = -0.435805738924137; + fWeightMatrix0to1[8][5] = 2.22920897230816; + fWeightMatrix0to1[9][5] = -0.590267878593306; + fWeightMatrix0to1[10][5] = 1.81519843139597; + fWeightMatrix0to1[11][5] = -1.27185382653094; + fWeightMatrix0to1[12][5] = -1.47103922048247; + fWeightMatrix0to1[13][5] = 0.547787478237777; + fWeightMatrix0to1[14][5] = 0.227708755905687; + fWeightMatrix0to1[15][5] = -1.46813509039314; + fWeightMatrix0to1[16][5] = -0.0525733201505653; + fWeightMatrix0to1[17][5] = -0.109408204900155; + fWeightMatrix0to1[18][5] = 0.326916419457406; + fWeightMatrix0to1[0][6] = -0.897573267963214; + fWeightMatrix0to1[1][6] = -0.374010127046777; + fWeightMatrix0to1[2][6] = -0.0789346325365137; + fWeightMatrix0to1[3][6] = -0.998319913643738; + fWeightMatrix0to1[4][6] = 1.01933751235888; + fWeightMatrix0to1[5][6] = -0.985913803589177; + fWeightMatrix0to1[6][6] = -1.45439424255025; + fWeightMatrix0to1[7][6] = -0.278834694131582; + fWeightMatrix0to1[8][6] = -0.24879196817104; + fWeightMatrix0to1[9][6] = 2.19460624126606; + fWeightMatrix0to1[10][6] = 0.720530700907214; + fWeightMatrix0to1[11][6] = -0.541478420930393; + fWeightMatrix0to1[12][6] = -0.00862677189443074; + fWeightMatrix0to1[13][6] = 0.235434812899575; + fWeightMatrix0to1[14][6] = -0.946571167209579; + fWeightMatrix0to1[15][6] = 0.949420697844076; + fWeightMatrix0to1[16][6] = 0.397697406588499; + fWeightMatrix0to1[17][6] = -1.19287902043725; + fWeightMatrix0to1[18][6] = 0.367323540217887; + fWeightMatrix0to1[0][7] = -1.08982889728479; + fWeightMatrix0to1[1][7] = 0.0705548438716484; + fWeightMatrix0to1[2][7] = 1.21639858501589; + fWeightMatrix0to1[3][7] = 1.3533915188747; + fWeightMatrix0to1[4][7] = -1.72877194379874; + fWeightMatrix0to1[5][7] = -0.0954364128728001; + fWeightMatrix0to1[6][7] = 0.743186148113269; + fWeightMatrix0to1[7][7] = 1.58569293402206; + fWeightMatrix0to1[8][7] = -0.407976122711286; + fWeightMatrix0to1[9][7] = -0.757106488445243; + fWeightMatrix0to1[10][7] = -0.0513868284358275; + fWeightMatrix0to1[11][7] = -0.912763346380385; + fWeightMatrix0to1[12][7] = 1.28319073979458; + fWeightMatrix0to1[13][7] = 0.57440637742315; + fWeightMatrix0to1[14][7] = -0.0351951944683237; + fWeightMatrix0to1[15][7] = -0.334876100549796; + fWeightMatrix0to1[16][7] = 0.56826708139794; + fWeightMatrix0to1[17][7] = -1.11819662764277; + fWeightMatrix0to1[18][7] = -0.161625991599902; + fWeightMatrix0to1[0][8] = 1.41064908124236; + fWeightMatrix0to1[1][8] = -0.279389666861271; + fWeightMatrix0to1[2][8] = 0.647413274617866; + fWeightMatrix0to1[3][8] = 0.0329313689509846; + fWeightMatrix0to1[4][8] = 0.765222372267189; + fWeightMatrix0to1[5][8] = 0.805711391551295; + fWeightMatrix0to1[6][8] = 0.704971983155431; + fWeightMatrix0to1[7][8] = -1.15585865232024; + fWeightMatrix0to1[8][8] = 1.4004056798631; + fWeightMatrix0to1[9][8] = 0.59589686311756; + fWeightMatrix0to1[10][8] = 0.0506274444455068; + fWeightMatrix0to1[11][8] = 0.778310657929542; + fWeightMatrix0to1[12][8] = 1.36413859490602; + fWeightMatrix0to1[13][8] = -0.722376977263356; + fWeightMatrix0to1[14][8] = -0.651133777015196; + fWeightMatrix0to1[15][8] = 1.16225199814518; + fWeightMatrix0to1[16][8] = -0.898290853245839; + fWeightMatrix0to1[17][8] = 0.255981113911936; + fWeightMatrix0to1[18][8] = 1.15983322253769; + fWeightMatrix0to1[0][9] = 0.64410967707169; + fWeightMatrix0to1[1][9] = 0.298655015427935; + fWeightMatrix0to1[2][9] = 0.953288508810634; + fWeightMatrix0to1[3][9] = 1.17515129066659; + fWeightMatrix0to1[4][9] = -1.48534121747573; + fWeightMatrix0to1[5][9] = 0.383588681780043; + fWeightMatrix0to1[6][9] = -0.682117670973728; + fWeightMatrix0to1[7][9] = 1.0734580716766; + fWeightMatrix0to1[8][9] = 0.0972488394714247; + fWeightMatrix0to1[9][9] = -1.44575203315637; + fWeightMatrix0to1[10][9] = 0.689035260216028; + fWeightMatrix0to1[11][9] = 0.783461854623659; + fWeightMatrix0to1[12][9] = -0.897921034866479; + fWeightMatrix0to1[13][9] = -0.150132887679573; + fWeightMatrix0to1[14][9] = -0.227819148775529; + fWeightMatrix0to1[15][9] = -0.454368500870791; + fWeightMatrix0to1[16][9] = 0.926313537934954; + fWeightMatrix0to1[17][9] = 0.375592979473134; + fWeightMatrix0to1[18][9] = -0.212723032034983; + fWeightMatrix0to1[0][10] = -0.903684557324865; + fWeightMatrix0to1[1][10] = -0.269219667927999; + fWeightMatrix0to1[2][10] = 0.956329276333231; + fWeightMatrix0to1[3][10] = 1.14695509555494; + fWeightMatrix0to1[4][10] = -0.0665167038175885; + fWeightMatrix0to1[5][10] = -0.154134638989865; + fWeightMatrix0to1[6][10] = -0.937515521234543; + fWeightMatrix0to1[7][10] = 0.9660568680461; + fWeightMatrix0to1[8][10] = 0.389207068896224; + fWeightMatrix0to1[9][10] = -1.43667067795005; + fWeightMatrix0to1[10][10] = -0.545302499304715; + fWeightMatrix0to1[11][10] = 0.646453677304514; + fWeightMatrix0to1[12][10] = 0.368070906498839; + fWeightMatrix0to1[13][10] = -1.01860632431505; + fWeightMatrix0to1[14][10] = -0.00201116742788192; + fWeightMatrix0to1[15][10] = 0.609992814668807; + fWeightMatrix0to1[16][10] = -0.2995034193925; + fWeightMatrix0to1[17][10] = 0.165861384025389; + fWeightMatrix0to1[18][10] = 0.65872850910737; + fWeightMatrix0to1[0][11] = 0.76239282169146; + fWeightMatrix0to1[1][11] = 1.114355352444; + fWeightMatrix0to1[2][11] = 0.00632312719316779; + fWeightMatrix0to1[3][11] = -1.38700360257435; + fWeightMatrix0to1[4][11] = -1.33543093140446; + fWeightMatrix0to1[5][11] = 2.36450431921163; + fWeightMatrix0to1[6][11] = 1.63667811844591; + fWeightMatrix0to1[7][11] = 1.28531389688515; + fWeightMatrix0to1[8][11] = 0.311507523856964; + fWeightMatrix0to1[9][11] = 1.62382261557303; + fWeightMatrix0to1[10][11] = -1.53683084288582; + fWeightMatrix0to1[11][11] = -0.880227449202108; + fWeightMatrix0to1[12][11] = 0.469944237847874; + fWeightMatrix0to1[13][11] = -0.574782950115894; + fWeightMatrix0to1[14][11] = 0.0834393415934373; + fWeightMatrix0to1[15][11] = 1.73663042170519; + fWeightMatrix0to1[16][11] = -0.794958681610394; + fWeightMatrix0to1[17][11] = 1.03182112824119; + fWeightMatrix0to1[18][11] = -0.194707701648851; + fWeightMatrix0to1[0][12] = -1.12453351932177; + fWeightMatrix0to1[1][12] = 0.349214136004141; + fWeightMatrix0to1[2][12] = 0.648304976611225; + fWeightMatrix0to1[3][12] = 0.863958688425645; + fWeightMatrix0to1[4][12] = 0.53991657996592; + fWeightMatrix0to1[5][12] = -0.175441713082249; + fWeightMatrix0to1[6][12] = 1.86358071406195; + fWeightMatrix0to1[7][12] = -1.15194868707706; + fWeightMatrix0to1[8][12] = 0.303276761188666; + fWeightMatrix0to1[9][12] = -0.293569411375138; + fWeightMatrix0to1[10][12] = -1.13999727749549; + fWeightMatrix0to1[11][12] = -0.668860599026539; + fWeightMatrix0to1[12][12] = -0.929148759645519; + fWeightMatrix0to1[13][12] = 0.0354692929050461; + fWeightMatrix0to1[14][12] = -0.786027039415339; + fWeightMatrix0to1[15][12] = -1.04264078551136; + fWeightMatrix0to1[16][12] = -1.44812079105289; + fWeightMatrix0to1[17][12] = 0.0540896196172365; + fWeightMatrix0to1[18][12] = -0.492485393452257; + fWeightMatrix0to1[0][13] = -0.333167216181322; + fWeightMatrix0to1[1][13] = 0.123887737942558; + fWeightMatrix0to1[2][13] = 0.380006497159629; + fWeightMatrix0to1[3][13] = 0.451090958441009; + fWeightMatrix0to1[4][13] = -1.24985513801445; + fWeightMatrix0to1[5][13] = 0.146122374228418; + fWeightMatrix0to1[6][13] = 2.45815635758746; + fWeightMatrix0to1[7][13] = 1.67650332997768; + fWeightMatrix0to1[8][13] = 0.0261643692739909; + fWeightMatrix0to1[9][13] = -1.47712987834849; + fWeightMatrix0to1[10][13] = -1.0713005012704; + fWeightMatrix0to1[11][13] = 0.0656128452057918; + fWeightMatrix0to1[12][13] = -0.72591709364151; + fWeightMatrix0to1[13][13] = 0.490200081745697; + fWeightMatrix0to1[14][13] = 0.0825337270008085; + fWeightMatrix0to1[15][13] = 2.1664215923145; + fWeightMatrix0to1[16][13] = 0.390608640807874; + fWeightMatrix0to1[17][13] = 0.514931391652967; + fWeightMatrix0to1[18][13] = -0.0561729443152231; + fWeightMatrix0to1[0][14] = -2.09001832233408; + fWeightMatrix0to1[1][14] = 1.72881427757093; + fWeightMatrix0to1[2][14] = -0.0381319424927858; + fWeightMatrix0to1[3][14] = -2.05905352202282; + fWeightMatrix0to1[4][14] = -0.84529895120051; + fWeightMatrix0to1[5][14] = -0.325430883200274; + fWeightMatrix0to1[6][14] = 1.25000988278363; + fWeightMatrix0to1[7][14] = -0.0268772937346941; + fWeightMatrix0to1[8][14] = -0.651686501592155; + fWeightMatrix0to1[9][14] = 0.115833680890629; + fWeightMatrix0to1[10][14] = 2.11416880687827; + fWeightMatrix0to1[11][14] = 0.40560026675739; + fWeightMatrix0to1[12][14] = 0.319016786783736; + fWeightMatrix0to1[13][14] = -0.33280581243366; + fWeightMatrix0to1[14][14] = 0.496865152794801; + fWeightMatrix0to1[15][14] = -0.615512669262649; + fWeightMatrix0to1[16][14] = -1.46690737428128; + fWeightMatrix0to1[17][14] = -1.52062200595209; + fWeightMatrix0to1[18][14] = -1.66633039441861; + // weight matrix from layer 1 to 2 + fWeightMatrix1to2[0][0] = 0.0428683723750179; + fWeightMatrix1to2[0][1] = -0.177501101264912; + fWeightMatrix1to2[0][2] = 0.641503101776094; + fWeightMatrix1to2[0][3] = -0.658895361751999; + fWeightMatrix1to2[0][4] = -0.0571464010312664; + fWeightMatrix1to2[0][5] = -0.704806328003322; + fWeightMatrix1to2[0][6] = -0.121182349512334; + fWeightMatrix1to2[0][7] = -0.0680342016206922; + fWeightMatrix1to2[0][8] = 0.132383506938821; + fWeightMatrix1to2[0][9] = 0.0530225967277884; + fWeightMatrix1to2[0][10] = 0.0968814546615638; + fWeightMatrix1to2[0][11] = 0.0706561052588567; + fWeightMatrix1to2[0][12] = -0.028978796869773; + fWeightMatrix1to2[0][13] = 0.0827747721359912; + fWeightMatrix1to2[0][14] = 0.329575883298149; + fWeightMatrix1to2[0][15] = 0.318011854043643; + fWeightMatrix1to2[0][16] = 0.0087319385918838; + fWeightMatrix1to2[0][17] = 0.674654265382897; + fWeightMatrix1to2[0][18] = 0.00140682084534325; + fWeightMatrix1to2[0][19] = 0.484340512284042; +} + +inline double ReadMLPOuter::GetMvaValue__( const std::vector<double>& inputValues ) const +{ + if (inputValues.size() != (unsigned int)fLayerSize[0]-1) { + std::cout << "Input vector needs to be of size " << fLayerSize[0]-1 << std::endl; + return 0; + } + + for (int l=0; l<fLayers; l++) + for (int i=0; i<fLayerSize[l]; i++) fWeights[l][i]=0; + + for (int l=0; l<fLayers-1; l++) + fWeights[l][fLayerSize[l]-1]=1; + + for (int i=0; i<fLayerSize[0]-1; i++) + fWeights[0][i]=inputValues[i]; + + // layer 0 to 1 + for (int o=0; o<fLayerSize[1]-1; o++) { + for (int i=0; i<fLayerSize[0]; i++) { + double inputVal = fWeightMatrix0to1[o][i] * fWeights[0][i]; + fWeights[1][o] += inputVal; + } + fWeights[1][o] = ActivationFnc(fWeights[1][o]); + } + // layer 1 to 2 + for (int o=0; o<fLayerSize[2]; o++) { + for (int i=0; i<fLayerSize[1]; i++) { + double inputVal = fWeightMatrix1to2[o][i] * fWeights[1][i]; + fWeights[2][o] += inputVal; + } + fWeights[2][o] = OutputActivationFnc(fWeights[2][o]); + } + + return fWeights[2][0]; +} + +double ReadMLPOuter::ActivationFnc(double x) const { + // hyperbolic tan + return tanh(x); +} +double ReadMLPOuter::OutputActivationFnc(double x) const { + // identity + return x; +} + +// Clean up +inline void ReadMLPOuter::Clear() +{ + // nothing to clear +} + inline double ReadMLPOuter::GetMvaValue( const std::vector<double>& inputValues ) const + { + // classifier response value + double retval = 0; + + // classifier response, sanity check first + if (!IsStatusClean()) { + std::cout << "Problem in class \"" << fClassName << "\": cannot return classifier response" + << " because status is dirty" << std::endl; + retval = 0; + } + else { + if (IsNormalised()) { + // normalise variables + std::vector<double> iV; + int ivar = 0; + for (std::vector<double>::const_iterator varIt = inputValues.begin(); + varIt != inputValues.end(); varIt++, ivar++) { + iV.push_back(NormVariable( *varIt, fVmin[ivar], fVmax[ivar] )); + } + Transform( iV, -1 ); + retval = GetMvaValue__( iV ); + } + else { + std::vector<double> iV; + int ivar = 0; + for (std::vector<double>::const_iterator varIt = inputValues.begin(); + varIt != inputValues.end(); varIt++, ivar++) { + iV.push_back(*varIt); + } + Transform( iV, -1 ); + retval = GetMvaValue__( iV ); + } + } + + return retval; + } + +//_______________________________________________________________________ +inline void ReadMLPOuter::InitTransform_1() +{ + // Normalization transformation, initialisation + fMin_1[0][0] = 1262.8170166; + fMax_1[0][0] = 25870.0039062; + fMin_1[1][0] = 1367.57849121; + fMax_1[1][0] = 23745.2070312; + fMin_1[2][0] = 1262.8170166; + fMax_1[2][0] = 25870.0039062; + fMin_1[0][1] = -4.7790851593; + fMax_1[0][1] = 0.974924445152; + fMin_1[1][1] = -0.42424929142; + fMax_1[1][1] = 0.970570802689; + fMin_1[2][1] = -4.7790851593; + fMax_1[2][1] = 0.974924445152; + fMin_1[0][2] = -0; + fMax_1[0][2] = 0.869569957256; + fMin_1[1][2] = 0; + fMax_1[1][2] = 0.870256125927; + fMin_1[2][2] = -0; + fMax_1[2][2] = 0.870256125927; + fMin_1[0][3] = 0; + fMax_1[0][3] = 0.874010562897; + fMin_1[1][3] = 0; + fMax_1[1][3] = 0.902063071728; + fMin_1[2][3] = 0; + fMax_1[2][3] = 0.902063071728; + fMin_1[0][4] = 0.278514027596; + fMax_1[0][4] = 0.998945295811; + fMin_1[1][4] = 0.228343188763; + fMax_1[1][4] = 0.97812306881; + fMin_1[2][4] = 0.228343188763; + fMax_1[2][4] = 0.998945295811; + fMin_1[0][5] = 0.546376109123; + fMax_1[0][5] = 1.00381207466; + fMin_1[1][5] = 0.452791303396; + fMax_1[1][5] = 0.99529415369; + fMin_1[2][5] = 0.452791303396; + fMax_1[2][5] = 1.00381207466; + fMin_1[0][6] = 0; + fMax_1[0][6] = 1; + fMin_1[1][6] = 0; + fMax_1[1][6] = 1; + fMin_1[2][6] = 0; + fMax_1[2][6] = 1; + fMin_1[0][7] = 0; + fMax_1[0][7] = 0.499058365822; + fMin_1[1][7] = 0; + fMax_1[1][7] = 0.498812377453; + fMin_1[2][7] = 0; + fMax_1[2][7] = 0.499058365822; + fMin_1[0][8] = 0; + fMax_1[0][8] = 1.95758318901; + fMin_1[1][8] = 0; + fMax_1[1][8] = 1.95918369293; + fMin_1[2][8] = 0; + fMax_1[2][8] = 1.95918369293; + fMin_1[0][9] = 0; + fMax_1[0][9] = 1; + fMin_1[1][9] = 0; + fMax_1[1][9] = 1; + fMin_1[2][9] = 0; + fMax_1[2][9] = 1; + fMin_1[0][10] = 0; + fMax_1[0][10] = 8; + fMin_1[1][10] = 0; + fMax_1[1][10] = 8; + fMin_1[2][10] = 0; + fMax_1[2][10] = 8; + fMin_1[0][11] = 0; + fMax_1[0][11] = 4; + fMin_1[1][11] = 0; + fMax_1[1][11] = 5; + fMin_1[2][11] = 0; + fMax_1[2][11] = 5; + fMin_1[0][12] = 0; + fMax_1[0][12] = 3; + fMin_1[1][12] = 0; + fMax_1[1][12] = 4; + fMin_1[2][12] = 0; + fMax_1[2][12] = 4; + fMin_1[0][13] = 0; + fMax_1[0][13] = 3; + fMin_1[1][13] = 0; + fMax_1[1][13] = 3; + fMin_1[2][13] = 0; + fMax_1[2][13] = 3; +} + +//_______________________________________________________________________ +inline void ReadMLPOuter::Transform_1( std::vector<double>& iv, int cls) const +{ + // Normalization transformation + if (cls < 0 || cls > 2) { + if (2 > 1 ) cls = 2; + else cls = 2; + } + const int nVar = 14; + + // get indices of used variables + + // define the indices of the variables which are transformed by this transformation + std::vector<int> indicesGet; + std::vector<int> indicesPut; + + indicesGet.push_back( 0); + indicesGet.push_back( 1); + indicesGet.push_back( 2); + indicesGet.push_back( 3); + indicesGet.push_back( 4); + indicesGet.push_back( 5); + indicesGet.push_back( 6); + indicesGet.push_back( 7); + indicesGet.push_back( 8); + indicesGet.push_back( 9); + indicesGet.push_back( 10); + indicesGet.push_back( 11); + indicesGet.push_back( 12); + indicesGet.push_back( 13); + indicesPut.push_back( 0); + indicesPut.push_back( 1); + indicesPut.push_back( 2); + indicesPut.push_back( 3); + indicesPut.push_back( 4); + indicesPut.push_back( 5); + indicesPut.push_back( 6); + indicesPut.push_back( 7); + indicesPut.push_back( 8); + indicesPut.push_back( 9); + indicesPut.push_back( 10); + indicesPut.push_back( 11); + indicesPut.push_back( 12); + indicesPut.push_back( 13); + + std::vector<double> dv(nVar); + for (int ivar=0; ivar<nVar; ivar++) dv[ivar] = iv[indicesGet.at(ivar)]; + for (int ivar=0;ivar<14;ivar++) { + double offset = fMin_1[cls][ivar]; + double scale = 1.0/(fMax_1[cls][ivar]-fMin_1[cls][ivar]); + iv[indicesPut.at(ivar)] = (dv[ivar]-offset)*scale * 2 - 1; + } +} + +//_______________________________________________________________________ +inline void ReadMLPOuter::InitTransform() +{ + InitTransform_1(); +} + +//_______________________________________________________________________ +inline void ReadMLPOuter::Transform( std::vector<double>& iv, int sigOrBgd ) const +{ + Transform_1( iv, sigOrBgd ); +} diff --git a/CaloFuture/CaloFutureTools/src/Track2CaloFuture.cpp b/CaloFuture/CaloFutureTools/src/Track2CaloFuture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d8437288326b0428e5815fc31a32830b17ef3146 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/Track2CaloFuture.cpp @@ -0,0 +1,137 @@ +// Include files + +// LHCb +#include "GaudiKernel/Point3DTypes.h" +#include "GaudiKernel/Vector3DTypes.h" +#include "LHCbMath/Line.h" +#include "LHCbMath/GeomFun.h" +#include "Event/Track.h" +#include "Event/CaloCluster.h" +#include "Event/CaloHypo.h" +#include "TrackInterfaces/ITrackExtrapolator.h" +// local +#include "Track2CaloFuture.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : Track2CaloFuture +// +// Simple tool to propagate track to Calo reference planes +// +// 2007-06-25 : Olivier Deschamps +//----------------------------------------------------------------------------- + +// Declaration of the Tool Factory +DECLARE_COMPONENT( Track2CaloFuture ) + + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +Track2CaloFuture::Track2CaloFuture( const std::string& type, + const std::string& name, + const IInterface* parent ) + : GaudiTool ( type, name , parent ) +{ + declareInterface<ITrack2CaloFuture>(this); +} + +//============================================================================= +StatusCode Track2CaloFuture::initialize(){ + StatusCode sc = GaudiTool::initialize(); + if (sc.isFailure()) return Error("Failed to initialize", sc); + m_extrapolator = tool<ITrackExtrapolator>( m_extrapolatorType,"Extrapolator",this ); + return StatusCode::SUCCESS; +} +//============================================================================= +bool Track2CaloFuture::match(const LHCb::Track* track, std::string det,CaloPlane::Plane plane , double delta, const LHCb::Tr::PID pid ){ + m_status = setting(track); + m_det = det; + m_calo = getDet<DeCalorimeter>( det ); + m_state = caloState(plane, delta, pid); + m_cell = m_calo->Cell( m_state.position() ); + m_valid = m_calo->valid( m_cell ); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << " Track2CaloFuture setting [" << *track <<","<< det<<"] status : " <<m_status << endmsg; + return m_status; +} +//============================================================================= +LHCb::State Track2CaloFuture::caloState(CaloPlane::Plane plane , double delta, const LHCb::Tr::PID pid ){ + + LHCb::State state; // empty state + if( !m_status ) return state; + + // get caloPlane + ROOT::Math::Plane3D refPlane = m_calo->plane( plane ); + // propagate state to refPlane + LHCb::State calostate( m_track->closestState( refPlane ) ); + StatusCode sc = m_extrapolator->propagate ( calostate, refPlane , m_tolerance , pid ); + if(sc.isFailure())return state; + + if( 0. == delta)return calostate; + + Gaudi::XYZVector dir (calostate.tx(), calostate.ty(), 1.); + Gaudi::XYZPoint point = calostate.position() + delta * dir/dir.R(); + // extrapolate to the new point + sc = m_extrapolator->propagate ( calostate, point.z(), pid ); + if(sc.isFailure())return state; + return calostate; +} +//============================================================================= +bool Track2CaloFuture::setting(const LHCb::Track* track){ + m_track = track; + return ( NULL == m_track) ? false : true; +} + + + + +LHCb::State Track2CaloFuture::closestState(LHCb::CaloCluster* cluster,const LHCb::Tr::PID pid ){ + return closestState( cluster->position(),pid); +} + +LHCb::State Track2CaloFuture::closestState(LHCb::CaloHypo* hypo,const LHCb::Tr::PID pid ){ + LHCb::State state ;//emtpy state + LHCb::CaloPosition* calopos = hypo->position(); + if(calopos == NULL)return state; + return closestState( *calopos ,pid); +} +LHCb::State Track2CaloFuture::closestState(LHCb::CaloPosition calopos,const LHCb::Tr::PID pid ){ + double x = calopos.parameters()(LHCb::CaloPosition::Index::X); + double y = calopos.parameters()(LHCb::CaloPosition::Index::Y); + return closestState(x,y, pid); +} +LHCb::State Track2CaloFuture::closestState(LHCb::CaloCellID cellID,const LHCb::Tr::PID pid ){ + Gaudi::XYZPoint point = m_calo->cellCenter( cellID ); + return closestState(point.X(),point.Y(), pid); +} + +//============================================================================= +LHCb::State Track2CaloFuture::closestState(double x, double y,const LHCb::Tr::PID pid){ + LHCb::State state; // empty state + if( !m_status ) return state; + + // get state on Front of Ecal + LHCb::State calostate = caloState( CaloPlane::Front); + if(calostate.z() == 0 ) return state; + + // get frontPlane + ROOT::Math::Plane3D frontPlane = m_calo->plane( CaloPlane::Front ); + + // Define calo line (from transversal barycenter) and track line in Ecal + typedef Gaudi::Math::Line<Gaudi::XYZPoint,Gaudi::XYZVector> Line; + Gaudi::XYZVector normal = frontPlane.Normal(); + double zEcal = ( -normal.X()*x -normal.Y()*y - frontPlane.HesseDistance() )/normal.Z(); // tilt + Gaudi::XYZPoint point( x , y , zEcal ); + Line cLine( point ,frontPlane.Normal() ); + Line tLine( calostate.position() , calostate.slopes() ); + + // Find points of closest distance between calo Line and track Line + Gaudi::XYZPoint cP,tP; + Gaudi::Math::closestPoints<Line,Line,Gaudi::XYZPoint>(cLine,tLine,cP,tP); + + // propagate the state the new Z of closest distance + StatusCode sc = m_extrapolator->propagate ( calostate, tP.Z() , pid); + + if(sc.isFailure())return state; + return calostate; +} diff --git a/CaloFuture/CaloFutureTools/src/Track2CaloFuture.h b/CaloFuture/CaloFutureTools/src/Track2CaloFuture.h new file mode 100644 index 0000000000000000000000000000000000000000..70d8a778bc83f0347a6023336870d687fe03c623 --- /dev/null +++ b/CaloFuture/CaloFutureTools/src/Track2CaloFuture.h @@ -0,0 +1,71 @@ +// $Id: Track2CaloFuture.h,v 1.1.1.1 2008-05-08 09:09:02 cattanem Exp $ +#ifndef TRACK2CALOFUTURE_H +#define TRACK2CALOFUTURE_H 1 + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiTool.h" +//from LHCb +#include "CaloFutureInterfaces/ITrack2CaloFuture.h" +#include "Event/Track.h" + +// Forward declarations +struct ITrackExtrapolator; +namespace LHCb +{ +} + +/** @class Track2CaloFuture Track2CaloFuture.h + * + * + * @author Olivier Deschamps + * @date 2006-11-30 + */ +class Track2CaloFuture : public GaudiTool, virtual public ITrack2CaloFuture { +public: + /// Standard constructor + Track2CaloFuture( const std::string& type, + const std::string& name, + const IInterface* parent); + + StatusCode initialize() override; + + bool match(const LHCb::Track* track, + std::string det = DeCalorimeterLocation::Ecal, + CaloPlane::Plane plane = CaloPlane::ShowerMax, + double delta = 0., + const LHCb::Tr::PID pid = LHCb::Tr::PID::Pion() + ) override; + + LHCb::State caloState() override {return m_state;}; + LHCb::CaloCellID caloCellID() override {return m_cell;}; + bool isValid() override {return m_valid;}; + + // Closest State + LHCb::State closestState(LHCb::CaloHypo* hypo ,const LHCb::Tr::PID pid = LHCb::Tr::PID::Pion()) override; + LHCb::State closestState(LHCb::CaloCluster* cluster,const LHCb::Tr::PID pid = LHCb::Tr::PID::Pion()) override; + LHCb::State closestState(LHCb::CaloPosition calopos,const LHCb::Tr::PID pid = LHCb::Tr::PID::Pion()) override; + LHCb::State closestState(LHCb::CaloCellID cellID ,const LHCb::Tr::PID pid = LHCb::Tr::PID::Pion()) override; + const LHCb::Track* track() override {return m_track;}; + + + +protected: + LHCb::State closestState(double x, double y,const LHCb::Tr::PID pid = LHCb::Tr::PID::Pion()); + LHCb::State caloState(CaloPlane::Plane plane= CaloPlane::ShowerMax , + double delta =0 , + const LHCb::Tr::PID pid = LHCb::Tr::PID::Pion() ); + bool setting (const LHCb::Track* track); + bool m_status = false; + const LHCb::Track* m_track = nullptr; + LHCb::State m_state; + DeCalorimeter* m_calo = nullptr; + std::string m_det; +private: + ITrackExtrapolator* m_extrapolator = nullptr; + Gaudi::Property<std::string> m_extrapolatorType {this, "ExtrapolatorType", "TrackRungeKuttaExtrapolator"}; + Gaudi::Property<float> m_tolerance {this, "Tolerance", 0.01}; + LHCb::CaloCellID m_cell; + bool m_valid = false; +}; +#endif // TRACK2CALOFUTURE_H diff --git a/Rec/GlobalReco/CMakeLists.txt b/Rec/GlobalReco/CMakeLists.txt index 2c0dad2c47f5b604c747ee3b602ed30534d2f32c..b71c14edbd8eef03fde596b051c14edd3b076ddb 100644 --- a/Rec/GlobalReco/CMakeLists.txt +++ b/Rec/GlobalReco/CMakeLists.txt @@ -5,6 +5,8 @@ gaudi_subdir(GlobalReco v6r55) gaudi_depends_on_subdirs(Calo/CaloInterfaces Calo/CaloUtils + CaloFuture/CaloFutureInterfaces + CaloFuture/CaloFutureUtils Det/CaloDet Event/RecEvent GaudiAlg @@ -19,7 +21,7 @@ include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS}) gaudi_add_module(GlobalReco src/*.cpp INCLUDE_DIRS Tr/TrackInterfaces - LINK_LIBRARIES CaloUtils CaloDetLib RecEvent GaudiAlgLib RelationsLib) + LINK_LIBRARIES CaloUtils CaloFutureUtils CaloDetLib RecEvent GaudiAlgLib RelationsLib) gaudi_install_python_modules() diff --git a/Rec/GlobalReco/python/GlobalReco/Configuration.py b/Rec/GlobalReco/python/GlobalReco/Configuration.py index 9993bda2fcacb0c668ac6233c7f250de6186417f..e930556580c80692339b4855361c79259d4d56e1 100644 --- a/Rec/GlobalReco/python/GlobalReco/Configuration.py +++ b/Rec/GlobalReco/python/GlobalReco/Configuration.py @@ -68,6 +68,11 @@ class GlobalRecoConf(LHCbConfigurableUser): ChargedProtoParticleAddHcalInfo, ChargedProtoParticleAddPrsInfo, ChargedProtoParticleAddSpdInfo, + FutureChargedProtoParticleAddEcalInfo, + FutureChargedProtoParticleAddBremInfo, + FutureChargedProtoParticleAddHcalInfo, + FutureChargedProtoParticleAddPrsInfo, + FutureChargedProtoParticleAddSpdInfo, ChargedProtoParticleAddVeloInfo, ChargedProtoCombineDLLsAlg, DelegatingTrackSelector ) @@ -83,9 +88,14 @@ class GlobalRecoConf(LHCbConfigurableUser): # Add PID information rich = ChargedProtoParticleAddRichInfo("ChargedProtoPAddRich") muon = ChargedProtoParticleAddMuonInfo("ChargedProtoPAddMuon") - ecal = ChargedProtoParticleAddEcalInfo("ChargedProtoPAddEcal") - brem = ChargedProtoParticleAddBremInfo("ChargedProtoPAddBrem") - hcal = ChargedProtoParticleAddHcalInfo("ChargedProtoPAddHcal") + if self.getProp("NoSpdPrs") : + ecal = FutureChargedProtoParticleAddEcalInfo("FutureChargedProtoPAddEcal") + brem = FutureChargedProtoParticleAddBremInfo("FutureChargedProtoPAddBrem") + hcal = FutureChargedProtoParticleAddHcalInfo("FutureChargedProtoPAddHcal") + else: + ecal = ChargedProtoParticleAddEcalInfo("ChargedProtoPAddEcal") + brem = ChargedProtoParticleAddBremInfo("ChargedProtoPAddBrem") + hcal = ChargedProtoParticleAddHcalInfo("ChargedProtoPAddHcal") velo = ChargedProtoParticleAddVeloInfo("ChargedProtoPAddVeloDEDX") # Fill the Combined DLL information in the charged protoparticles combine = ChargedProtoCombineDLLsAlg("ChargedProtoPCombDLLs") @@ -98,11 +108,15 @@ class GlobalRecoConf(LHCbConfigurableUser): cseq.Members += [ velo, rich,muon,combine ] # Neutrals - from Configurables import NeutralProtoPAlg + from Configurables import NeutralProtoPAlg, FutureNeutralProtoPAlg nseq = GaudiSequencer("NeutralProtoParticles") seq.Members += [nseq] - neutral = NeutralProtoPAlg("NeutralProtoPMaker") - nseq.Members += [ neutral ] + if self.getProp("NoSpdPrs") : + neutral = FutureNeutralProtoPAlg("FutureNeutralProtoPMaker") + nseq.Members += [ neutral ] + else: + neutral = NeutralProtoPAlg("NeutralProtoPMaker") + nseq.Members += [ neutral ] # Set output levels if self.isPropertySet("OutputLevel"): diff --git a/Rec/GlobalReco/src/FutureChargedProtoParticleAddBremInfo.cpp b/Rec/GlobalReco/src/FutureChargedProtoParticleAddBremInfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7cfff2e7895702107c84fac989e054b6ea372dbf --- /dev/null +++ b/Rec/GlobalReco/src/FutureChargedProtoParticleAddBremInfo.cpp @@ -0,0 +1,166 @@ + +//----------------------------------------------------------------------------- +/** @file ChargedProtoParticleAddBremInfo.cpp + * + * Implementation file for algorithm ChargedProtoParticleAddBremInfo + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 28/08/2009 + */ +//----------------------------------------------------------------------------- + +// local +#include "FutureChargedProtoParticleAddBremInfo.h" + +//----------------------------------------------------------------------------- + +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( FutureChargedProtoParticleAddBremInfo ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +FutureChargedProtoParticleAddBremInfo:: +FutureChargedProtoParticleAddBremInfo( const std::string& name, + ISvcLocator* pSvcLocator) + : FutureChargedProtoParticleCALOFUTUREBaseAlg ( name , pSvcLocator ) +{ + // default locations from context() + + using namespace LHCb::CaloFuture2Track; + using namespace LHCb::CaloFutureIdLocation; + using namespace LHCb::CaloFutureAlgUtils; + + m_inBremPath = PathFromContext( context() , InBrem ); + m_bremMatchPath = PathFromContext( context() , BremMatch ); + m_bremChi2Path = PathFromContext( context() , BremChi2 ); + m_bremPIDePath = PathFromContext( context() , BremPIDe ); + m_protoPath = LHCb::ProtoParticleLocation::Charged ; + + declareProperty("InputInBremLocation" , m_inBremPath ); + declareProperty("InputBremMatchLocation" , m_bremMatchPath ); + declareProperty("InputBremChi2Location" , m_bremChi2Path ); + declareProperty("InputBremPIDeLocation" , m_bremPIDePath ); + declareProperty("ProtoParticleLocation" , m_protoPath ); + +} + +//============================================================================= +// Main execution +//============================================================================= +StatusCode FutureChargedProtoParticleAddBremInfo::execute() +{ + // Load the Brem data + const auto sc = getBremData(); + if ( !sc ) + { + return Warning( "No BREM data -> ProtoParticles will not be changed.", StatusCode::SUCCESS ); + } + + // ProtoParticle container + auto * protos = getIfExists<LHCb::ProtoParticles>(m_protoPath); + if ( !protos ) + { + if( msgLevel(MSG::DEBUG) ) debug() << "No existing ProtoParticle container at " + << m_protoPath<<" thus do nothing."<<endmsg; + return StatusCode::SUCCESS; + } + + // Loop over proto particles and fill brem info + for ( auto * proto : *protos ) { addBrem(proto); } + + if ( counterStat->isQuiet() ) + counter("BremPIDs("+context()+") ==> " + m_protoPath )+= protos->size(); + + return StatusCode::SUCCESS; +} + +//============================================================================= + +//============================================================================= +// Loads the Calo Brem data +//============================================================================= +bool FutureChargedProtoParticleAddBremInfo::getBremData() +{ + const bool sc1 = loadCaloTable(m_InBremTable , m_inBremPath); + const bool sc2 = loadCaloTable(m_bremTrTable , m_bremMatchPath); + const bool sc3 = loadCaloTable(m_BremChi2Table, m_bremChi2Path); + const bool sc4 = loadCaloTable(m_dlleBremTable, m_bremPIDePath); + + const bool sc = sc1 && sc2 && sc3 && sc4; + if ( sc && msgLevel(MSG::DEBUG) ) debug() << "BREM PID SUCCESSFULLY LOADED" << endmsg; + + return sc; +} + +//============================================================================= +// Add Calo Brem info to the protoparticle +//============================================================================= +bool FutureChargedProtoParticleAddBremInfo::addBrem( LHCb::ProtoParticle * proto ) const +{ + // First remove existing BREM info + proto->removeCaloBremInfo(); + + // Add new info + + bool hasBremPID = false; + + const auto aRange = m_InBremTable -> relations ( proto->track() ) ; + if ( !aRange.empty() ) + { + hasBremPID = aRange.front().to(); + if ( hasBremPID ) + { + if ( msgLevel(MSG::VERBOSE) ) verbose() << " -> The Brem. extrapolated line is in Ecal acceptance" << endmsg; + proto->addInfo(LHCb::ProtoParticle::additionalInfo::InAccBrem , true ); + + // Get the highest weight associated brem. CaloHypo (3D matching) + const auto hRange = m_bremTrTable->inverse()->relations ( proto->track() ) ; + if ( !hRange.empty() ) + { + const auto * hypo = hRange.front().to(); + proto->addToCalo ( hypo ); + using namespace CaloFutureDataType; + proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloNeutralSpd, m_estimator->data(hypo, HypoSpdM ) > 0 ); + proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloNeutralPrs, m_estimator->data(hypo, HypoPrsE ) ); + proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloNeutralEcal, m_estimator->data(hypo, ClusterE ) ); + proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloBremMatch , m_estimator->data(hypo, BremMatch ) ); + proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloNeutralID , m_estimator->data(hypo, CellID ) ); + proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloNeutralHcal2Ecal , m_estimator->data(hypo, Hcal2Ecal ) ); + proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloNeutralE49 , m_estimator->data(hypo, E49 ) ); + } + + // Get the BremChi2 (intermediate) estimator + { + const auto vRange = m_BremChi2Table -> relations ( proto->track() ) ; + if ( !vRange.empty() ) { proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloBremChi2, vRange.front().to() ); } + } + + // Get the Brem DLL(e) + { + const auto vRange = m_dlleBremTable -> relations ( proto->track() ) ; + if ( !vRange.empty() ) { proto->addInfo(LHCb::ProtoParticle::additionalInfo::BremPIDe , vRange.front().to() ); } + } + + if ( msgLevel(MSG::VERBOSE) ) + verbose() << " -> BremStrahlung PID : " + << " Chi2-Brem =" << proto->info(LHCb::ProtoParticle::additionalInfo::CaloBremMatch, -999.) + << " BremChi2 =" << proto->info(LHCb::ProtoParticle::additionalInfo::CaloBremChi2, -999.) + << " Dlle (Brem) =" << proto->info(LHCb::ProtoParticle::additionalInfo::BremPIDe, -999.) + << " Spd Digits " << proto->info(LHCb::ProtoParticle::additionalInfo::CaloNeutralSpd, 0.) + << " Prs Digits " << proto->info(LHCb::ProtoParticle::additionalInfo::CaloNeutralPrs, 0.) + << " Ecal Cluster " << proto->info(LHCb::ProtoParticle::additionalInfo::CaloNeutralEcal, 0.) + << endmsg; + } + else + { + if ( msgLevel(MSG::VERBOSE) ) verbose() << " -> The Brem. extrapolated line is NOT in Ecal acceptance" << endmsg; + } + } + else + { + if ( msgLevel(MSG::VERBOSE) ) verbose() << " -> No entry for that track in the Brem acceptance table" << endmsg; + } + + return hasBremPID; +} diff --git a/Rec/GlobalReco/src/FutureChargedProtoParticleAddBremInfo.h b/Rec/GlobalReco/src/FutureChargedProtoParticleAddBremInfo.h new file mode 100644 index 0000000000000000000000000000000000000000..f42b9e31ee6bcaace460e460759e3f4bc6332338 --- /dev/null +++ b/Rec/GlobalReco/src/FutureChargedProtoParticleAddBremInfo.h @@ -0,0 +1,60 @@ + +//----------------------------------------------------------------------------- +/** @file ChargedProtoParticleAddBremInfo.h + * + * Header file for algorithm ChargedProtoParticleAddBremInfo + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 29/03/2006 + */ +//----------------------------------------------------------------------------- + +#ifndef GLOBALRECO_FutureChargedProtoParticleAddBremInfo_H +#define GLOBALRECO_FutureChargedProtoParticleAddBremInfo_H 1 + +// from Gaudi +#include "FutureChargedProtoParticleCALOFUTUREBaseAlg.h" + +/** @class FutureChargedProtoParticleAddBremInfo FutureChargedProtoParticleAddBremInfo.h + * + * Updates the CALO 'BREM' information stored in the ProtoParticles + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 28/08/2009 + */ + +class FutureChargedProtoParticleAddBremInfo final : public FutureChargedProtoParticleCALOFUTUREBaseAlg +{ + +public: + + /// Standard constructor + FutureChargedProtoParticleAddBremInfo( const std::string& name, ISvcLocator* pSvcLocator ); + + StatusCode execute() override; ///< Algorithm execution + +private: + + /// Load the Calo Brem tables + bool getBremData(); + + /// Add Calo Brem information to the given ProtoParticle + bool addBrem( LHCb::ProtoParticle * proto ) const; + +private: + + std::string m_protoPath; ///< Location of the ProtoParticles in the TES + + std::string m_inBremPath ; + std::string m_bremMatchPath ; + std::string m_bremChi2Path ; + std::string m_bremPIDePath ; + + const LHCb::CaloFuture2Track::ITrAccTable* m_InBremTable = nullptr; + const LHCb::CaloFuture2Track::IHypoTrTable2D* m_bremTrTable = nullptr; + const LHCb::CaloFuture2Track::ITrEvalTable* m_BremChi2Table = nullptr; + const LHCb::CaloFuture2Track::ITrEvalTable* m_dlleBremTable = nullptr; + +}; + +#endif // GLOBALRECO_FutureChargedProtoParticleAddBremInfo_H diff --git a/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.cpp b/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1ffe4ccc7bcc09e9816bd5d49eb05da298c0b0c0 --- /dev/null +++ b/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.cpp @@ -0,0 +1,225 @@ + +//----------------------------------------------------------------------------- +/** @file FutureChargedProtoParticleAddEcalInfo.cpp + * + * Implementation file for algorithm FutureChargedProtoParticleAddEcalInfo + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 28/08/2009 + */ +//----------------------------------------------------------------------------- + +// local +#include "FutureChargedProtoParticleAddEcalInfo.h" + +//----------------------------------------------------------------------------- + +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( FutureChargedProtoParticleAddEcalInfo ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +FutureChargedProtoParticleAddEcalInfo:: +FutureChargedProtoParticleAddEcalInfo( const std::string& name, + ISvcLocator* pSvcLocator) +: FutureChargedProtoParticleCALOFUTUREBaseAlg ( name , pSvcLocator ) +{ + // default locations from context() + + using namespace LHCb::CaloFuture2Track; + using namespace LHCb::CaloFutureIdLocation; + m_protoPath = LHCb::ProtoParticleLocation::Charged ; + m_inEcalPath = LHCb::CaloFutureAlgUtils::PathFromContext( context() , InEcal ); + m_electronMatchPath = LHCb::CaloFutureAlgUtils::PathFromContext( context() , ElectronMatch ); + m_clusterMatchPath = LHCb::CaloFutureAlgUtils::PathFromContext( context() , ClusterMatch ); + m_ecalChi2Path = LHCb::CaloFutureAlgUtils::PathFromContext( context() , EcalChi2 ); + m_ecalEPath = LHCb::CaloFutureAlgUtils::PathFromContext( context() , EcalE ); + m_clusterChi2Path = LHCb::CaloFutureAlgUtils::PathFromContext( context() , ClusChi2 ); + m_ecalPIDePath = LHCb::CaloFutureAlgUtils::PathFromContext( context() , EcalPIDe ); + m_ecalPIDmuPath = LHCb::CaloFutureAlgUtils::PathFromContext( context() , EcalPIDmu ); + declareProperty("InputInEcalLocation" , m_inEcalPath ); + declareProperty("InputElectronMatchLocation" , m_electronMatchPath ); + declareProperty("InputClusterMatchLocation" , m_clusterMatchPath ); + declareProperty("InputEcalChi2Location" , m_ecalChi2Path ); + declareProperty("InputEcalELocation" , m_ecalEPath ); + declareProperty("InputClusterChi2Location" , m_clusterChi2Path ); + declareProperty("InputEcalPIDeLocation" , m_ecalPIDePath ); + declareProperty("InputEcalPIDmuLocation" , m_ecalPIDmuPath ); + + // ProtoParticles + declareProperty( "ProtoParticleLocation", m_protoPath ); +} + +//============================================================================= +// Initialization +//============================================================================= +StatusCode FutureChargedProtoParticleAddEcalInfo::initialize() +{ + const StatusCode sc = FutureChargedProtoParticleCALOFUTUREBaseAlg::initialize(); + if ( sc.isFailure() ) return sc; + + // CaloElectron tool + //m_electron = tool<ICaloElectron>("CaloElectron","CaloElectron",this); + m_electron = tool<ICaloFutureElectron>("CaloFutureElectron","CaloFutureElectron",this); + + return sc; +} + +//============================================================================= +// Main execution +//============================================================================= +StatusCode FutureChargedProtoParticleAddEcalInfo::execute() +{ + // Load the ECAL data + const bool sc = getEcalData(); + if ( !sc ) + { + return Warning( "No ECAL data -> ProtoParticles will not be changed.", StatusCode::SUCCESS ); + } + + // ProtoParticle container + auto * protos = getIfExists<LHCb::ProtoParticles>(m_protoPath); + if ( !protos ) + { + if( msgLevel(MSG::DEBUG) ) debug() << "No existing ProtoParticle container at " + << m_protoPath<<" thus do nothing."<<endmsg; + return StatusCode::SUCCESS; + } + + // Loop over proto particles and update ECAL info + for ( auto * proto : *protos ) { addEcal(proto); } + + if ( counterStat->isQuiet() ) + counter("EcalPIDs("+context()+") ==> " + m_protoPath )+= protos->size(); + + return StatusCode::SUCCESS; +} + +//============================================================================= + +//============================================================================= +// Loads the Calo Ecal data +//============================================================================= +bool FutureChargedProtoParticleAddEcalInfo::getEcalData() +{ + const bool sc1 = loadCaloTable(m_InEcalTable , m_inEcalPath ); + const bool sc2 = loadCaloTable(m_elecTrTable , m_electronMatchPath); + const bool sc3 = loadCaloTable(m_clusTrTable , m_clusterMatchPath ); + const bool sc4 = loadCaloTable(m_EcalChi2Table, m_ecalChi2Path); + const bool sc5 = loadCaloTable(m_EcalETable , m_ecalEPath); + const bool sc6 = loadCaloTable(m_ClusChi2Table, m_clusterChi2Path); + const bool sc7 = loadCaloTable(m_dlleEcalTable, m_ecalPIDePath); + const bool sc8 = loadCaloTable(m_dllmuEcalTable,m_ecalPIDmuPath); + + const bool sc = sc1 && sc2 && sc3 && sc4 && sc5 && sc6 && sc7 && sc8; + if ( sc && msgLevel(MSG::DEBUG) ) debug() << "Ecal PID SUCCESSFULLY LOADED" << endmsg; + + return sc; +} + +//============================================================================= +// Add Calo Ecal info to the protoparticle +//============================================================================= +bool FutureChargedProtoParticleAddEcalInfo::addEcal( LHCb::ProtoParticle * proto ) const +{ + // First remove existing ECAL info + proto->removeCaloEcalInfo(); + + // Now add new ECAL info + + bool hasEcalPID = false; + + const auto aRange = m_InEcalTable -> relations ( proto->track() ) ; + if ( !aRange.empty() ) + { + hasEcalPID = aRange.front().to(); + + if( hasEcalPID ) + { + if ( msgLevel(MSG::VERBOSE) ) verbose() << " -> The track is in Ecal acceptance" << endmsg; + proto->addInfo(LHCb::ProtoParticle::additionalInfo::InAccEcal, true ); + + // Get the highest weight associated electron CaloHypo (3D matching) + const auto hRange = m_elecTrTable->inverse()->relations ( proto->track() ) ; + if ( !hRange.empty() ){ + + const auto * hypo = hRange.front().to(); + proto->addToCalo ( hypo ); + // CaloElectron->caloTrajectory must be after addToCalo + if ( electronTool()->set(proto) ){ + proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloTrajectoryL, electronTool()->caloTrajectoryL(CaloPlane::ShowerMax,"hypo") ); + proto->addInfo( LHCb::ProtoParticle::additionalInfo::CaloEoverP, electronTool()->eOverP() ); + } + + using namespace CaloFutureDataType; + proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloChargedSpd, m_estimator->data(hypo, HypoSpdM ) > 0 ); + proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloChargedPrs, m_estimator->data(hypo, HypoPrsE ) ); + proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloChargedEcal, m_estimator->data(hypo, ClusterE ) ); + proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloChargedID , m_estimator->data(hypo, CellID ) ); + proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloElectronMatch , hRange.front().weight() ); + } + + // Get the highest weight associated CaloCluster (2D matching) + const auto cRange = m_clusTrTable -> inverse() ->relations ( proto->track() ) ; + if ( !cRange.empty() ) { proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloTrMatch , cRange.front().weight() ); } + + // Get EcalE (intermediate) estimator + { + const auto vRange = m_EcalETable -> relations ( proto->track() ) ; + if ( !vRange.empty() ) { proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloEcalE , vRange.front().to() ); } + } + + // Get EcalChi2 (intermediate) estimator + { + const auto vRange = m_EcalChi2Table -> relations ( proto->track() ) ; + if ( !vRange.empty() ) { proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloEcalChi2, vRange.front().to() ); } + } + + // Get ClusChi2 (intermediate) estimator + { + const auto vRange = m_ClusChi2Table -> relations ( proto->track() ) ; + if ( !vRange.empty() ) { proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloClusChi2, vRange.front().to() ); } + } + + // Get Ecal DLL(e) + { + const auto vRange = m_dlleEcalTable -> relations ( proto->track() ) ; + if ( !vRange.empty() ) { proto->addInfo(LHCb::ProtoParticle::additionalInfo::EcalPIDe , vRange.front().to() ); } + } + + // Get Ecal DLL(mu) + { + const auto vRange = m_dllmuEcalTable -> relations ( proto->track() ) ; + if ( !vRange.empty() ) { proto->addInfo(LHCb::ProtoParticle::additionalInfo::EcalPIDmu , vRange.front().to() ); } + } + + if ( msgLevel(MSG::VERBOSE) ) + verbose() << " -> Ecal PID : " + << " Chi2-3D =" << proto->info(LHCb::ProtoParticle::additionalInfo::CaloElectronMatch, -999.) + << " Chi2-2D =" << proto->info(LHCb::ProtoParticle::additionalInfo::CaloTrMatch, -999.) + << " EcalE =" << proto->info(LHCb::ProtoParticle::additionalInfo::CaloEcalE , -999.) + << " ClusChi2 =" << proto->info(LHCb::ProtoParticle::additionalInfo::CaloClusChi2, -999.) + << " EcalChi2 =" << proto->info(LHCb::ProtoParticle::additionalInfo::CaloEcalChi2, -999.) + << " Dlle (Ecal) =" << proto->info(LHCb::ProtoParticle::additionalInfo::EcalPIDe, -999.) + << " Dllmu (Ecal) =" << proto->info(LHCb::ProtoParticle::additionalInfo::EcalPIDmu, -999.) + << " Spd Digits " << proto->info(LHCb::ProtoParticle::additionalInfo::CaloChargedSpd, 0.) + << " Prs Digits " << proto->info(LHCb::ProtoParticle::additionalInfo::CaloChargedPrs, 0.) + << " Spd Digits " << proto->info(LHCb::ProtoParticle::additionalInfo::CaloChargedSpd, 0.) + << " Ecal Cluster " << proto->info(LHCb::ProtoParticle::additionalInfo::CaloChargedEcal, 0.) + << " TrajectoryL " << proto->info(LHCb::ProtoParticle::additionalInfo::CaloTrajectoryL, 0.) + << endmsg; + + } + else + { + if ( msgLevel(MSG::VERBOSE) )verbose() << " -> The track is NOT in Ecal acceptance" << endmsg; + } + } + else + { + if ( msgLevel(MSG::VERBOSE) )verbose() << " -> No entry for that track in the Ecal acceptance table " << endmsg; + } + + return hasEcalPID; +} diff --git a/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.h b/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.h new file mode 100644 index 0000000000000000000000000000000000000000..3ac9e984c47851da822023b62d7332d8d7dd99ec --- /dev/null +++ b/Rec/GlobalReco/src/FutureChargedProtoParticleAddEcalInfo.h @@ -0,0 +1,74 @@ +//----------------------------------------------------------------------------- +/** @file FutureChargedProtoParticleAddEcalInfo.h + * + * Header file for algorithm FutureChargedProtoParticleAddEcalInfo + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 29/03/2006 + */ +//----------------------------------------------------------------------------- + +#ifndef GLOBALRECO_FutureChargedProtoParticleAddEcalInfo_H +#define GLOBALRECO_FutureChargedProtoParticleAddEcalInfo_H 1 + +#include "FutureChargedProtoParticleCALOFUTUREBaseAlg.h" +#include "CaloFutureUtils/ICaloFutureElectron.h" + +/** @class FutureChargedProtoParticleAddEcalInfo FutureChargedProtoParticleAddEcalInfo.h + * + * Updates the ECAL information stored in the ProtoParticles + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 28/08/2009 + */ + +class FutureChargedProtoParticleAddEcalInfo final : public FutureChargedProtoParticleCALOFUTUREBaseAlg +{ + +public: + + /// Standard constructor + FutureChargedProtoParticleAddEcalInfo( const std::string& name, ISvcLocator* pSvcLocator ); + + StatusCode initialize() override; ///< Algorithm initialization + StatusCode execute() override; ///< Algorithm execution + +private: + + /// Load the Calo Ecal tables + bool getEcalData(); + + /// Add Calo Ecal information to the given ProtoParticle + bool addEcal( LHCb::ProtoParticle * proto ) const; + + /// Access the electron tool + inline ICaloFutureElectron * electronTool() const noexcept { return m_electron; } + +private: + + std::string m_protoPath; ///< Location of the ProtoParticles in the TES + + std::string m_inEcalPath ; + std::string m_electronMatchPath ; + std::string m_clusterMatchPath ; + std::string m_ecalChi2Path ; + std::string m_ecalEPath ; + std::string m_clusterChi2Path ; + std::string m_ecalPIDePath ; + std::string m_ecalPIDmuPath ; + + const LHCb::CaloFuture2Track::ITrAccTable* m_InEcalTable = nullptr; + const LHCb::CaloFuture2Track::IHypoTrTable2D* m_elecTrTable = nullptr; + const LHCb::CaloFuture2Track::IClusTrTable2D* m_clusTrTable = nullptr; + const LHCb::CaloFuture2Track::ITrEvalTable* m_EcalChi2Table = nullptr; + const LHCb::CaloFuture2Track::ITrEvalTable* m_EcalETable = nullptr; + const LHCb::CaloFuture2Track::ITrEvalTable* m_ClusChi2Table = nullptr; + const LHCb::CaloFuture2Track::ITrEvalTable* m_dlleEcalTable = nullptr; + const LHCb::CaloFuture2Track::ITrEvalTable* m_dllmuEcalTable = nullptr; + + /// CaloElectron tool + ICaloFutureElectron * m_electron = nullptr; + +}; + +#endif // GLOBALRECO_FutureChargedProtoParticleAddEcalInfo_H diff --git a/Rec/GlobalReco/src/FutureChargedProtoParticleAddHcalInfo.cpp b/Rec/GlobalReco/src/FutureChargedProtoParticleAddHcalInfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2bfb3f2b34423ed61a3e5d8aade746926c49a3d0 --- /dev/null +++ b/Rec/GlobalReco/src/FutureChargedProtoParticleAddHcalInfo.cpp @@ -0,0 +1,149 @@ + +//----------------------------------------------------------------------------- +/** @file FutureChargedProtoParticleAddHcalInfo.cpp + * + * Implementation file for algorithm FutureChargedProtoParticleAddHcalInfo + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 28/08/2009 + */ +//----------------------------------------------------------------------------- + +// local +#include "FutureChargedProtoParticleAddHcalInfo.h" + +//----------------------------------------------------------------------------- + +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( FutureChargedProtoParticleAddHcalInfo ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +FutureChargedProtoParticleAddHcalInfo:: +FutureChargedProtoParticleAddHcalInfo( const std::string& name, + ISvcLocator* pSvcLocator) + : FutureChargedProtoParticleCALOFUTUREBaseAlg ( name , pSvcLocator ) +{ + // default locations from context() + + using namespace LHCb::CaloFuture2Track; + using namespace LHCb::CaloFutureIdLocation; + using namespace LHCb::CaloFutureAlgUtils; + + m_protoPath = LHCb::ProtoParticleLocation::Charged ; + m_inHcalPath = PathFromContext( context() , InHcal ); + m_hcalEPath = PathFromContext( context() , HcalE ); + m_hcalPIDePath = PathFromContext( context() , HcalPIDe ); + m_hcalPIDmuPath = PathFromContext( context() , HcalPIDmu ); + + declareProperty("ProtoParticleLocation" , m_protoPath ); + declareProperty("InputInHcalLocation" , m_inHcalPath ); + declareProperty("InputHcalELocation" , m_hcalEPath ); + declareProperty("InputHcalPIDeLocation" , m_hcalPIDePath ); + declareProperty("InputHcalPIDmuLocation" , m_hcalPIDmuPath ); +} + +//============================================================================= +// Main execution +//============================================================================= +StatusCode FutureChargedProtoParticleAddHcalInfo::execute() +{ + // Load the HCAL data + const bool sc = getHcalData(); + if ( !sc ) + { + return Warning( "No HCAL data -> ProtoParticles will not be changed.", StatusCode::SUCCESS ); + } + + // ProtoParticle container + auto * protos = getIfExists<LHCb::ProtoParticles>(m_protoPath); + if ( !protos ) + { + if( msgLevel(MSG::DEBUG) ) debug() << "No existing ProtoParticle container at " + << m_protoPath<<" thus do nothing."<<endmsg; + return StatusCode::SUCCESS; + } + + // Loop over proto particles and update HCAL info + for ( auto * proto : *protos ) { addHcal(proto); } + + if ( counterStat->isQuiet() ) + counter("HcalPIDs("+context()+") ==> " + m_protoPath )+= protos->size(); + + return StatusCode::SUCCESS; +} + +//============================================================================= + +//============================================================================= +// Loads the Calo Hcal data +//============================================================================= +bool FutureChargedProtoParticleAddHcalInfo::getHcalData() +{ + const bool sc1 = loadCaloTable(m_InHcalTable , m_inHcalPath); + const bool sc2 = loadCaloTable(m_HcalETable , m_hcalEPath); + const bool sc3 = loadCaloTable(m_dlleHcalTable , m_hcalPIDePath); + const bool sc4 = loadCaloTable(m_dllmuHcalTable, m_hcalPIDmuPath); + const bool sc = sc1 && sc2 && sc3 && sc4; + if ( sc && msgLevel(MSG::DEBUG) ) debug() << "HCAL PID SUCCESSFULLY LOADED" << endmsg; + return sc; +} + +//============================================================================= +// Add Calo Hcal info to the protoparticle +//============================================================================= +bool FutureChargedProtoParticleAddHcalInfo::addHcal( LHCb::ProtoParticle * proto ) const +{ + // clear HCAL info + proto->removeCaloHcalInfo(); + + bool hasHcalPID = false; + + const auto aRange = m_InHcalTable -> relations ( proto->track() ) ; + if ( !aRange.empty() ) + { + hasHcalPID = aRange.front().to(); + if( hasHcalPID ) + { + if ( msgLevel(MSG::VERBOSE) )verbose() << " -> The track is in Hcal acceptance" << endmsg; + proto->addInfo(LHCb::ProtoParticle::additionalInfo::InAccHcal, true ); + + // Get the HcalE (intermediate) estimator + { + const auto vRange = m_HcalETable -> relations ( proto->track() ) ; + if ( !vRange.empty() ) { proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloHcalE, vRange.front().to() ); } + } + + // Get the Hcal DLL(e) + { + const auto vRange = m_dlleHcalTable -> relations ( proto->track() ) ; + if ( !vRange.empty() ) { proto->addInfo(LHCb::ProtoParticle::additionalInfo::HcalPIDe , vRange.front().to() ); } + } + + // Get the Hcal DLL(mu) + { + const auto vRange = m_dllmuHcalTable -> relations ( proto->track() ) ; + if ( !vRange.empty() ) { proto->addInfo(LHCb::ProtoParticle::additionalInfo::HcalPIDmu , vRange.front().to() ); } + } + + if ( msgLevel(MSG::VERBOSE) ) + verbose() << " -> Hcal PID : " + << " HcalE =" << proto->info(LHCb::ProtoParticle::additionalInfo::CaloHcalE, -999.) + << " Dlle (Hcal) =" << proto->info(LHCb::ProtoParticle::additionalInfo::HcalPIDe, -999.) + << " Dllmu (Hcal) =" << proto->info(LHCb::ProtoParticle::additionalInfo::HcalPIDmu, -999.) + << endmsg; + + } + else + { + if ( msgLevel(MSG::VERBOSE) )verbose() << " -> The track is NOT in Hcal acceptance" << endmsg; + } + } + else + { + if ( msgLevel(MSG::VERBOSE) )verbose() << " -> No entry for that track in the Hcal acceptance table" << endmsg; + } + + return hasHcalPID; +} diff --git a/Rec/GlobalReco/src/FutureChargedProtoParticleAddHcalInfo.h b/Rec/GlobalReco/src/FutureChargedProtoParticleAddHcalInfo.h new file mode 100644 index 0000000000000000000000000000000000000000..2693afb36ddcf8091bc53aff8c7d017010343d04 --- /dev/null +++ b/Rec/GlobalReco/src/FutureChargedProtoParticleAddHcalInfo.h @@ -0,0 +1,60 @@ + +//----------------------------------------------------------------------------- +/** @file FutureChargedProtoParticleAddHcalInfo.h + * + * Header file for algorithm FutureChargedProtoParticleAddHcalInfo + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 29/03/2006 + */ +//----------------------------------------------------------------------------- + +#ifndef GLOBALRECO_FutureChargedProtoParticleAddHcalInfo_H +#define GLOBALRECO_FutureChargedProtoParticleAddHcalInfo_H 1 + +// from Gaudi +#include "FutureChargedProtoParticleCALOFUTUREBaseAlg.h" + +/** @class FutureChargedProtoParticleAddHcalInfo FutureChargedProtoParticleAddHcalInfo.h + * + * Updates the CALO HCAL information stored in the ProtoParticles + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 28/08/2009 + */ + +class FutureChargedProtoParticleAddHcalInfo final : public FutureChargedProtoParticleCALOFUTUREBaseAlg +{ + +public: + + /// Standard constructor + FutureChargedProtoParticleAddHcalInfo( const std::string& name, ISvcLocator* pSvcLocator ); + + StatusCode execute() override; ///< Algorithm execution + +private: + + /// Load the Calo Hcal tables + bool getHcalData(); + + /// Add Calo Hcal information to the given ProtoParticle + bool addHcal( LHCb::ProtoParticle * proto ) const; + +private: + + std::string m_protoPath; ///< Location of the ProtoParticles in the TES + + std::string m_inHcalPath ; + std::string m_hcalEPath ; + std::string m_hcalPIDePath ; + std::string m_hcalPIDmuPath ; + + const LHCb::CaloFuture2Track::ITrAccTable* m_InHcalTable = nullptr; + const LHCb::CaloFuture2Track::ITrEvalTable* m_HcalETable = nullptr; + const LHCb::CaloFuture2Track::ITrEvalTable* m_dlleHcalTable = nullptr; + const LHCb::CaloFuture2Track::ITrEvalTable* m_dllmuHcalTable = nullptr; + +}; + +#endif // GLOBALRECO_FutureChargedProtoParticleAddHcalInfo_H diff --git a/Rec/GlobalReco/src/FutureChargedProtoParticleAddPrsInfo.cpp b/Rec/GlobalReco/src/FutureChargedProtoParticleAddPrsInfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1c867aa62f19aa3bcf79e3eb219530ccea621853 --- /dev/null +++ b/Rec/GlobalReco/src/FutureChargedProtoParticleAddPrsInfo.cpp @@ -0,0 +1,141 @@ + +//----------------------------------------------------------------------------- +/** @file FutureChargedProtoParticleAddPrsInfo.cpp + * + * Implementation file for algorithm FutureChargedProtoParticleAddPrsInfo + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 28/08/2009 + */ +//----------------------------------------------------------------------------- + +// local +#include "FutureChargedProtoParticleAddPrsInfo.h" + +//----------------------------------------------------------------------------- + +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( FutureChargedProtoParticleAddPrsInfo ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +FutureChargedProtoParticleAddPrsInfo:: +FutureChargedProtoParticleAddPrsInfo( const std::string& name, + ISvcLocator* pSvcLocator) + : FutureChargedProtoParticleCALOFUTUREBaseAlg ( name , pSvcLocator ) +{ + // default locations from context() + + using namespace LHCb::CaloFuture2Track; + using namespace LHCb::CaloFutureIdLocation; + using namespace LHCb::CaloFutureAlgUtils; + + m_protoPath = LHCb::ProtoParticleLocation::Charged ; + m_inPrsPath = PathFromContext( context() , InPrs ); + m_prsEPath = PathFromContext( context() , PrsE ); + m_prsPIDePath = PathFromContext( context() , PrsPIDe ); + + declareProperty("ProtoParticleLocation" , m_protoPath ); + declareProperty("InputInPrsLocation" , m_inPrsPath ); + declareProperty("InputPrsELocation" , m_prsEPath ); + declareProperty("InputPrsPIDeLocation" , m_prsPIDePath ); + +} + +//============================================================================= +// Main execution +//============================================================================= +StatusCode FutureChargedProtoParticleAddPrsInfo::execute() +{ + // Load the Brem data + const bool sc = getPrsData(); + if ( !sc ) + { + return Warning( "No BREM data -> ProtoParticles will not be changed.", StatusCode::SUCCESS ); + } + + // ProtoParticle container + auto * protos = getIfExists<LHCb::ProtoParticles>(m_protoPath); + if ( !protos ) + { + if ( msgLevel(MSG::DEBUG) ) debug() << "No existing ProtoParticle container at " + << m_protoPath<<" thus do nothing."<<endmsg; + return StatusCode::SUCCESS; + } + + // Loop over proto particles and update PRS info + for ( auto * proto : *protos ) { addPrs(proto); } + + if ( counterStat->isQuiet() ) counter("PrsPIDs("+context()+") ==> " + m_protoPath )+= protos->size(); + + return StatusCode::SUCCESS; +} + +//============================================================================= + +//============================================================================= +// Loads the Calo Prs data +//============================================================================= +bool FutureChargedProtoParticleAddPrsInfo::getPrsData() +{ + const bool sc1 = loadCaloTable(m_InPrsTable , m_inPrsPath); + const bool sc2 = loadCaloTable(m_PrsETable , m_prsEPath); + const bool sc3 = loadCaloTable(m_dllePrsTable, m_prsPIDePath); + const bool sc = sc1 && sc2 && sc3; + if ( sc && msgLevel(MSG::DEBUG) ) debug() << "PRS PID SUCCESSFULLY LOADED" << endmsg; + return sc; +} + +//============================================================================= +// Add Calo Prs info to the protoparticle +//============================================================================= +bool FutureChargedProtoParticleAddPrsInfo::addPrs( LHCb::ProtoParticle * proto ) const +{ + // clear PRS info + proto->removeCaloPrsInfo(); + + // Add new info + + bool hasPrsPID = false; + + const auto aRange = m_InPrsTable -> relations ( proto->track() ) ; + if( !aRange.empty() ) + { + hasPrsPID = aRange.front().to(); + if( hasPrsPID ) + { + if ( msgLevel(MSG::VERBOSE) )verbose() << " -> The track is in Prs acceptance" << endmsg; + proto->addInfo(LHCb::ProtoParticle::additionalInfo::InAccPrs , true ); + + // Get the PrsE (intermediate) estimator + { + const auto vRange = m_PrsETable -> relations ( proto->track() ) ; + if ( !vRange.empty() ) { proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloPrsE, vRange.front().to() ); } + } + + // Get the Prs DLL(e) + { + const auto vRange = m_dllePrsTable -> relations ( proto->track() ) ; + if ( !vRange.empty() ) { proto->addInfo(LHCb::ProtoParticle::additionalInfo::PrsPIDe , vRange.front().to() ); } + } + + if ( msgLevel(MSG::VERBOSE) ) + verbose() << " -> Prs PID : " + << " PrsE =" << proto->info(LHCb::ProtoParticle::additionalInfo::CaloPrsE, -999.) + << " Dlle (Prs) =" << proto->info(LHCb::ProtoParticle::additionalInfo::PrsPIDe , -999.) + << endmsg; + + } + else + { + if ( msgLevel(MSG::VERBOSE) )verbose() << " -> The track is NOT in Prs acceptance" << endmsg; + } + } + else + { + if ( msgLevel(MSG::VERBOSE) )verbose() << " -> No entry for that track in the Prs acceptance table" << endmsg; + } + + return hasPrsPID; +} diff --git a/Rec/GlobalReco/src/FutureChargedProtoParticleAddPrsInfo.h b/Rec/GlobalReco/src/FutureChargedProtoParticleAddPrsInfo.h new file mode 100644 index 0000000000000000000000000000000000000000..5119f576c10504ae31feb45c48197bc6d3e304b3 --- /dev/null +++ b/Rec/GlobalReco/src/FutureChargedProtoParticleAddPrsInfo.h @@ -0,0 +1,58 @@ + +//----------------------------------------------------------------------------- +/** @file FutureChargedProtoParticleAddPrsInfo.h + * + * Header file for algorithm FutureChargedProtoParticleAddPrsInfo + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 29/03/2006 + */ +//----------------------------------------------------------------------------- + +#ifndef GLOBALRECO_FutureChargedProtoParticleAddPrsInfo_H +#define GLOBALRECO_FutureChargedProtoParticleAddPrsInfo_H 1 + +// from Gaudi +#include "FutureChargedProtoParticleCALOFUTUREBaseAlg.h" + +/** @class FutureChargedProtoParticleAddPrsInfo FutureChargedProtoParticleAddPrsInfo.h + * + * Updates the CALO 'BREM' information stored in the ProtoParticles + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 28/08/2009 + */ + +class FutureChargedProtoParticleAddPrsInfo final : public FutureChargedProtoParticleCALOFUTUREBaseAlg +{ + +public: + + /// Standard constructor + FutureChargedProtoParticleAddPrsInfo( const std::string& name, ISvcLocator* pSvcLocator ); + + StatusCode execute() override; ///< Algorithm execution + +private: + + /// Load the Calo Prs tables + bool getPrsData(); + + /// Add Calo Prs information to the given ProtoParticle + bool addPrs( LHCb::ProtoParticle * proto ) const; + +private: + + std::string m_protoPath; ///< Location of the ProtoParticles in the TES + + std::string m_inPrsPath ; + std::string m_prsEPath ; + std::string m_prsPIDePath ; + + const LHCb::CaloFuture2Track::ITrAccTable* m_InPrsTable = nullptr; + const LHCb::CaloFuture2Track::ITrEvalTable* m_PrsETable = nullptr; + const LHCb::CaloFuture2Track::ITrEvalTable* m_dllePrsTable = nullptr; + +}; + +#endif // GLOBALRECO_FutureChargedProtoParticleAddPrsInfo_H diff --git a/Rec/GlobalReco/src/FutureChargedProtoParticleAddSpdInfo.cpp b/Rec/GlobalReco/src/FutureChargedProtoParticleAddSpdInfo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..95cdb941f3c70719ed46dad6ffacbff9f736d5b4 --- /dev/null +++ b/Rec/GlobalReco/src/FutureChargedProtoParticleAddSpdInfo.cpp @@ -0,0 +1,128 @@ + +//----------------------------------------------------------------------------- +/** @file FutureChargedProtoParticleAddSpdInfo.cpp + * + * Implementation file for algorithm FutureChargedProtoParticleAddSpdInfo + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 28/08/2009 + */ +//----------------------------------------------------------------------------- + +// local +#include "FutureChargedProtoParticleAddSpdInfo.h" + +//----------------------------------------------------------------------------- + +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( FutureChargedProtoParticleAddSpdInfo ) + +//============================================================================= +// Standard constructor, initializes variables +//============================================================================= +FutureChargedProtoParticleAddSpdInfo:: +FutureChargedProtoParticleAddSpdInfo( const std::string& name, + ISvcLocator* pSvcLocator) + : FutureChargedProtoParticleCALOFUTUREBaseAlg ( name , pSvcLocator ) +{ + // default locations from context() + + using namespace LHCb::CaloFuture2Track; + using namespace LHCb::CaloFutureIdLocation; + using namespace LHCb::CaloFutureAlgUtils; + + m_protoPath = LHCb::ProtoParticleLocation::Charged ; + m_inSpdPath = PathFromContext( context() , InSpd ); + m_spdEPath = PathFromContext( context() , SpdE ); + + declareProperty("ProtoParticleLocation" , m_protoPath ); + declareProperty("InputInSpdLocation" , m_inSpdPath ); + declareProperty("InputSpdELocation" , m_spdEPath ); +} + +//============================================================================= +// Main execution +//============================================================================= +StatusCode FutureChargedProtoParticleAddSpdInfo::execute() +{ + // Load the Brem data + const bool sc = getSpdData(); + if ( !sc ) + { + return Warning( "No CALO SPD data -> ProtoParticles will not be changed.", + StatusCode::SUCCESS ); + } + + // ProtoParticle container + auto * protos = getIfExists<LHCb::ProtoParticles>(m_protoPath); + if ( !protos ) + { + if ( msgLevel(MSG::DEBUG) ) debug() << "No existing ProtoParticle container at " + << m_protoPath<<" thus do nothing."<<endmsg; + return StatusCode::SUCCESS; + } + + // Loop over proto particles and update SPD info + for ( auto * proto : *protos ) { addSpd(proto); } + + if ( counterStat->isQuiet() ) + counter("SpdPIDs("+context()+") ==> " + m_protoPath )+= protos->size(); + + return StatusCode::SUCCESS; +} + +//============================================================================= + +//============================================================================= +// Loads the Calo Spd data +//============================================================================= +bool FutureChargedProtoParticleAddSpdInfo::getSpdData() +{ + const bool sc1 = loadCaloTable(m_InSpdTable , m_inSpdPath); + const bool sc2 = loadCaloTable(m_SpdETable , m_spdEPath ); + const bool sc = sc1 && sc2; + if ( sc && msgLevel(MSG::DEBUG) ) debug() << "SPD PID SUCCESSFULLY LOADED" << endmsg; + return sc; +} + +//============================================================================= +// Add Calo Spd info to the protoparticle +//============================================================================= +bool FutureChargedProtoParticleAddSpdInfo::addSpd( LHCb::ProtoParticle * proto ) const +{ + // clear SPD info + proto->removeCaloSpdInfo(); + + bool hasSpdPID = false; + + const auto aRange = m_InSpdTable -> relations ( proto->track() ) ; + if ( !aRange.empty() ) + { + hasSpdPID = aRange.front().to(); + if ( hasSpdPID ) + { + if ( msgLevel(MSG::VERBOSE) )verbose() << " -> The track is in Spd acceptance" << endmsg; + proto->addInfo(LHCb::ProtoParticle::additionalInfo::InAccSpd , true ); + + // Get the PrsE (intermediate) estimator + const auto vRange = m_SpdETable -> relations ( proto->track() ) ; + if ( !vRange.empty() ) { proto->addInfo(LHCb::ProtoParticle::additionalInfo::CaloSpdE, vRange.front().to() ); } + + if ( msgLevel(MSG::VERBOSE) ) + verbose() << " -> Spd PID : " + << " SpdE =" << proto->info(LHCb::ProtoParticle::additionalInfo::CaloSpdE, -999.) + << endmsg; + + } + else + { + if ( msgLevel(MSG::VERBOSE) ) verbose() << " -> The track is NOT in Spd acceptance" << endmsg; + } + } + else + { + if ( msgLevel(MSG::VERBOSE) ) verbose() << " -> No entry for that track in the Spd acceptance table" << endmsg; + } + + return hasSpdPID; +} diff --git a/Rec/GlobalReco/src/FutureChargedProtoParticleAddSpdInfo.h b/Rec/GlobalReco/src/FutureChargedProtoParticleAddSpdInfo.h new file mode 100644 index 0000000000000000000000000000000000000000..01de1e1e1fb004da060604eb7aaa3250118cd3fe --- /dev/null +++ b/Rec/GlobalReco/src/FutureChargedProtoParticleAddSpdInfo.h @@ -0,0 +1,56 @@ + +//----------------------------------------------------------------------------- +/** @file FutureChargedProtoParticleAddSpdInfo.h + * + * Header file for algorithm FutureChargedProtoParticleAddSpdInfo + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 29/03/2006 + */ +//----------------------------------------------------------------------------- + +#ifndef GLOBALRECO_FutureChargedProtoParticleAddSpdInfo_H +#define GLOBALRECO_FutureChargedProtoParticleAddSpdInfo_H 1 + +// from Gaudi +#include "FutureChargedProtoParticleCALOFUTUREBaseAlg.h" + +/** @class FutureChargedProtoParticleAddSpdInfo FutureChargedProtoParticleAddSpdInfo.h + * + * Updates the CALO SPD information stored in the ProtoParticles + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 28/08/2009 + */ + +class FutureChargedProtoParticleAddSpdInfo final : public FutureChargedProtoParticleCALOFUTUREBaseAlg +{ + +public: + + /// Standard constructor + FutureChargedProtoParticleAddSpdInfo( const std::string& name, ISvcLocator* pSvcLocator ); + + StatusCode execute() override; ///< Algorithm execution + +private: + + /// Load the Calo Spd tables + bool getSpdData(); + + /// Add Calo Spd information to the given ProtoParticle + bool addSpd( LHCb::ProtoParticle * proto ) const; + +private: + + std::string m_protoPath; ///< Location of the ProtoParticles in the TES + + std::string m_inSpdPath ; + std::string m_spdEPath ; + + const LHCb::CaloFuture2Track::ITrAccTable* m_InSpdTable = nullptr; + const LHCb::CaloFuture2Track::ITrEvalTable* m_SpdETable = nullptr; + +}; + +#endif // GLOBALRECO_FutureChargedProtoParticleAddSpdInfo_H diff --git a/Rec/GlobalReco/src/FutureChargedProtoParticleCALOFUTUREBaseAlg.cpp b/Rec/GlobalReco/src/FutureChargedProtoParticleCALOFUTUREBaseAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1fb7f88c2e0dfc480dc80a3cad6b1fe50882193f --- /dev/null +++ b/Rec/GlobalReco/src/FutureChargedProtoParticleCALOFUTUREBaseAlg.cpp @@ -0,0 +1,28 @@ +//----------------------------------------------------------------------------- +/** @file FutureChargedProtoParticleCALOFUTUREBaseAlg.cpp + * + * Implementation file for algorithm FutureChargedProtoParticleCALOFUTUREBaseAlg + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 28/08/2009 + */ +//----------------------------------------------------------------------------- + +// local +#include "FutureChargedProtoParticleCALOFUTUREBaseAlg.h" + +//----------------------------------------------------------------------------- + +//============================================================================= +// Initialization +//============================================================================= +StatusCode FutureChargedProtoParticleCALOFUTUREBaseAlg::initialize() +{ + const StatusCode sc = GaudiAlgorithm::initialize(); + if ( sc.isFailure() ) return sc; + + counterStat = tool<IFutureCounterLevel>("FutureCounterLevel"); + m_estimator = tool<ICaloFutureHypoEstimator>("CaloFutureHypoEstimator","CaloFutureHypoEstimator",this); + + return sc; +} diff --git a/Rec/GlobalReco/src/FutureChargedProtoParticleCALOFUTUREBaseAlg.h b/Rec/GlobalReco/src/FutureChargedProtoParticleCALOFUTUREBaseAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..abb781a29a16302cfc0c662db65c3a54d9c4090d --- /dev/null +++ b/Rec/GlobalReco/src/FutureChargedProtoParticleCALOFUTUREBaseAlg.h @@ -0,0 +1,72 @@ +//----------------------------------------------------------------------------- +/** @file FutureChargedProtoParticleCALOFUTUREBaseAlg.h + * + * Header file for algorithm FutureChargedProtoParticleCALOFUTUREBaseAlg + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 29/03/2006 + */ +//----------------------------------------------------------------------------- + +#ifndef GLOBALRECO_FutureChargedProtoParticleCALOFUTUREBaseAlg_H +#define GLOBALRECO_FutureChargedProtoParticleCALOFUTUREBaseAlg_H 1 + +// from Gaudi +#include "GaudiAlg/GaudiAlgorithm.h" + +// Event +#include "Event/ProtoParticle.h" + +// from CaloUtils +#include "CaloFutureUtils/CaloFuture2Track.h" +#include "Event/CaloDataFunctor.h" +#include "CaloFutureUtils/CaloFutureAlgUtils.h" + +// Relations +#include "Relations/IRelation.h" +#include "Relations/IRelationWeighted2D.h" +#include "CaloFutureInterfaces/ICaloFutureHypoEstimator.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" + +/** @class FutureChargedProtoParticleCALOFUTUREBaseAlg FutureChargedProtoParticleCALOFUTUREBaseAlg.h + * + * Base class for ProtoParticle algorithms that add CALOFUTURE information + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 28/08/2009 + */ + +class FutureChargedProtoParticleCALOFUTUREBaseAlg : public GaudiAlgorithm +{ + +public: + + /// Standard constructor + using GaudiAlgorithm::GaudiAlgorithm; + + StatusCode initialize() override; ///< Algorithm initialization + +protected: + IFutureCounterLevel* counterStat; + + /// Loads a CALOFUTURE relations table + template < typename TYPE > + inline bool loadCaloTable( TYPE *& table, const std::string & location ) const + { + table = getIfExists<TYPE>( location ); + if ( !table ) + { + Warning("No CALOFUTURE "+System::typeinfoName(typeid(TYPE))+ + " table at '"+location+"'", StatusCode::SUCCESS ).ignore(); + } + return ( nullptr != table ); + } + +protected: + + // Add extra info from CaloDigits (Spd+Prs) + ICaloFutureHypoEstimator * m_estimator = nullptr; + +}; + +#endif // GLOBALRECO_FutureChargedProtoParticleCALOFUTUREBaseAlg_H diff --git a/Rec/GlobalReco/src/FutureNeutralProtoPAlg.cpp b/Rec/GlobalReco/src/FutureNeutralProtoPAlg.cpp new file mode 100644 index 0000000000000000000000000000000000000000..41e9bfb05b4fb8b905520237018f0795fbc722bc --- /dev/null +++ b/Rec/GlobalReco/src/FutureNeutralProtoPAlg.cpp @@ -0,0 +1,248 @@ +// ============================================================================ +// Include files +// ============================================================================ +#include "FutureNeutralProtoPAlg.h" +// ============================================================================ +/** @file + * Implementation file for class FutureNeutralProtoPAlg + * @date 2006-06-09 + * @author Olivier Deschamps + */ +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( FutureNeutralProtoPAlg ) +// ============================================================================ +// Standard constructor, initializes variables +// ============================================================================ +FutureNeutralProtoPAlg::FutureNeutralProtoPAlg( const std::string& name, + ISvcLocator* pSvcLocator) +: GaudiAlgorithm ( name , pSvcLocator ) +{ + // declare the properties + declareProperty ( "HyposLocations" , m_hyposLocations ) ; + declareProperty ( "ProtoParticleLocation" , m_protoLocation ) ; + declareProperty ( "LightMode" , m_light_mode = false, + "Use 'light' mode and do not collect all information. Useful for Calibration." ) ; + + // default location from context() + using namespace LHCb::CaloHypoLocation; + m_hyposLocations.push_back( LHCb::CaloFutureAlgUtils::PathFromContext( context() , MergedPi0s ) ) ; // put it 1st to speed-up photon mass retrieval + m_hyposLocations.push_back( LHCb::CaloFutureAlgUtils::PathFromContext( context() , Photons ) ) ; + m_hyposLocations.push_back( LHCb::CaloFutureAlgUtils::PathFromContext( context() , SplitPhotons ) ) ; + // m_protoLocation = LHCb::CaloFutureAlgUtils::PathFromContext( flag , LHCb::ProtoParticleLocation::Neutrals ); + m_protoLocation = LHCb::ProtoParticleLocation::Neutrals ; +} +// ============================================================================ +// Initialization +// ============================================================================ +StatusCode FutureNeutralProtoPAlg::initialize() +{ + const StatusCode sc = GaudiAlgorithm::initialize(); // must be executed first + if ( sc.isFailure() ) return sc; // error printed already by GaudiAlgorithm + if( msgLevel(MSG::DEBUG) ) debug() << "==> Initialize" << endmsg; + + for ( const auto & loc : m_hyposLocations ) + { info() << " Hypothesis loaded from " << loc << endmsg; } + + counterStat = tool<IFutureCounterLevel>("FutureCounterLevel"); + + if ( lightMode() ) + info() << "FutureNeutral protoparticles will be created in 'Light' Mode" << endmsg ; + + m_estimator = tool<ICaloFutureHypoEstimator>("CaloFutureHypoEstimator","CaloFutureHypoEstimator",this); + m_estimator->hypo2CaloFuture()->_setProperty("Seed", "false").ignore(); + m_estimator->hypo2CaloFuture()->_setProperty("PhotonLine", "true").ignore(); + m_estimator->hypo2CaloFuture()->_setProperty("AddNeighbors", "false").ignore(); + + m_mass.clear(); + m_setMass = false; + + return sc; +} + +double FutureNeutralProtoPAlg::getMass( const int cellCode ) const +{ + if( !m_setMass ) + { + Warning("You should process MergedPi0 protoparticles first to speed up retrieval of photon 'mass'",StatusCode::SUCCESS,1).ignore(); + // === storing masses + m_setMass = true; + using namespace LHCb::CaloHypoLocation; + const auto loc = LHCb::CaloFutureAlgUtils::PathFromContext( context() , MergedPi0s ); + const auto * hypos = getIfExists<LHCb::CaloHypos>( loc ); + if ( !hypos )return 0.; + for ( const auto& hypo : *hypos ) + { + if ( !hypo ) continue; + using namespace CaloFutureDataType; + const auto cellCode = int(m_estimator->data(hypo, CellID )); + m_mass[cellCode]=m_estimator->data(hypo, HypoM ); + } + } + const auto it = m_mass.find(cellCode); + return ( it == m_mass.end() ? 0.0 : it->second ); +} + +// ============================================================================ +// Main execution +// ============================================================================ +StatusCode FutureNeutralProtoPAlg::execute() +{ + + // create and register the output container + LHCb::ProtoParticles* protos = nullptr; + if ( !lightMode() && exist<LHCb::ProtoParticles>(m_protoLocation) ) + { + Warning( "Existing ProtoParticle container at " +m_protoLocation+ " found -> Will replace", StatusCode::SUCCESS, 1).ignore(); + if(counterStat->isQuiet())counter("Replaced Proto")+=1; + protos = get<LHCb::ProtoParticles>(m_protoLocation); + protos->clear(); + } + else + { + protos = new LHCb::ProtoParticles(); + put( protos , m_protoLocation ) ; + } + + if ( !protos )return Warning("FutureNeutralProto container points to NULL ",StatusCode::SUCCESS); + + // -- reset mass storage + m_mass.clear(); + m_setMass=false; + //------ loop over all caloHypo containers + for ( const auto & loc : m_hyposLocations ) + { + + //== Load the CaloHypo container + const auto * hypos = getIfExists<LHCb::CaloHypos>( loc ); + if ( ! hypos ) + { + if( msgLevel(MSG::DEBUG) ) debug()<< "No CaloHypo at '" << loc << "'" << endmsg ; + if ( counterStat->isQuiet() ) counter("No " + loc + " container") += 1; + continue; + } + + // no cluster mass storage when no MergedPi0 + if ( LHCb::CaloFutureAlgUtils::toUpper(loc).find("MERGED") != std::string::npos && + hypos->empty() ) { m_setMass = true; } + + if ( msgLevel(MSG::DEBUG) ) + debug() << "CaloHypo loaded at " << loc << " (# " << hypos->size()<<")"<< endmsg; + int count = 0 ; + + // == Loop over CaloHypos + for ( const auto * hypo : *hypos ) + { + if ( ! hypo ) { continue ; } + count++; + + // == create and store the corresponding ProtoParticle + auto * proto = new LHCb::ProtoParticle() ; + protos->insert( proto ) ; + + // == link CaloHypo to ProtoP + using namespace CaloFutureDataType; + proto-> addToCalo( hypo ) ; + + // ===== add data to protoparticle + if ( !lightMode() ) + { + std::ostringstream type(""); + type << hypo->hypothesis(); + const auto hypothesis = type.str(); + // extra data : + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralID ,hypo, CellID ); // seed cellID + // retrieve HypoM for photon + const auto cellCode = int(m_estimator->data(hypo, CellID )); + if( hypo -> hypothesis() == LHCb::CaloHypo::Hypothesis::Photon ) + { + const auto mass = getMass( cellCode ); + if( mass > 0. ) + { + proto->addInfo( LHCb::ProtoParticle::additionalInfo::ClusterMass, mass ); + if(counterStat->isVerbose())counter("ClusterMass for Photon") += mass; + } + } + else if ( hypo -> hypothesis() == LHCb::CaloHypo::Hypothesis::Pi0Merged ) + { + pushData(proto, LHCb::ProtoParticle::additionalInfo::ClusterMass, hypo, HypoM); + m_setMass=true; + m_mass[cellCode] = m_estimator->data(hypo, HypoM ); + } + if( hypo -> hypothesis() != LHCb::CaloHypo::Hypothesis::Pi0Merged ){ + pushData(proto, LHCb::ProtoParticle::additionalInfo::ClusterAsX, hypo, ClusterAsX, 0); + pushData(proto, LHCb::ProtoParticle::additionalInfo::ClusterAsY, hypo, ClusterAsY, 0); + } + + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralPrs, hypo, HypoPrsE ); + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralEcal,hypo, ClusterE ); + + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloTrMatch, hypo, ClusterMatch , +1.e+06 ); // ** input to neutralID + pushData(proto, LHCb::ProtoParticle::additionalInfo::ShowerShape, hypo, Spread); // ** input to neutralID && isPhoton (as Fr2) + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralSpd, hypo, HypoSpdM ); // ** input to neutralID + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralHcal2Ecal, hypo, Hcal2Ecal); // ** input to neutralID + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloClusterCode, hypo , ClusterCode); + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloClusterFrac, hypo , ClusterFrac,1); + pushData(proto, LHCb::ProtoParticle::additionalInfo::Saturation, hypo, Saturation, 0); + + + + auto dep = (m_estimator->data(hypo, ToSpdM ) > 0) ? -1. : +1.; + dep *= m_estimator->data(hypo, ToPrsE ); + proto -> addInfo ( LHCb::ProtoParticle::additionalInfo::CaloDepositID , dep ) ; // ** input to neutralID toPrsE=|caloDepositID| + + // DLL-based neutralID (to be obsolete) : + pushData(proto, LHCb::ProtoParticle::additionalInfo::PhotonID , hypo, NeutralID , -1. ,true ); // old DLL-based neutral-ID // FORCE + + // isNotX inputs : + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralE49 , hypo, E49 ); + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralE19 , hypo, E19 ); // ** input to neutralID + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloPrsNeutralE49, hypo, PrsE49 ); // ** input to neutralID + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloPrsNeutralE19, hypo, PrsE19 ); // ** input to neutralID + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloPrsNeutralE4max,hypo, PrsE4Max); // ** input to neutralID + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloNeutralPrsM , hypo, HypoPrsM); // ** input to neutralID + // isNotX output : + pushData(proto, LHCb::ProtoParticle::additionalInfo::IsNotH , hypo, isNotH , -1. , true ); // new NN-based neutral-ID (anti-H) // FORCE + pushData(proto, LHCb::ProtoParticle::additionalInfo::IsNotE , hypo, isNotE , -1. , true ); // new NN-based neutral-ID (anti-E) // FORCE + + // isPhoton inputs (photon & mergedPi0 only) + if( hypo -> hypothesis() != LHCb::CaloHypo::Hypothesis::PhotonFromMergedPi0 ) + { + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloShapeFr2r4 ,hypo, isPhotonFr2r4); // -- input to isPhoton + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloShapeAsym ,hypo, isPhotonAsym); // -- input to isPhoton + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloShapeKappa ,hypo, isPhotonKappa); // -- input to isPhoton + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloShapeE1 ,hypo, isPhotonEseed); // -- input to isPhoton + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloShapeE2 ,hypo, isPhotonE2); // -- input to isPhoton + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloPrsShapeE2 ,hypo, isPhotonPrsE2); // -- input to isPhoton + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloPrsShapeEmax ,hypo, isPhotonPrsEmax); // -- input to isPhoton + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloPrsShapeFr2 ,hypo, isPhotonPrsFr2); // -- input to isPhoton + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloPrsShapeAsym ,hypo, isPhotonPrsAsym); // -- input to isPhoton + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloPrsM ,hypo, isPhotonPrsM); // -- input to isPhoton + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloPrsM15 ,hypo, isPhotonPrsM15); // -- input to isPhoton + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloPrsM30 ,hypo, isPhotonPrsM30); // -- input to isPhoton + pushData(proto, LHCb::ProtoParticle::additionalInfo::CaloPrsM45 ,hypo, isPhotonPrsM45); // -- input to isPhoton + // isPhoton output : + pushData(proto, LHCb::ProtoParticle::additionalInfo::IsPhoton , hypo, isPhoton , +1. , true ); // NN-based neutral-ID (anti-pi0) // FORCE to +1 when missing (i.e. PT < 2 GeV) + pushData(proto, LHCb::ProtoParticle::additionalInfo::IsPhotonXGB , hypo, isPhotonXGB , +1. , true ); // XGBoost-based neutral-ID (anti-pi0) // FORCE to +1 when missing (i.e. PT < 2 GeV) + + } + }// lightmode + } // loop over CaloHypos + if ( counterStat->isQuiet() ) counter( loc + "=>" + m_protoLocation) += count; + } // loop over HyposLocations + + + if ( msgLevel(MSG::DEBUG) )debug() << "# Future Neutral ProtoParticles created : " << protos -> size() << endmsg; + if(counterStat->isQuiet())counter ("#protos in " + m_protoLocation) += protos->size() ; + return StatusCode::SUCCESS; +} +// ============================================================================ +// Finalize +// ============================================================================ + +StatusCode FutureNeutralProtoPAlg::finalize(){ + // + if ( lightMode() ) + { info() << "Future Neutral protoparticles have been created in 'Light' Mode" << endmsg ; } + + return GaudiAlgorithm::finalize(); // must be called after all other actions +} diff --git a/Rec/GlobalReco/src/FutureNeutralProtoPAlg.h b/Rec/GlobalReco/src/FutureNeutralProtoPAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..99675b2a154a95c93ebe754aaa212f8631a34dcc --- /dev/null +++ b/Rec/GlobalReco/src/FutureNeutralProtoPAlg.h @@ -0,0 +1,106 @@ +// ============================================================================ +#ifndef GLOBALRECO_FUTURENEUTRALPROTOPALG_H +#define GLOBALRECO_FUTURENEUTRALPROTOPALG_H 1 +// ============================================================================ +// Include files +// ============================================================================ +// Event +#include "Event/CaloHypo.h" +#include "Event/ProtoParticle.h" +// Calo +#include "CaloFutureUtils/CaloFutureAlgUtils.h" +#include "CaloFutureInterfaces/ICaloFutureHypoEstimator.h" +#include "CaloFutureInterfaces/IFutureCounterLevel.h" +// from Gaudi +#include "GaudiAlg/GaudiAlgorithm.h" +/** @class FutureNeutralProtoPAlg FutureNeutralProtoPAlg.h + * + * Creator of the neutral ProtoParticles from CaloHypos + * + * The current version fills the following estimators for ProtoParticle + * + * <ul> + * <li> <i>CaloTrMatch</i> as <b>minimal</b> of this estimator for all + * linked <i>CaloHypo</i> objects. The value is extracted from + * the relation table/associator as a relation weigth between + * <i>CaloCluster</i> and <i>TrStoredTrack</i> objects </li> + * <li> <i>CaloDepositID</i> as <b>maximal</b> of this estimator for all + * linked <i>CaloHypo</i> objects using Spd/Prs estimator tool + * written by Frederic Machefert </li> + * <li> <i>CaloShowerShape</i> as <b>maximal</b> of the estimator for + * all linked <i>CaloHypo</i> objects. Estimator is equal to the + * sum of diagonal elements of cluster spread matrix (2nd order + * moments of the cluster) </li> + * <li> <i>ClusterMass</i> as <b>maximal</b> of the estimator of + * cluster mass using smart algorithm by Olivier Deschamp </li> + * <li> <i>PhotonID</i> as the estimator of PhotonID + * using nice identifiaction tool + * CaloPhotonEstimatorTool by Frederic Machefert * + * </ul> + * + * + * @author Olivier Deschamps + * @date 2006-06-09 + * Adapted from NeutralPPsFromCPsAlg class (Vanya Belyaev Ivan.Belyaev@itep.ru) + */ +class FutureNeutralProtoPAlg final : public GaudiAlgorithm +{ + // ========================================================================== + public: + // ========================================================================== + /// Standard constructor + FutureNeutralProtoPAlg ( const std::string& name, ISvcLocator* pSvcLocator ); + + StatusCode initialize() override; ///< Algorithm initialization + StatusCode execute() override; ///< Algorithm execution + StatusCode finalize() override; ///< Algorithm finalization + + private: + + /// use"light" mode? ( suitable fo recalibration purposes) + inline bool lightMode() const noexcept { return m_light_mode ; } + + void pushData( LHCb::ProtoParticle*, + LHCb::ProtoParticle::additionalInfo, + const LHCb::CaloHypo*, + const CaloFutureDataType::DataType, + const double def=CaloFutureDataType::Default, + const bool force=false) const; + + double getMass( const int cellCode ) const; + +private:// data + + IFutureCounterLevel* counterStat = nullptr; + + std::string m_protoLocation ; + std::vector<std::string> m_hyposLocations ; + /// flag to indicate "light/calibration" mode + bool m_light_mode{false} ; + ICaloFutureHypoEstimator * m_estimator = nullptr; + mutable std::map<const int,double> m_mass = {{}}; + mutable bool m_setMass{false}; + +}; + +inline void FutureNeutralProtoPAlg::pushData(LHCb::ProtoParticle* proto , + LHCb::ProtoParticle::additionalInfo pflag , + const LHCb::CaloHypo* hypo, + const CaloFutureDataType::DataType hflag, + const double def, + const bool force ) const +{ + const auto data = m_estimator->data(hypo, hflag , def ); + if ( data != def || force ) + { + proto->addInfo( pflag,data ); // only store when different from default + std::ostringstream mess; + mess << pflag << " for " << hypo->hypothesis(); + counter( mess.str() ) += data; + } +} + + + + +#endif // GLOBALRECO_FUTURENEUTRALPROTOPALG_H diff --git a/Rec/GlobalReco/src/FutureNeutralProtoParticleAddNeutralID.cpp b/Rec/GlobalReco/src/FutureNeutralProtoParticleAddNeutralID.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e7af779dc195af065d886d0b765201f5a5a028a1 --- /dev/null +++ b/Rec/GlobalReco/src/FutureNeutralProtoParticleAddNeutralID.cpp @@ -0,0 +1,131 @@ +// Include files + +// local +#include "FutureNeutralProtoParticleAddNeutralID.h" +#include "CaloFutureUtils/CaloMomentum.h" + +//----------------------------------------------------------------------------- +// Implementation file for class : FutureNeutralProtoParticleAddNeutralID +// +// 2014-05-27 : Olivier Deschamps +//----------------------------------------------------------------------------- + +namespace { + +enum class func_type { none, abs, area }; + +bool addInput( double& data, + const LHCb::ProtoParticle* proto, + const LHCb::ProtoParticle::additionalInfo flag, + const func_type func = func_type::none ) +{ + auto v = proto->info( flag,-1e+06 ); + if ( func == func_type::abs ) { v = fabs(v); } + else if ( func == func_type::area ) { v = double( (int( v ) >> 12) & 0x3 ); } + data = v; + return proto->hasInfo( flag ); +} +} + +//============================================================================= +// Main execution +//============================================================================= +StatusCode FutureNeutralProtoParticleAddNeutralID::execute() +{ + // locate input data + for ( auto * proto : * get<LHCb::ProtoParticles>(evtSvc(),m_input) ) + { + + const auto & hypos = proto->calo() ; + if ( hypos.empty() ) { continue ; } + + const auto hypo = hypos.front(); + const auto pt = LHCb::CaloMomentum(hypo).pt(); + + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "---------- " << hypo->hypothesis() << " ---------- " <<endmsg; + + //======== re-build neutralID + if ( m_isNotE.value() || m_isNotH.value()) + { + double nV[10] = {}; + bool nOk = true; + nOk &= addInput(nV[0],proto,LHCb::ProtoParticle::additionalInfo::CaloTrMatch); + nOk &= addInput(nV[1],proto,LHCb::ProtoParticle::additionalInfo::CaloDepositID,func_type::abs); + nOk &= addInput(nV[2],proto,LHCb::ProtoParticle::additionalInfo::CaloNeutralE19); + nOk &= addInput(nV[3],proto,LHCb::ProtoParticle::additionalInfo::CaloNeutralHcal2Ecal); + nOk &= addInput(nV[4],proto,LHCb::ProtoParticle::additionalInfo::CaloPrsNeutralE19); + nOk &= addInput(nV[5],proto,LHCb::ProtoParticle::additionalInfo::CaloPrsNeutralE49); + nOk &= addInput(nV[6],proto,LHCb::ProtoParticle::additionalInfo::ShowerShape); + nOk &= addInput(nV[7],proto,LHCb::ProtoParticle::additionalInfo::CaloPrsNeutralE4max); + nOk &= addInput(nV[8],proto,LHCb::ProtoParticle::additionalInfo::CaloNeutralPrsM); + nOk &= addInput(nV[9],proto,LHCb::ProtoParticle::additionalInfo::CaloNeutralSpd); + const double* nnV = nV; + if ( m_isNotE.value() && nOk ) + { + const auto temp = proto->info(LHCb::ProtoParticle::additionalInfo::IsNotE,-1.); + proto->eraseInfo(LHCb::ProtoParticle::additionalInfo::IsNotE); + const auto val = ( pt > m_isNotE_Pt.value() ) ? m_neutralID->isNotE(nnV) : -1. ; + proto->addInfo(LHCb::ProtoParticle::additionalInfo::IsNotE,val ); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "UPDATING IsNotE : " + << temp << " ---> " << proto->info(LHCb::ProtoParticle::additionalInfo::IsNotE,-1.) + << " (" << proto->hasInfo(LHCb::ProtoParticle::additionalInfo::IsNotE ) << ")" << endmsg; + } + if ( m_isNotH.value() && nOk ) + { + const auto temp = proto->info(LHCb::ProtoParticle::additionalInfo::IsNotH,-1.); + proto->eraseInfo(LHCb::ProtoParticle::additionalInfo::IsNotH); + const auto val = ( pt > m_isNotH_Pt) ? m_neutralID->isNotH(nnV) : -1.; + proto->addInfo(LHCb::ProtoParticle::additionalInfo::IsNotH, val ); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "UPDATING IsNotH : " + << temp << " ---> " << proto->info(LHCb::ProtoParticle::additionalInfo::IsNotH,-1.) + << " (" << proto->hasInfo(LHCb::ProtoParticle::additionalInfo::IsNotH ) << ")" << endmsg; + } + } + + // re-build gamma/pi0 separation + if ( m_isPhoton.value() && hypo -> hypothesis() != LHCb::CaloHypo::Hypothesis::PhotonFromMergedPi0 ) + { + double pV[15] = {}; + bool pOk = true; + pOk &= addInput(pV[0],proto,LHCb::ProtoParticle::additionalInfo::CaloNeutralID,func_type::area); + pOk &= addInput(pV[1],proto,LHCb::ProtoParticle::additionalInfo::ShowerShape); + pOk &= addInput(pV[2],proto,LHCb::ProtoParticle::additionalInfo::CaloShapeFr2r4); + pOk &= addInput(pV[3],proto,LHCb::ProtoParticle::additionalInfo::CaloShapeAsym); + pOk &= addInput(pV[4],proto,LHCb::ProtoParticle::additionalInfo::CaloShapeKappa); + pOk &= addInput(pV[5],proto,LHCb::ProtoParticle::additionalInfo::CaloShapeE1); + pOk &= addInput(pV[6],proto,LHCb::ProtoParticle::additionalInfo::CaloShapeE2); + pOk &= addInput(pV[7],proto,LHCb::ProtoParticle::additionalInfo::CaloPrsShapeFr2); + pOk &= addInput(pV[8],proto,LHCb::ProtoParticle::additionalInfo::CaloPrsShapeAsym); + pOk &= addInput(pV[9],proto,LHCb::ProtoParticle::additionalInfo::CaloPrsShapeEmax); + pOk &= addInput(pV[10],proto,LHCb::ProtoParticle::additionalInfo::CaloPrsShapeE2); + pOk &= addInput(pV[11],proto,LHCb::ProtoParticle::additionalInfo::CaloPrsM); + pOk &= addInput(pV[12],proto,LHCb::ProtoParticle::additionalInfo::CaloPrsM15); + pOk &= addInput(pV[13],proto,LHCb::ProtoParticle::additionalInfo::CaloPrsM30); + pOk &= addInput(pV[14],proto,LHCb::ProtoParticle::additionalInfo::CaloPrsM45); + const double* ppV = pV; + + if ( m_isPhoton.value() && pOk ) + { + const auto temp=proto->info(LHCb::ProtoParticle::additionalInfo::IsPhoton,-1.); + proto->eraseInfo(LHCb::ProtoParticle::additionalInfo::IsPhoton); + const auto val = ( pt > m_isPhoton_Pt.value() ) ? m_gammaPi0->isPhoton(ppV) : -1.; + proto->addInfo( LHCb::ProtoParticle::additionalInfo::IsPhoton, val ); + if( UNLIKELY( msgLevel(MSG::DEBUG) ) ) + debug() << "UPDATING IsPhoton : " + << temp << " ---> " << proto->info(LHCb::ProtoParticle::additionalInfo::IsPhoton,-1.) + << " (" << proto->hasInfo(LHCb::ProtoParticle::additionalInfo::IsPhoton ) << ")" << endmsg; + } + } + } + return StatusCode::SUCCESS; +} + +//============================================================================= + +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( FutureNeutralProtoParticleAddNeutralID ) + +//============================================================================= diff --git a/Rec/GlobalReco/src/FutureNeutralProtoParticleAddNeutralID.h b/Rec/GlobalReco/src/FutureNeutralProtoParticleAddNeutralID.h new file mode 100644 index 0000000000000000000000000000000000000000..25f8ff023da3b36433347d68d480a269d162b9f5 --- /dev/null +++ b/Rec/GlobalReco/src/FutureNeutralProtoParticleAddNeutralID.h @@ -0,0 +1,42 @@ +#ifndef FUTURENEUTRALPROTOPARTICLEADDNEUTRALID_H +#define FUTURENEUTRALPROTOPARTICLEADDNEUTRALID_H 1 + +// Include files +// from Gaudi +#include "GaudiAlg/GaudiAlgorithm.h" +#include "CaloFutureInterfaces/IFutureGammaPi0SeparationTool.h" +#include "CaloFutureInterfaces/IFutureNeutralIDTool.h" +#include "Event/ProtoParticle.h" + +/** @class FutureNeutralProtoParticleAddNeutralID FutureNeutralProtoParticleAddNeutralID.h + * + * + * @author Olivier Deschamps + * @date 2014-05-27 + */ + +class FutureNeutralProtoParticleAddNeutralID final : public GaudiAlgorithm +{ + + public: + + using GaudiAlgorithm::GaudiAlgorithm; + + StatusCode execute() override; ///< Algorithm execution + + private: + + Gaudi::Property<std::string> m_input { this, "Input" , LHCb::ProtoParticleLocation::Neutrals }; + Gaudi::Property<bool> m_isNotE { this, "UpdateIsNotE" , true }; + Gaudi::Property<bool> m_isNotH { this, "UpdateIsNotH" , true }; + Gaudi::Property<bool> m_isPhoton { this, "UpdateIsPhoton" , true }; + Gaudi::Property<double> m_isNotE_Pt { this, "MinPtIsNotE" , 75.0 }; + Gaudi::Property<double> m_isNotH_Pt { this, "MinPtIsNotH" , 75.0 }; + Gaudi::Property<double> m_isPhoton_Pt { this, "MinPtIsPhoton" , 2000.0 }; + ToolHandle<IFutureGammaPi0SeparationTool> m_gammaPi0 { this, "FutureGammaPi0SeparationTool" , "FutureGammaPi0SeparationTool" }; + ToolHandle<IFutureNeutralIDTool> m_neutralID { this, "FutureNeutralIDTool" , "FutureNeutralIDTool" }; + +}; + + +#endif // FUTURENEUTRALPROTOPARTICLEADDNEUTRALID_H diff --git a/Rec/RecConf/python/RecConf/Configuration.py b/Rec/RecConf/python/RecConf/Configuration.py index 2343743677cff49d3f35d976669ef3d621d79167..200a650aeb1d81e7e6a07ab410ef40f6b8e397cb 100755 --- a/Rec/RecConf/python/RecConf/Configuration.py +++ b/Rec/RecConf/python/RecConf/Configuration.py @@ -9,9 +9,9 @@ __author__ = "Rob Lambert" from LHCbKernel.Configuration import * from TrackSys.Configuration import * from GlobalReco.Configuration import * -from Configurables import CaloProcessor +from Configurables import CaloProcessor, CaloFutureProcessor -from Configurables import ( ProcessPhase, CaloMoniDstConf, +from Configurables import ( ProcessPhase, CaloMoniDstConf, CaloFutureMoniDstConf, VeloRecMonitors, GlobalRecoChecks, MuonTrackMonitorConf, MuonIDAlg ) @@ -24,7 +24,8 @@ class RecSysConf(LHCbConfigurableUser): ## Possible used Configurables __used_configurables__ = [ GlobalRecoConf , TrackSys , - CaloProcessor ] + CaloProcessor , + CaloFutureProcessor] ## Default tracking Sub-detector processing sequence (Run I ) DefaultTrackingSubdets = ["VELO","TT","IT","OT","Tr","Vertex"] @@ -37,7 +38,7 @@ class RecSysConf(LHCbConfigurableUser): ## Default reconstruction sequence for field-on data (Run II) DefaultSubDetsFieldOnRun2 = ["Decoding"] + DefaultTrackingSubdetsRun2 + ["RICH","CALO","MUON","PROTO","SUMMARY"] ## Default reconstruction sequence for field-on data (Upgrade) - DefaultSubDetsFieldOnUpgrade = ["Decoding"] + DefaultTrackingSubdetsUpgrade + ["RICH","CALO","MUON","PROTO","SUMMARY"] + DefaultSubDetsFieldOnUpgrade = ["Decoding"] + DefaultTrackingSubdetsUpgrade + ["RICH","CALOFUTURE","MUON","PROTO","SUMMARY"] ## List of known special data processing options KnownSpecialData = [ "cosmics", "veloOpen", "fieldOff", "beamGas", "microBiasTrigger", "pA", "pGun"] ## List of DataTypes (years) for Run 2 @@ -83,11 +84,11 @@ class RecSysConf(LHCbConfigurableUser): trackConf = TrackSys() trSeq = trackConf.getProp("TrackingSequence") if trSeq != []: - DefaultSubDetsFieldOnUpgrade = ["Decoding"] + trSeq + ["RICH","CALO", + DefaultSubDetsFieldOnUpgrade = ["Decoding"] + trSeq + ["RICH","CALOFUTURE", "MUON","PROTO","SUMMARY"] else: DefaultSubDetsFieldOnUpgrade = ["Decoding","TrFast","TrBest","RICH", - "CALO","MUON","PROTO","SUMMARY"] + "CALOFUTURE","MUON","PROTO","SUMMARY"] self.setProp("RecoSequence",DefaultSubDetsFieldOnUpgrade) recoSeq = self.getProp("RecoSequence") @@ -255,6 +256,20 @@ class RecSysConf(LHCbConfigurableUser): seq.Members = [caloConf.caloSequence()] GaudiKernel.ProcessJobOptions.PrintOff() + if "CALOFUTURE" in recoSeq: + import GaudiKernel.ProcessJobOptions + seq = GaudiSequencer ( 'RecoCALOFUTURESeq' ) + caloConf=CaloFutureProcessor( + Context = self.getProp('Context') , + OutputLevel = self.getProp('OutputLevel') , + UseTracks = True , + EnableOnDemand = False , + DataType = self.getProp ('DataType') + ) + GaudiKernel.ProcessJobOptions.PrintOn(force=True) + seq.Members = [caloConf.caloFutureSequence()] + GaudiKernel.ProcessJobOptions.PrintOff() + # MUON if "MUON" in recoSeq: from MuonID import ConfiguredMuonIDs @@ -297,6 +312,7 @@ class RecMoniConf(LHCbConfigurableUser): ## Possible used Configurables __used_configurables__ = [ CaloMoniDstConf, + CaloFutureMoniDstConf, VeloRecMonitors, MuonTrackMonitorConf, GlobalRecoChecks ] @@ -331,7 +347,8 @@ class RecMoniConf(LHCbConfigurableUser): } ## Known monitoring sequences, all run by default - KnownMoniSubdets = ["CALO","RICH","MUON","VELO","OT","ST"] + + KnownMoniSubdets = ["CALO","RICH","MUON","VELO","OT","ST"] KnownMoniGeneral = ["GENERAL","Tr","PROTO","Hlt"] KnownMoniSubdets = KnownMoniSubdets + KnownMoniGeneral KnownExpertMoniSubdets = KnownMoniSubdets+["TT","IT"] @@ -353,7 +370,10 @@ class RecMoniConf(LHCbConfigurableUser): if [det for det in ['IT', 'TT'] if det in dets]: dets.append("ST") if [det for det in ['SPD', 'PRS', 'ECAL', 'HCAL'] if det in dets]: - dets.append("CALO") + if self.getProp("DataType") == "Upgrade": + dets.append("CALOFUTURE") + else: + dets.append("CALO") if [det for det in ['RICH1','RICH2','RICH1PMT','RICH2PMT'] if det in dets]: dets.append("RICH") @@ -391,6 +411,7 @@ class RecMoniConf(LHCbConfigurableUser): from Configurables import ProcessPhase ProcessPhase("Moni").DetectorList += moniSeq + # Histograms filled both in real and simulated data cases if "GENERAL" in moniSeq : @@ -430,9 +451,14 @@ class RecMoniConf(LHCbConfigurableUser): seq.Members += [richTime] # CALO - caloTime = RecProcessingTimeMoni("CaloEventProcTime") - caloTime.Algorithms = ["RecoCALOSeq"] - seq.Members += [caloTime] + if self.getProp("DataType") == "Upgrade": + caloTime = RecProcessingTimeMoni("CaloFutureEventProcTime") + caloTime.Algorithms = ["RecoCALOFUTURESeq"] + seq.Members += [caloTime] + else: + caloTime = RecProcessingTimeMoni("CaloEventProcTime") + caloTime.Algorithms = ["RecoCALOSeq"] + seq.Members += [caloTime] # MUON muonTime = RecProcessingTimeMoni("MuonEventProcTime") @@ -464,6 +490,22 @@ class RecMoniConf(LHCbConfigurableUser): self.setOtherProps(caloMoni,["Histograms"]) GaudiKernel.ProcessJobOptions.PrintOff() + if "CALOFUTURE" in moniSeq : + import GaudiKernel.ProcessJobOptions + GaudiKernel.ProcessJobOptions.PrintOn(force=True) + from Configurables import GaudiSequencer + seq = GaudiSequencer( "MoniCALOFUTURESeq") + noSPDPRS = True + if [det for det in ['SPD','PRS'] if det in dets]: + noSPDPRS = False + caloMoni = CaloFutureMoniDstConf( MonitorSequence = seq, + OutputLevel = self.getProp('OutputLevel'), + Context = 'Offline', + NoSpdPrs = noSPDPRS) + caloMoni.printConf() + self.setOtherProps(caloMoni,["Histograms"]) + GaudiKernel.ProcessJobOptions.PrintOff() + if "VELO" in moniSeq : from Configurables import GaudiSequencer self.setOtherProps(VeloRecMonitors(),["Histograms","OutputLevel"])