2   Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
 
    7 // $Id: RingerDiscriminatorWrapper.icc 791627 2017-01-10 04:45:53Z wsfreund $
 
    8 #ifndef RINGERSELECTORTOOLS_PROCEDURES_RINGERDISCRIMINATIONWRAPPER_ICC
 
    9 #define RINGERSELECTORTOOLS_PROCEDURES_RINGERDISCRIMINATIONWRAPPER_ICC
 
   11 #include "RingerDiscriminatorWrapper.h"
 
   12 #include "RingerProcedureWrapper.icc"
 
   14 #include "RingerSelectorTools/procedures/Normalizations.h"
 
   15 #include "RingerSelectorTools/procedures/NeuralNetwork.h"
 
   17 #include <type_traits>
 
   21 namespace WrapperHelperFcns {
 
   24  * Return the discriminator on dirObj of ppType
 
   27 Discrimination::IDiscriminatorVarDep* getDiscr(discrEnum_t discrType,
 
   30   using namespace Discrimination;
 
   31   // For the interface case, we will have to create each pre-processing
 
   32   // depending on the information written on ppType:
 
   35     case discrEnum_t::NNFeedForward:
 
   37       return NNFeedForwardVarDep::read( dirObj );
 
   42       throw std::runtime_error( std::string("Cannot read discriminator of ") +
 
   43           "type: " + toStr(discrType) );
 
   49 void addExtraDescription( std::vector<float> &input
 
   50                         , const DepVarStruct& depVar
 
   51                         , const Ringer::PreProcessing::Norm::ExtraPatternsNorm* extraPatNorm
 
   52                         , const Ringer::ExtraDescriptionPatterns& extraDescr )
 
   54   if ( extraPatNorm == nullptr ) {
 
   55     throw std::runtime_error( std::string("Attempted to add description with empty norm") );
 
   57   if( extraDescr.feedEta() ){
 
   58     input.push_back( extraPatNorm->normEta( depVar.eta ) );
 
   60   if( extraDescr.feedEt() ){
 
   61     input.push_back( extraPatNorm->normEt( depVar.et ) );
 
   63   if( extraDescr.feedPileupEstimation() ){
 
   64     input.push_back( extraPatNorm->normPileupEstimation( depVar.pileupEstimation ) );
 
   67 } // WrapperHelperFcns
 
   69 // Import Wrapper Helper functions
 
   70 using namespace WrapperHelperFcns;
 
   72 // =============================================================================
 
   73 //            -----------------------------------------
 
   74 //            RingerProcedureWrapper for Discriminators
 
   75 //            -----------------------------------------
 
   76 // =============================================================================
 
   78 // =============================================================================
 
   81   /*EtaDependency*/int etaDependency,
 
   82   /*EtDependency*/int etDependency,
 
   83   /*SegmentationType*/int segType
 
   85 void RingerProcedureWrapper<
 
   90   false,     // isPreProcessor
 
   91   true,      // isDiscriminator
 
   95   for ( size_t ppColIdx = 0; ppColIdx < m_ppWrapperCol.size(); ++ppColIdx){
 
   96     if (m_ppWrapperCol[ppColIdx]){
 
   97       m_ppWrapperCol[ppColIdx]->releaseMemory();
 
  100   for ( size_t segIdx = 0; segIdx < m_discrCol.size() ; ++segIdx){
 
  101     for ( size_t etIdx = 0; etIdx < m_discrCol[segIdx].size() ; ++etIdx){
 
  102       for ( size_t etaIdx = 0; etaIdx < m_discrCol[segIdx][etIdx].size();
 
  105         delete m_discrCol[segIdx][etIdx][etaIdx];
 
  113 // =============================================================================
 
  116   /*EtaDependency*/int etaDependency,
 
  117   /*EtDependency*/int etDependency,
 
  118   /*SegmentationType*/int segType
 
  120 void RingerProcedureWrapper<
 
  125   false,     // isPreProcessor
 
  126   true,      // isDiscriminator
 
  127   false>     // isThreshold
 
  129     const DepVarStruct &depVar,
 
  130     const xAOD::CaloRings *clrings,
 
  131     const TrackPatternsHolder *trackPat,
 
  132     std::vector<float> &output) const
 
  135   ATH_MSG_DEBUG("Applying first discrimination layer discriminators.");
 
  138   // Clear any previous output:
 
  141   // We will put pre-processing results into this vector:
 
  142   std::vector<float> transformVec;
 
  145     ATH_MSG_DEBUG( "Allocating space on transformVec of size " <<
 
  146       (((clrings)?(m_nRings):0) +
 
  147       ((trackPat)?TrackPatternsHolder::numberOfPatterns():0)));
 
  150   // We grant it enougth space to handle worst case:
 
  151   transformVec.reserve(
 
  152       (clrings)?(m_nRings):(0 +
 
  153       ((trackPat)?TrackPatternsHolder::numberOfPatterns():0))
 
  156   std::vector<float> input = transformVec;
 
  158   if ( m_ppWrapperCol.empty() ) {
 
  159     // Otherwise simply push-back information:
 
  161       clrings->exportRingsTo(transformVec);
 
  164       trackPat->exportPatternsTo(transformVec);
 
  167     // FIXME: This does not work with multiple normalizations, we need to
 
  168     // change this to something where the pre-processor will keep the
 
  169     // segmentation information that it will receive and where should it divide
 
  172     // If pre-processing available execute it:
 
  173     for ( size_t ppIdx = 0; ppIdx < m_ppWrapperCol.size(); ++ppIdx ){
 
  174       m_ppWrapperCol[ppIdx]->applyPreProcessing(
 
  182   // Initialize eta and et indexes:
 
  183   size_t etaIdx(0), etIdx(0);
 
  184   // Get the correct idx to be applied:
 
  186     etaIdx = findEtaBin(depVar.eta, m_discrCol[0]);
 
  189     etIdx = findEtBin(depVar.et, m_discrCol[0]);
 
  195     case SegmentationType::NoSegmentation:
 
  199       ATH_MSG_VERBOSE("Applying NonSegmented"
 
  200           " discriminator at etaIdx (" << etaIdx << ") and etIdx ("
 
  203       input = transformVec;
 
  204       if ( static_cast<bool>(m_extraDescriptionPatterns) ) {
 
  205         // Add demanded extra description
 
  206         addExtraDescription( input, depVar, m_extraDescriptionNorms.at(etIdx).at(etaIdx), m_extraDescriptionPatterns );
 
  208       // Apply discrimination to all transformed space:
 
  209       m_discrCol[cDiscr++][etIdx][etaIdx]->execute(input,output);
 
  212     case SegmentationType::TrackCalSegmentation:
 
  215       ATH_MSG_VERBOSE("Applying Track/Cal segmented"
 
  216           " discriminators at etaIdx (" << etaIdx << ") and etIdx ("
 
  220         // Apply discrimination to CaloRings as one:
 
  221         getCaloSegmentFromTransformVec( m_nRings,
 
  225         if ( static_cast<bool>(m_extraDescriptionPatterns) ) {
 
  226           // Add demanded extra description
 
  227           addExtraDescription( input, depVar, m_extraDescriptionNorms.at(etIdx).at(etaIdx), m_extraDescriptionPatterns );
 
  230         executeSegmentedDiscr(
 
  232             m_discrCol[cDiscr++][etIdx][etaIdx],
 
  238         // Apply discrimination to Track separated:
 
  239         getTrackSegmentFromTransformVec(
 
  240             // If the CaloRings is available, then we have to increase the
 
  241             // start index to jump all Calorimeter representations:
 
  242             (clrings)?(m_nRings):0,
 
  246         if ( static_cast<bool>(m_extraDescriptionPatterns) ) {
 
  247           // Add demanded extra description
 
  248           addExtraDescription( input, depVar, m_extraDescriptionNorms.at(etIdx).at(etaIdx), m_extraDescriptionPatterns );
 
  251         executeSegmentedDiscr(
 
  253             m_discrCol[cDiscr++][etIdx][etaIdx],
 
  260     case SegmentationType::TrackCalPatTypeSegmentation:
 
  262       // TODO Implement this if it is going to be used:
 
  263       throw std::runtime_error(std::string("There is no implementation method "
 
  264             "for ") + toStr(static_cast<SegmentationType>(segType)) );
 
  266     case SegmentationType::TrackCalJointSections:
 
  269       ATH_MSG_VERBOSE("Applying Track/Cal-JointSections segmented"
 
  270           " discriminators at etaIdx (" << etaIdx << ") and etIdx ("
 
  274         // Apply discrimination to each CalJointSection:
 
  275         while ( cDiscr < static_cast<size_t>(
 
  276               CalJointSection::NJointSections) )
 
  278           getCaloSegmentFromTransformVec(
 
  280               static_cast<CalJointSection>(cDiscr),
 
  284           if ( static_cast<bool>(m_extraDescriptionPatterns) ) {
 
  285             // Add demanded extra description
 
  286             addExtraDescription( input, depVar, m_extraDescriptionNorms.at(etIdx).at(etaIdx), m_extraDescriptionPatterns );
 
  289           executeSegmentedDiscr(
 
  291               m_discrCol[cDiscr++][etIdx][etaIdx],
 
  295         cDiscr += static_cast<size_t>(CalJointSection::NJointSections);
 
  298         // Apply discrimination to Track separated:
 
  299         getTrackSegmentFromTransformVec(
 
  300             (clrings)?(m_nRings):0,
 
  304         if ( static_cast<bool>(m_extraDescriptionPatterns) ) {
 
  305           // Add demanded extra description
 
  306           addExtraDescription( input, depVar, m_extraDescriptionNorms.at(etIdx).at(etaIdx), m_extraDescriptionPatterns );
 
  309         executeSegmentedDiscr(
 
  311             m_discrCol[cDiscr++][etIdx][etaIdx],
 
  318     case SegmentationType::TrackCalJointLayers:
 
  321       ATH_MSG_VERBOSE("Applying Track/Cal-JointLayers segmented"
 
  322           " discriminators at etaIdx (" << etaIdx << ") and etIdx ("
 
  326         // Apply discrimination to each CalJointLayer:
 
  327         while ( cDiscr < static_cast<size_t>(
 
  328               CalJointLayer::NJointLayers) )
 
  330           getCaloSegmentFromTransformVec(
 
  332               static_cast<CalJointLayer>(cDiscr),
 
  336           if ( static_cast<bool>(m_extraDescriptionPatterns) ) {
 
  337             // Add demanded extra description
 
  338             addExtraDescription( input, depVar, m_extraDescriptionNorms.at(etIdx).at(etaIdx), m_extraDescriptionPatterns );
 
  341           executeSegmentedDiscr(
 
  343               m_discrCol[cDiscr++][etIdx][etaIdx],
 
  347         cDiscr += static_cast<size_t>(CalJointLayer::NJointLayers);
 
  350         // Apply discrimination to Track separated:
 
  351         getTrackSegmentFromTransformVec(
 
  352             (clrings)?(m_nRings):0,
 
  356         if ( static_cast<bool>(m_extraDescriptionPatterns) ) {
 
  357           // Add demanded extra description
 
  358           addExtraDescription( input, depVar, m_extraDescriptionNorms.at(etIdx).at(etaIdx), m_extraDescriptionPatterns );
 
  361         executeSegmentedDiscr(
 
  363             m_discrCol[cDiscr++][etIdx][etaIdx],
 
  374 // =============================================================================
 
  377   /*EtaDependency*/int etaDependency,
 
  378   /*EtDependency*/int etDependency,
 
  379   /*SegmentationType*/int segType
 
  381 void RingerProcedureWrapper<
 
  386   false,     // isPreProcessor
 
  387   true,      // isDiscriminator
 
  388   false>     // isThreshold
 
  390     const DepVarStruct &depVar,
 
  391     const std::vector<float> &input,
 
  392     std::vector<float> &output) const
 
  395   ATH_MSG_DEBUG("Applying internal discrimination layer discriminators.");
 
  398   // This method only applies for segType NoSegmentation.
 
  399   ensureNoSegmentationOnlyFcn(static_cast<SegmentationType>(segType));
 
  402   std::vector<float> inputCopy = input;
 
  403   // First, execute pp wrapper collection:
 
  404   for ( size_t ppIdx = 0; ppIdx < m_ppWrapperCol.size(); ++ppIdx ){
 
  405     m_ppWrapperCol[ppIdx]->applyPreProcessing(depVar,inputCopy);
 
  408   if (!etaDependency && !etDependency){
 
  409     m_discr->execute(inputCopy,output);
 
  413   // Initialize eta and et indexes:
 
  414   size_t etaIdx(0), etIdx(0);
 
  416   // Get the correct idx to be applied:
 
  418     etaIdx = findEtaBin(depVar.eta, m_discrCol[0]);
 
  421     etIdx = findEtBin(depVar.et, m_discrCol[0]);
 
  424   if ( static_cast<bool>(m_extraDescriptionPatterns) ) {
 
  425     // Add demanded extra description
 
  426     addExtraDescription( inputCopy, depVar, m_extraDescriptionNorms.at(etIdx).at(etaIdx), m_extraDescriptionPatterns );
 
  430   m_discrCol[0][etIdx][etaIdx]->execute(inputCopy,output);
 
  433 // =============================================================================
 
  436   /*EtaDependency*/int etaDependency,
 
  437   /*EtDependency*/int etDependency,
 
  438   /*SegmentationType*/int segType
 
  440 void RingerProcedureWrapper<
 
  445   false,     // isPreProcessor
 
  446   true,      // isDiscriminator
 
  447   false>     // isThreshold
 
  448 ::checkPPWrapperCol() const {
 
  449   if (m_ppWrapperCol.empty()){
 
  450     throw std::runtime_error(std::string(
 
  451           "Attempted to start Discriminator Wrapper with"
 
  452            " PreProcessing Wrapper collection that is empty.\n"
 
  453            "In this case, do not input PreProcessing"
 
  454            " Wrapper collection in Discriminator"
 
  455            " Wrapper construction."));
 
  458   for ( size_t ppWrapperIdx = 0; ppWrapperIdx < m_ppWrapperCol.size();
 
  460     if( !m_ppWrapperCol[ppWrapperIdx] ||
 
  461         m_ppWrapperCol[ppWrapperIdx]->empty() ){
 
  462       throw std::runtime_error(std::string(
 
  463             "Attempted to start Discriminator Wrapper with"
 
  464             " PreProcessing Wrapper collection with"
 
  465             " empty PreProcessing Wrapper."));
 
  470 // =============================================================================
 
  473   /*EtaDependency*/int etaDependency,
 
  474   /*EtDependency*/int etDependency,
 
  475   /*SegmentationType*/int segType
 
  477 void RingerProcedureWrapper<
 
  482   false,     // isPreProcessor
 
  483   true,      // isDiscriminator
 
  484   false>     // isThreshold
 
  485 ::checkExtraPatNorm() const {
 
  486   if ( m_extraDescriptionNorms.size() != m_discrCol[0].size() ){
 
  487     throw std::runtime_error( std::string("Extra normalization and discriminator et size do not match") );
 
  489   if ( m_extraDescriptionNorms[0].size() != m_discrCol[0][0].size() ) {
 
  490     throw std::runtime_error( std::string("Extra normalization and discriminator eta size do not match") );
 
  494 // =============================================================================
 
  497   /*EtaDependency*/int etaDependency,
 
  498   /*EtDependency*/int etDependency,
 
  499   /*SegmentationType*/int segType
 
  501 void RingerProcedureWrapper<
 
  506   false,     // isPreProcessor
 
  507   true,      // isDiscriminator
 
  508   false>     // isThreshold
 
  509 ::checkDiscrCol() const {
 
  511     checkCollection(m_discrCol,
 
  512         static_cast<EtaDependency>(etaDependency),
 
  513         static_cast<EtDependency>(etDependency));
 
  514     if (segType && m_discrCol.size() < 2 ){
 
  515       throw std::runtime_error(std::string("Cannot allocate dependency vector "
 
  516             "with size lesser than one when using segmentation dependency."));
 
  518   } catch ( const std::runtime_error &e ) {
 
  519     throw std::runtime_error(std::string("Couldn't initialize RingerDiscriminationWrapper collection due to: ")
 
  524 // =============================================================================
 
  527   /*EtaDependency*/int etaDependency,
 
  528   /*EtDependency*/int etDependency,
 
  529   /*SegmentationType*/int segType
 
  531 void RingerProcedureWrapper<
 
  536   false,     // isPreProcessor
 
  537   true,      // isDiscriminator
 
  538   false>     // isThreshold
 
  539 ::setMsgStream(MsgStream *msg) const {
 
  540   // The pre-processors wrapper collection:
 
  541   for ( size_t ppWrapperIdx = 0; ppWrapperIdx < m_ppWrapperCol.size(); ++ppWrapperIdx ){
 
  542     if ( m_ppWrapperCol[ppWrapperIdx] ) {
 
  543       m_ppWrapperCol[ppWrapperIdx]->setMsgStream(msg);
 
  546   // The discrimination collection:
 
  547   setCollectionMsgStream(msg,m_discrCol);
 
  548   // Set the wrapper message stream:
 
  549   this->RedirectMsgStream::setMsgStream(msg);
 
  552 // =============================================================================
 
  555   /*EtaDependency*/int etaDependency,
 
  556   /*EtDependency*/int etDependency,
 
  557   /*SegmentationType*/int segType
 
  559 std::string RingerProcedureWrapper<
 
  564   false,      // isPreProcessor
 
  565   true,       // isDiscriminator
 
  566   false>      // isThreshold
 
  568   typedef typename RingerProcedureType<procedure_t>::procEnum_t procEnum_t;
 
  569   std::stringstream ss;
 
  570   ss << "RingerProcedureWrapper<"
 
  571         << toStr(procedure_t::template procType<procEnum_t>() )
 
  572         << ((std::is_same<procedure_t,
 
  573                              Discrimination::IDiscriminatorVarDep>::value)?",":
 
  575         << toStr(static_cast<EtaDependency>(etaDependency)) << ","
 
  576         << toStr(static_cast<EtDependency>(etDependency)) << ","
 
  577         << toStr(static_cast<SegmentationType>(segType)) << ">";
 
  581 // =============================================================================
 
  584   /*EtaDependency*/int etaDependency,
 
  585   /*EtDependency*/int etDependency,
 
  586   /*SegmentationType*/int segType
 
  588 std::string RingerProcedureWrapper<
 
  593   false,      // isPreProcessor
 
  594   true,       // isDiscriminator
 
  595   false>      // isThreshold
 
  597   return staticFullName();
 
  600 // =============================================================================
 
  603   /*EtaDependency*/int etaDependency,
 
  604   /*EtDependency*/int etDependency,
 
  605   /*SegmentationType*/int segType
 
  607 void RingerProcedureWrapper<
 
  612   false,      // isPreProcessor
 
  613   true,       // isDiscriminator
 
  614   false>      // isThreshold
 
  615 ::print(MSG::Level lvl) const
 
  617   if ( this->isStreamAvailable() ) {
 
  618     if ( this->level() > lvl ){
 
  619       // Don't waste time to print nothing.
 
  622     this->msg() << lvl << " -------- Printing PreProcesorWrappers -------- "
 
  624     // Print pre-processing collection:
 
  625     for ( size_t ppWrapIdx = 0; ppWrapIdx < m_ppWrapperCol.size(); ++ppWrapIdx )
 
  627       this->msg() << lvl << "PreProcessingWrapper"
 
  628         << IOHelperFcns::makeIdxStr(ppWrapIdx) << endmsg;
 
  629       m_ppWrapperCol[ppWrapIdx]->print( lvl );
 
  631     this->msg() << lvl << " --- Finished printing PreProcessorWrappers --- "
 
  633     // Print discriminators
 
  634     std::vector<unsigned> posVec(3);
 
  635     for ( size_t segIdx = 0; segIdx < m_discrCol.size() ; ++segIdx){
 
  637       for ( size_t etIdx = 0; etIdx < m_discrCol[segIdx].size() ; ++etIdx){
 
  639         for ( size_t etaIdx = 0; etaIdx < m_discrCol[segIdx][etIdx].size();
 
  643           this->msg() << lvl << m_discrCol[segIdx][etIdx][etaIdx]->name() <<
 
  644             IOHelperFcns::makeIdxStr(posVec) << " configuration:" << endmsg;
 
  645           m_discrCol[segIdx][etIdx][etaIdx]->print(lvl);
 
  650     std::cerr << "Stream is not available, cannot print " << fullName() << "."
 
  655 // =============================================================================
 
  658   /*EtaDependency*/int etaDependency,
 
  659   /*EtDependency*/int etDependency,
 
  660   /*SegmentationType*/int segType
 
  662 void RingerProcedureWrapper<
 
  667   false,     // isPreProcessor
 
  668   true,      // isDiscriminator
 
  669   false>     // isThreshold
 
  670 ::write(TDirectory *baseDir, const char *idxStr) const
 
  673   // ----------- Template basics ----------
 
  674   // Create configuration directory
 
  675   TDirectory *configDir = IOHelperFcns::makeDir(baseDir,
 
  676       (std::string(name()) + idxStr).c_str() );
 
  678   // Write basic template information:
 
  679   discrEnum_t discrType = procedure_t::template procType<discrEnum_t>();
 
  680   SegmentationType fileSegType = static_cast<SegmentationType>(segType);
 
  681   EtaDependency fileEtaDep = static_cast<EtaDependency>(etaDependency);
 
  682   EtDependency fileEtDep = static_cast<EtDependency>(etDependency);
 
  683   // FIXME Why do I need to use const? Unfortunately if I don't use so, the
 
  684   // compiler won't accept static_casting from discr_Enum_t to unsigned int:
 
  685   // some issue with reference casting.
 
  686   // It may have something to do with object life time, as const references
 
  687   // have lifetime extended.
 
  688   IOHelperFcns::writeVar<const discrEnum_t, const unsigned int>( configDir,
 
  691   IOHelperFcns::writeVar<const SegmentationType, const unsigned int>( configDir,
 
  694   IOHelperFcns::writeVar<const EtaDependency, const unsigned int>( configDir,
 
  697   IOHelperFcns::writeVar<const EtDependency, const unsigned int>( configDir,
 
  701   // ----------- Pre-processing chain ----------
 
  702   // Write flag whether there is pre-processing chain for this discriminator:
 
  703   IPreProcWrapper::writeCol(m_ppWrapperCol, configDir);
 
  705   // ------------ Discriminators: ---------------
 
  706   // Write size information:
 
  707   unsigned discrSegDepSize = m_discrCol.size();
 
  708   unsigned discrEtDepSize = m_discrCol[0].size();
 
  709   unsigned discrEtaDepSize = m_discrCol[0][0].size();
 
  710   IOHelperFcns::writeVar( configDir,  "discrSegDepSize" , discrSegDepSize );
 
  711   IOHelperFcns::writeVar( configDir,  "discrEtDepSize"  , discrEtDepSize  );
 
  712   IOHelperFcns::writeVar( configDir,  "discrEtaDepSize" , discrEtaDepSize );
 
  713   // Write Discriminator collection
 
  714   std::vector<unsigned int> discrCount(3);
 
  715   for (size_t segIdx = 0;
 
  716       segIdx < m_discrCol.size();
 
  719     discrCount[0] = segIdx;
 
  720     for (size_t etIdx = 0;
 
  721         etIdx < m_discrCol[segIdx].size();
 
  724       discrCount[1] = etIdx;
 
  725       for (size_t etaIdx = 0;
 
  726           etaIdx < m_discrCol[segIdx][etIdx].size();
 
  729         discrCount[2] = etaIdx;
 
  730         m_discrCol[segIdx][etIdx][etaIdx]->write(
 
  732             IOHelperFcns::makeIdxStr(discrCount).c_str());
 
  736   unsigned mask = m_extraDescriptionPatterns.to_ulong();
 
  737   IOHelperFcns::writeVar( configDir
 
  738                         , "extraDescriptionPatterns"
 
  742   // Work on the extra pattern normalization:
 
  743   if (static_cast<bool>(m_extraDescriptionPatterns) ){
 
  744     this->checkExtraPatNorm();
 
  745     unsigned et(0), eta(0);
 
  746     for ( const auto& extraNormVec : m_extraDescriptionNorms ) {
 
  747       for ( const auto extraNorm : extraNormVec ) {
 
  748         std::vector<unsigned> idxs{et,eta};
 
  749         extraNorm->write( configDir, IOHelperFcns::makeIdxStr( idxs ).c_str()  );
 
  758 // =============================================================================
 
  761   /*EtaDependency*/int etaDependency,
 
  762   /*EtDependency*/int etDependency,
 
  763   /*SegmentationType*/int segType
 
  765 RingerProcedureWrapper<procedure_t,
 
  772 RingerProcedureWrapper<
 
  777   false,     // isPreProcessor
 
  778   true,      // isDiscriminator
 
  779   false>     // isThreshold
 
  780 ::read(TDirectory *configDir, unsigned version)
 
  783   using namespace Discrimination;
 
  785   IOHelperFcns::checkDir(configDir);
 
  787   // ----------- Pre-processing chain ----------
 
  788   // Create empty preprocessing wrapper collection:
 
  789   IPreProcWrapperCollection ppWrapperCol;
 
  791   //ATH_MSG_DEBUG("Reading Discrimination Wrapper of type \""
 
  793   //    << "\" named \"" << configDir->GetName()
 
  794   //    << "\" and dependency : ["
 
  795   //    << toStr(segType) << ","
 
  796   //    << toStr(etaDependency) << ","
 
  797   //    << toStr(etDependency) << "]");
 
  799   // Check if this discriminator has pre-processing:
 
  801   IOHelperFcns::readVar( configDir, "hasPP", hasPP );
 
  803   // Fill preprocessing wrapper collection
 
  805     IPreProcWrapper::read( ppWrapperCol, configDir, version );
 
  807     //ATH_MSG_VERBOSE("This Discrimination Wrapper hasn't pre-processors.");
 
  810   // ----------- Discriminators: ----------
 
  811   // Read discrimination collection size:
 
  812   unsigned discrSegDepSize(0),
 
  815   IOHelperFcns::readVar( configDir,  "discrSegDepSize", discrSegDepSize );
 
  816   IOHelperFcns::readVar( configDir,  "discrEtDepSize" , discrEtDepSize  );
 
  817   IOHelperFcns::readVar( configDir,  "discrEtaDepSize", discrEtaDepSize );
 
  819   // Allocate discriminator collection with size specified on file
 
  820   DiscrDepProcCollection discrCol( discrSegDepSize,
 
  821       std::vector< std::vector< procedure_t*> >(
 
  822         discrEtDepSize, std::vector< procedure_t*>(
 
  823           discrEtaDepSize, nullptr )));
 
  825   // Allocate index position retriever:
 
  826   std::vector<unsigned int> discrIdxVec(3,0);
 
  827   std::vector<unsigned int> extraIdxVec(2,0);
 
  829   // Retrieve dir list and loop on it:
 
  830   std::shared_ptr<THashList> list(nullptr);
 
  831   if ( !( list = IOHelperFcns::getDirList(configDir) ) ) {
 
  832     std::runtime_error(std::string("Couldn't retrieve directory "
 
  833           "list from wrapper folder"));
 
  836   // Read description patterns:
 
  839     IOHelperFcns::readVar( configDir,  "extraDescriptionPatterns", mask );
 
  840   } catch ( std::exception &) {
 
  843   Ringer::ExtraDescriptionPatterns extraDescriptionPatterns(mask);
 
  845   ExtraPatternsNormCollection extraDescriptionNorms( discrEtDepSize
 
  846                                                    , std::vector< Ringer::PreProcessing::Norm::ExtraPatternsNorm* >( discrEtaDepSize, nullptr )
 
  849   TIter iter( list.get() );
 
  850   while ( TDirectory* dirObj = static_cast<TDirectory*>(iter()) ) {
 
  852     const char* folderName = dirObj->GetName();
 
  854     //ATH_MSG_VERBOSE("Scanning directory " << folderName );
 
  856     // Filter pre-processing wrapper dirs:
 
  857     if ( IOHelperFcns::startsWith( IRingerProcedureWrapper<PreProcessing::IPreProcessor>::wrapName, folderName) )
 
  859       // Ok, we don't need to scan this directory, we've handled it before.
 
  860       //ATH_MSG_VERBOSE("Directory is PreProcessorWrapper, continuing.." );
 
  863     // Treat extra patterns normalization
 
  864     if ( IOHelperFcns::startsWith( "ExtraPatternsNorm" , folderName) ){
 
  865       if ( ! static_cast<bool>( extraDescriptionPatterns ) ){
 
  866         throw std::runtime_error("Read ExtraPatternsNorm on file whereas no extra description is needed..." );
 
  868       IOHelperFcns::getIdxVecFromStr( folderName, extraIdxVec );
 
  869       auto* extraPatNorm = Ringer::PreProcessing::Norm::ExtraPatternsNormVarDep::read( dirObj );
 
  870       extraDescriptionNorms[ extraIdxVec[0] ][ extraIdxVec[1] ] = extraPatNorm;
 
  873     // Get information about the discriminator on the folder:
 
  874     discrEnum_t discrType;
 
  875     EtaDependency fileEtaDep;
 
  876     EtDependency fileEtDep;
 
  878       IOHelperFcns::readVar<discrEnum_t, unsigned int>(dirObj,
 
  881       IOHelperFcns::readVar<EtaDependency, unsigned int>(dirObj,
 
  884       IOHelperFcns::readVar<EtDependency, unsigned int>(dirObj,
 
  887     } catch (const std::runtime_error &e){
 
  888       throw std::runtime_error(std::string("Couldn't get discriminator type "
 
  889             "while") + "reading folder: " + folderName + ". Reason: "
 
  892     // Check if holden information dependency information is ok:
 
  893     if ( fileEtaDep != etaDependency ){
 
  894       throw std::runtime_error(std::string("Folder \"") + folderName + "\" is "
 
  895           + toStr(fileEtaDep) + " whereas Wrapper is " + toStr(static_cast<EtaDependency>(etaDependency)) + ".");
 
  897     if ( fileEtDep != etDependency ){
 
  898       throw std::runtime_error(std::string("Folder \"") + folderName + "\" is "
 
  899           + toStr(fileEtDep) + " whereas Wrapper is " + toStr(static_cast<EtDependency>(etDependency)) + ".");
 
  901     // Retrieve position indexes where we shall retrieve this discriminator
 
  902     IOHelperFcns::getIdxVecFromStr( folderName, discrIdxVec );
 
  904     // Check if everything is ok on indexes retrieved:
 
  905     if ( discrIdxVec.size() < 3 ||
 
  906         discrIdxVec[0] >= discrSegDepSize ||
 
  907         discrIdxVec[1] >= discrEtDepSize  ||
 
  908         discrIdxVec[2] >= discrEtaDepSize )
 
  910       throw std::runtime_error(std::string("There is something wrong with ")
 
  911             + "folder idxStr: " + folderName + ". Got idxStr " +
 
  912             IOHelperFcns::makeIdxStr(discrIdxVec) + ". Maximum discrimination "
 
  913             "collection size is : " + std::to_string(discrSegDepSize) + "," +
 
  914             std::to_string(discrEtDepSize) + "," + std::to_string(discrEtaDepSize));
 
  917     // Get a reference to the pointer (done only to reduce typing):
 
  918     procedure_t *&thisDiscr = discrCol[discrIdxVec[0]]
 
  922     // Check which procedure_t this discrimination wrapper holds.
 
  923     if ( std::is_same<procedure_t, IDiscriminatorVarDep >::value )
 
  925       // If the procedure_t is not the Discriminator interface, code will
 
  926       // never get here. We only use the interpret cast so that the compiler
 
  927       // doesn't complain about type casting.
 
  928       thisDiscr = dynamic_cast<procedure_t*>( getDiscr(discrType, dirObj) );
 
  930       // Here it's easier, we already know the type that is written in the file,
 
  931       // so all we need to do is loop over it and retrieve the discriminator.
 
  932       discrEnum_t wrapperDiscrType = procedure_t::template procType<discrEnum_t>();
 
  933       if ( discrType != wrapperDiscrType ){
 
  934         throw std::runtime_error( std::string("There is a discriminator of type ") +
 
  935             toStr(discrType) + " whereas this wrapper can only hold discriminators "
 
  936             "of type " + toStr(wrapperDiscrType));
 
  938       thisDiscr = procedure_t::read( dirObj );
 
  940     // ATH_MSG_VERBOSE("Successfully read directory " << folderName);
 
  943   // Create Discrimination wrapper:
 
  944   RingerProcedureWrapper *newWrapper = nullptr;
 
  945   if (ppWrapperCol.empty()) {
 
  946     newWrapper = new RingerProcedureWrapper(discrCol);
 
  948     newWrapper = new RingerProcedureWrapper(ppWrapperCol, discrCol);
 
  951   newWrapper->setExtraDescriptionPatterns( extraDescriptionPatterns );
 
  952   newWrapper->setExtraDescriptionNorms( extraDescriptionNorms );
 
  959 } // Namespace Ringer
 
  961 #endif // RINGERSELECTORTOOLS_PROCEDURES_RINGERDISCRIMINATIONWRAPPER_ICC