ATLAS Offline Software
RingerDiscriminatorWrapper.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include<iostream>
6 #include<string>
7 // $Id: RingerDiscriminatorWrapper.icc 791627 2017-01-10 04:45:53Z wsfreund $
8 #ifndef RINGERSELECTORTOOLS_PROCEDURES_RINGERDISCRIMINATIONWRAPPER_ICC
9 #define RINGERSELECTORTOOLS_PROCEDURES_RINGERDISCRIMINATIONWRAPPER_ICC
10 
11 #include "RingerDiscriminatorWrapper.h"
12 #include "RingerProcedureWrapper.icc"
13 
14 #include "RingerSelectorTools/procedures/Normalizations.h"
15 #include "RingerSelectorTools/procedures/NeuralNetwork.h"
16 
17 #include <type_traits>
18 
19 namespace Ringer {
20 
21 namespace WrapperHelperFcns {
22 
23 /**
24  * Return the discriminator on dirObj of ppType
25  **/
26 inline
27 Discrimination::IDiscriminatorVarDep* getDiscr(discrEnum_t discrType,
28  TDirectory *dirObj )
29 {
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:
33  switch ( discrType )
34  {
35  case discrEnum_t::NNFeedForward:
36  {
37  return NNFeedForwardVarDep::read( dirObj );
38  break;
39  }
40  default:
41  {
42  throw std::runtime_error( std::string("Cannot read discriminator of ") +
43  "type: " + toStr(discrType) );
44  }
45  }
46 }
47 
48 inline
49 void addExtraDescription( std::vector<float> &input
50  , const DepVarStruct& depVar
51  , const Ringer::PreProcessing::Norm::ExtraPatternsNorm* extraPatNorm
52  , const Ringer::ExtraDescriptionPatterns& extraDescr )
53 {
54  if ( extraPatNorm == nullptr ) {
55  throw std::runtime_error( std::string("Attempted to add description with empty norm") );
56  }
57  if( extraDescr.feedEta() ){
58  input.push_back( extraPatNorm->normEta( depVar.eta ) );
59  }
60  if( extraDescr.feedEt() ){
61  input.push_back( extraPatNorm->normEt( depVar.et ) );
62  }
63  if( extraDescr.feedPileupEstimation() ){
64  input.push_back( extraPatNorm->normPileupEstimation( depVar.pileupEstimation ) );
65  }
66 }
67 } // WrapperHelperFcns
68 
69 // Import Wrapper Helper functions
70 using namespace WrapperHelperFcns;
71 
72 // =============================================================================
73 // -----------------------------------------
74 // RingerProcedureWrapper for Discriminators
75 // -----------------------------------------
76 // =============================================================================
77 
78 // =============================================================================
79 template <
80  class procedure_t,
81  /*EtaDependency*/int etaDependency,
82  /*EtDependency*/int etDependency,
83  /*SegmentationType*/int segType
84 >
85 void RingerProcedureWrapper<
86  procedure_t,
87  etaDependency,
88  etDependency,
89  segType,
90  false, // isPreProcessor
91  true, // isDiscriminator
92  false> // isThreshold
93 ::releaseMemory()
94 {
95  for ( size_t ppColIdx = 0; ppColIdx < m_ppWrapperCol.size(); ++ppColIdx){
96  if (m_ppWrapperCol[ppColIdx]){
97  m_ppWrapperCol[ppColIdx]->releaseMemory();
98  }
99  }
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();
103  ++etaIdx)
104  {
105  delete m_discrCol[segIdx][etIdx][etaIdx];
106  }
107  }
108  }
109  m_discrCol.clear();
110  m_discr = nullptr;
111 }
112 
113 // =============================================================================
114 template <
115  class procedure_t,
116  /*EtaDependency*/int etaDependency,
117  /*EtDependency*/int etDependency,
118  /*SegmentationType*/int segType
119 >
120 void RingerProcedureWrapper<
121  procedure_t,
122  etaDependency,
123  etDependency,
124  segType,
125  false, // isPreProcessor
126  true, // isDiscriminator
127  false> // isThreshold
128 ::execute(
129  const DepVarStruct &depVar,
130  const xAOD::CaloRings *clrings,
131  const TrackPatternsHolder *trackPat,
132  std::vector<float> &output) const
133 {
134 #ifndef NDEBUG
135  ATH_MSG_DEBUG("Applying first discrimination layer discriminators.");
136 #endif
137 
138  // Clear any previous output:
139  output.clear();
140 
141  // We will put pre-processing results into this vector:
142  std::vector<float> transformVec;
143 
144 #ifndef NDEBUG
145  ATH_MSG_DEBUG( "Allocating space on transformVec of size " <<
146  (((clrings)?(m_nRings):0) +
147  ((trackPat)?TrackPatternsHolder::numberOfPatterns():0)));
148 #endif
149 
150  // We grant it enougth space to handle worst case:
151  transformVec.reserve(
152  (clrings)?(m_nRings):(0 +
153  ((trackPat)?TrackPatternsHolder::numberOfPatterns():0))
154  );
155 
156  std::vector<float> input = transformVec;
157 
158  if ( m_ppWrapperCol.empty() ) {
159  // Otherwise simply push-back information:
160  if (clrings){
161  clrings->exportRingsTo(transformVec);
162  }
163  if (trackPat){
164  trackPat->exportPatternsTo(transformVec);
165  }
166  } else {
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
170  // it.
171 
172  // If pre-processing available execute it:
173  for ( size_t ppIdx = 0; ppIdx < m_ppWrapperCol.size(); ++ppIdx ){
174  m_ppWrapperCol[ppIdx]->applyPreProcessing(
175  depVar,
176  clrings,
177  trackPat,
178  transformVec);
179  }
180  }
181 
182  // Initialize eta and et indexes:
183  size_t etaIdx(0), etIdx(0);
184  // Get the correct idx to be applied:
185  if (etaDependency) {
186  etaIdx = findEtaBin(depVar.eta, m_discrCol[0]);
187  }
188  if (etDependency) {
189  etIdx = findEtBin(depVar.et, m_discrCol[0]);
190  }
191 
192  size_t cDiscr = 0;
193 
194  switch(segType){
195  case SegmentationType::NoSegmentation:
196  {
197 
198 #ifndef NDEBUG
199  ATH_MSG_VERBOSE("Applying NonSegmented"
200  " discriminator at etaIdx (" << etaIdx << ") and etIdx ("
201  << etIdx << ").");
202 #endif
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 );
207  }
208  // Apply discrimination to all transformed space:
209  m_discrCol[cDiscr++][etIdx][etaIdx]->execute(input,output);
210  break;
211  }
212  case SegmentationType::TrackCalSegmentation:
213  {
214 #ifndef NDEBUG
215  ATH_MSG_VERBOSE("Applying Track/Cal segmented"
216  " discriminators at etaIdx (" << etaIdx << ") and etIdx ("
217  << etIdx << ").");
218 #endif
219  if (clrings){
220  // Apply discrimination to CaloRings as one:
221  getCaloSegmentFromTransformVec( m_nRings,
222  transformVec,
223  input);
224 
225  if ( static_cast<bool>(m_extraDescriptionPatterns) ) {
226  // Add demanded extra description
227  addExtraDescription( input, depVar, m_extraDescriptionNorms.at(etIdx).at(etaIdx), m_extraDescriptionPatterns );
228  }
229 
230  executeSegmentedDiscr(
231  input,
232  m_discrCol[cDiscr++][etIdx][etaIdx],
233  output);
234  } else {
235  cDiscr += 1;
236  }
237  if (trackPat){
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,
243  transformVec,
244  input);
245 
246  if ( static_cast<bool>(m_extraDescriptionPatterns) ) {
247  // Add demanded extra description
248  addExtraDescription( input, depVar, m_extraDescriptionNorms.at(etIdx).at(etaIdx), m_extraDescriptionPatterns );
249  }
250 
251  executeSegmentedDiscr(
252  input,
253  m_discrCol[cDiscr++][etIdx][etaIdx],
254  output);
255  } else {
256  cDiscr += 1;
257  }
258  break;
259  }
260  case SegmentationType::TrackCalPatTypeSegmentation:
261  {
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)) );
265  }
266  case SegmentationType::TrackCalJointSections:
267  {
268 #ifndef NDEBUG
269  ATH_MSG_VERBOSE("Applying Track/Cal-JointSections segmented"
270  " discriminators at etaIdx (" << etaIdx << ") and etIdx ("
271  << etIdx << ").");
272 #endif
273  if (clrings){
274  // Apply discrimination to each CalJointSection:
275  while ( cDiscr < static_cast<size_t>(
276  CalJointSection::NJointSections) )
277  {
278  getCaloSegmentFromTransformVec(
279  *m_rsRawConfCol,
280  static_cast<CalJointSection>(cDiscr),
281  transformVec,
282  input);
283 
284  if ( static_cast<bool>(m_extraDescriptionPatterns) ) {
285  // Add demanded extra description
286  addExtraDescription( input, depVar, m_extraDescriptionNorms.at(etIdx).at(etaIdx), m_extraDescriptionPatterns );
287  }
288 
289  executeSegmentedDiscr(
290  input,
291  m_discrCol[cDiscr++][etIdx][etaIdx],
292  output);
293  }
294  } else {
295  cDiscr += static_cast<size_t>(CalJointSection::NJointSections);
296  }
297  if (trackPat) {
298  // Apply discrimination to Track separated:
299  getTrackSegmentFromTransformVec(
300  (clrings)?(m_nRings):0,
301  transformVec,
302  input);
303 
304  if ( static_cast<bool>(m_extraDescriptionPatterns) ) {
305  // Add demanded extra description
306  addExtraDescription( input, depVar, m_extraDescriptionNorms.at(etIdx).at(etaIdx), m_extraDescriptionPatterns );
307  }
308 
309  executeSegmentedDiscr(
310  input,
311  m_discrCol[cDiscr++][etIdx][etaIdx],
312  output);
313  } else {
314  cDiscr += 1;
315  }
316  break;
317  }
318  case SegmentationType::TrackCalJointLayers:
319  {
320 #ifndef NDEBUG
321  ATH_MSG_VERBOSE("Applying Track/Cal-JointLayers segmented"
322  " discriminators at etaIdx (" << etaIdx << ") and etIdx ("
323  << etIdx << ").");
324 #endif
325  if (clrings){
326  // Apply discrimination to each CalJointLayer:
327  while ( cDiscr < static_cast<size_t>(
328  CalJointLayer::NJointLayers) )
329  {
330  getCaloSegmentFromTransformVec(
331  *m_rsRawConfCol,
332  static_cast<CalJointLayer>(cDiscr),
333  transformVec,
334  input);
335 
336  if ( static_cast<bool>(m_extraDescriptionPatterns) ) {
337  // Add demanded extra description
338  addExtraDescription( input, depVar, m_extraDescriptionNorms.at(etIdx).at(etaIdx), m_extraDescriptionPatterns );
339  }
340 
341  executeSegmentedDiscr(
342  input,
343  m_discrCol[cDiscr++][etIdx][etaIdx],
344  output);
345  }
346  } else {
347  cDiscr += static_cast<size_t>(CalJointLayer::NJointLayers);
348  }
349  if (trackPat){
350  // Apply discrimination to Track separated:
351  getTrackSegmentFromTransformVec(
352  (clrings)?(m_nRings):0,
353  transformVec,
354  input);
355 
356  if ( static_cast<bool>(m_extraDescriptionPatterns) ) {
357  // Add demanded extra description
358  addExtraDescription( input, depVar, m_extraDescriptionNorms.at(etIdx).at(etaIdx), m_extraDescriptionPatterns );
359  }
360 
361  executeSegmentedDiscr(
362  input,
363  m_discrCol[cDiscr++][etIdx][etaIdx],
364  output);
365  } else {
366  cDiscr += 1;
367  }
368  break;
369  }
370  }
371  return;
372 }
373 
374 // =============================================================================
375 template <
376  class procedure_t,
377  /*EtaDependency*/int etaDependency,
378  /*EtDependency*/int etDependency,
379  /*SegmentationType*/int segType
380 >
381 void RingerProcedureWrapper<
382  procedure_t,
383  etaDependency,
384  etDependency,
385  segType,
386  false, // isPreProcessor
387  true, // isDiscriminator
388  false> // isThreshold
389 ::execute(
390  const DepVarStruct &depVar,
391  const std::vector<float> &input,
392  std::vector<float> &output) const
393 {
394 #ifndef NDEBUG
395  ATH_MSG_DEBUG("Applying internal discrimination layer discriminators.");
396 #endif
397 
398  // This method only applies for segType NoSegmentation.
399  ensureNoSegmentationOnlyFcn(static_cast<SegmentationType>(segType));
400 
401  // Copy input:
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);
406  }
407 
408  if (!etaDependency && !etDependency){
409  m_discr->execute(inputCopy,output);
410  return;
411  }
412 
413  // Initialize eta and et indexes:
414  size_t etaIdx(0), etIdx(0);
415 
416  // Get the correct idx to be applied:
417  if (etaDependency){
418  etaIdx = findEtaBin(depVar.eta, m_discrCol[0]);
419  }
420  if (etDependency){
421  etIdx = findEtBin(depVar.et, m_discrCol[0]);
422  }
423 
424  if ( static_cast<bool>(m_extraDescriptionPatterns) ) {
425  // Add demanded extra description
426  addExtraDescription( inputCopy, depVar, m_extraDescriptionNorms.at(etIdx).at(etaIdx), m_extraDescriptionPatterns );
427  }
428 
429  // Apply it:
430  m_discrCol[0][etIdx][etaIdx]->execute(inputCopy,output);
431 }
432 
433 // =============================================================================
434 template <
435  class procedure_t,
436  /*EtaDependency*/int etaDependency,
437  /*EtDependency*/int etDependency,
438  /*SegmentationType*/int segType
439 >
440 void RingerProcedureWrapper<
441  procedure_t,
442  etaDependency,
443  etDependency,
444  segType,
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."));
456 
457  }
458  for ( size_t ppWrapperIdx = 0; ppWrapperIdx < m_ppWrapperCol.size();
459  ++ppWrapperIdx ){
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."));
466  }
467  }
468 }
469 
470 // =============================================================================
471 template <
472  class procedure_t,
473  /*EtaDependency*/int etaDependency,
474  /*EtDependency*/int etDependency,
475  /*SegmentationType*/int segType
476 >
477 void RingerProcedureWrapper<
478  procedure_t,
479  etaDependency,
480  etDependency,
481  segType,
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") );
488  }
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") );
491  }
492 }
493 
494 // =============================================================================
495 template <
496  class procedure_t,
497  /*EtaDependency*/int etaDependency,
498  /*EtDependency*/int etDependency,
499  /*SegmentationType*/int segType
500 >
501 void RingerProcedureWrapper<
502  procedure_t,
503  etaDependency,
504  etDependency,
505  segType,
506  false, // isPreProcessor
507  true, // isDiscriminator
508  false> // isThreshold
509 ::checkDiscrCol() const {
510  try {
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."));
517  }
518  } catch ( const std::runtime_error &e ) {
519  throw std::runtime_error(std::string("Couldn't initialize RingerDiscriminationWrapper collection due to: ")
520  + e.what() );
521  }
522 }
523 
524 // =============================================================================
525 template <
526  class procedure_t,
527  /*EtaDependency*/int etaDependency,
528  /*EtDependency*/int etDependency,
529  /*SegmentationType*/int segType
530 >
531 void RingerProcedureWrapper<
532  procedure_t,
533  etaDependency,
534  etDependency,
535  segType,
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);
544  }
545  }
546  // The discrimination collection:
547  setCollectionMsgStream(msg,m_discrCol);
548  // Set the wrapper message stream:
549  this->RedirectMsgStream::setMsgStream(msg);
550 }
551 
552 // =============================================================================
553 template <
554  class procedure_t,
555  /*EtaDependency*/int etaDependency,
556  /*EtDependency*/int etDependency,
557  /*SegmentationType*/int segType
558 >
559 std::string RingerProcedureWrapper<
560  procedure_t,
561  etaDependency,
562  etDependency,
563  segType,
564  false, // isPreProcessor
565  true, // isDiscriminator
566  false> // isThreshold
567 ::staticFullName() {
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)?",":
574  "(VarDep),")
575  << toStr(static_cast<EtaDependency>(etaDependency)) << ","
576  << toStr(static_cast<EtDependency>(etDependency)) << ","
577  << toStr(static_cast<SegmentationType>(segType)) << ">";
578  return ss.str();
579 }
580 
581 // =============================================================================
582 template <
583  class procedure_t,
584  /*EtaDependency*/int etaDependency,
585  /*EtDependency*/int etDependency,
586  /*SegmentationType*/int segType
587 >
588 std::string RingerProcedureWrapper<
589  procedure_t,
590  etaDependency,
591  etDependency,
592  segType,
593  false, // isPreProcessor
594  true, // isDiscriminator
595  false> // isThreshold
596 ::fullName() const {
597  return staticFullName();
598 }
599 
600 // =============================================================================
601 template <
602  class procedure_t,
603  /*EtaDependency*/int etaDependency,
604  /*EtDependency*/int etDependency,
605  /*SegmentationType*/int segType
606 >
607 void RingerProcedureWrapper<
608  procedure_t,
609  etaDependency,
610  etDependency,
611  segType,
612  false, // isPreProcessor
613  true, // isDiscriminator
614  false> // isThreshold
615 ::print(MSG::Level lvl) const
616 {
617  if ( this->isStreamAvailable() ) {
618  if ( this->level() > lvl ){
619  // Don't waste time to print nothing.
620  return;
621  }
622  this->msg() << lvl << " -------- Printing PreProcesorWrappers -------- "
623  << endmsg;
624  // Print pre-processing collection:
625  for ( size_t ppWrapIdx = 0; ppWrapIdx < m_ppWrapperCol.size(); ++ppWrapIdx )
626  {
627  this->msg() << lvl << "PreProcessingWrapper"
628  << IOHelperFcns::makeIdxStr(ppWrapIdx) << endmsg;
629  m_ppWrapperCol[ppWrapIdx]->print( lvl );
630  }
631  this->msg() << lvl << " --- Finished printing PreProcessorWrappers --- "
632  << endmsg;
633  // Print discriminators
634  std::vector<unsigned> posVec(3);
635  for ( size_t segIdx = 0; segIdx < m_discrCol.size() ; ++segIdx){
636  posVec[0] = segIdx;
637  for ( size_t etIdx = 0; etIdx < m_discrCol[segIdx].size() ; ++etIdx){
638  posVec[1] = etIdx;
639  for ( size_t etaIdx = 0; etaIdx < m_discrCol[segIdx][etIdx].size();
640  ++etaIdx)
641  {
642  posVec[2] = etaIdx;
643  this->msg() << lvl << m_discrCol[segIdx][etIdx][etaIdx]->name() <<
644  IOHelperFcns::makeIdxStr(posVec) << " configuration:" << endmsg;
645  m_discrCol[segIdx][etIdx][etaIdx]->print(lvl);
646  }
647  }
648  }
649  } else {
650  std::cerr << "Stream is not available, cannot print " << fullName() << "."
651  << std::endl;
652  }
653 }
654 
655 // =============================================================================
656 template <
657  class procedure_t,
658  /*EtaDependency*/int etaDependency,
659  /*EtDependency*/int etDependency,
660  /*SegmentationType*/int segType
661 >
662 void RingerProcedureWrapper<
663  procedure_t,
664  etaDependency,
665  etDependency,
666  segType,
667  false, // isPreProcessor
668  true, // isDiscriminator
669  false> // isThreshold
670 ::write(TDirectory *baseDir, const char *idxStr) const
671 {
672 
673  // ----------- Template basics ----------
674  // Create configuration directory
675  TDirectory *configDir = IOHelperFcns::makeDir(baseDir,
676  (std::string(name()) + idxStr).c_str() );
677 
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,
689  "discrType",
690  discrType);
691  IOHelperFcns::writeVar<const SegmentationType, const unsigned int>( configDir,
692  "segType",
693  fileSegType);
694  IOHelperFcns::writeVar<const EtaDependency, const unsigned int>( configDir,
695  "etaDependency",
696  fileEtaDep);
697  IOHelperFcns::writeVar<const EtDependency, const unsigned int>( configDir,
698  "etDependency",
699  fileEtDep);
700 
701  // ----------- Pre-processing chain ----------
702  // Write flag whether there is pre-processing chain for this discriminator:
703  IPreProcWrapper::writeCol(m_ppWrapperCol, configDir);
704 
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();
717  ++segIdx)
718  {
719  discrCount[0] = segIdx;
720  for (size_t etIdx = 0;
721  etIdx < m_discrCol[segIdx].size();
722  ++etIdx)
723  {
724  discrCount[1] = etIdx;
725  for (size_t etaIdx = 0;
726  etaIdx < m_discrCol[segIdx][etIdx].size();
727  ++etaIdx)
728  {
729  discrCount[2] = etaIdx;
730  m_discrCol[segIdx][etIdx][etaIdx]->write(
731  configDir,
732  IOHelperFcns::makeIdxStr(discrCount).c_str());
733  }
734  }
735  }
736  unsigned mask = m_extraDescriptionPatterns.to_ulong();
737  IOHelperFcns::writeVar( configDir
738  , "extraDescriptionPatterns"
739  , mask
740  );
741 
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() );
750  ++eta;
751  }
752  ++et; eta = 0;
753  }
754  }
755 
756 }
757 
758 // =============================================================================
759 template <
760  class procedure_t,
761  /*EtaDependency*/int etaDependency,
762  /*EtDependency*/int etDependency,
763  /*SegmentationType*/int segType
764 >
765 RingerProcedureWrapper<procedure_t,
766  etaDependency,
767  etDependency,
768  segType,
769  false,
770  true,
771  false> *
772 RingerProcedureWrapper<
773  procedure_t,
774  etaDependency,
775  etDependency,
776  segType,
777  false, // isPreProcessor
778  true, // isDiscriminator
779  false> // isThreshold
780 ::read(TDirectory *configDir, unsigned version)
781 {
782 
783  using namespace Discrimination;
784 
785  IOHelperFcns::checkDir(configDir);
786 
787  // ----------- Pre-processing chain ----------
788  // Create empty preprocessing wrapper collection:
789  IPreProcWrapperCollection ppWrapperCol;
790 
791  //ATH_MSG_DEBUG("Reading Discrimination Wrapper of type \""
792  // << ppType.Data()
793  // << "\" named \"" << configDir->GetName()
794  // << "\" and dependency : ["
795  // << toStr(segType) << ","
796  // << toStr(etaDependency) << ","
797  // << toStr(etDependency) << "]");
798 
799  // Check if this discriminator has pre-processing:
800  bool hasPP(false);
801  IOHelperFcns::readVar( configDir, "hasPP", hasPP );
802 
803  // Fill preprocessing wrapper collection
804  if (hasPP) {
805  IPreProcWrapper::read( ppWrapperCol, configDir, version );
806  } else {
807  //ATH_MSG_VERBOSE("This Discrimination Wrapper hasn't pre-processors.");
808  }
809 
810  // ----------- Discriminators: ----------
811  // Read discrimination collection size:
812  unsigned discrSegDepSize(0),
813  discrEtDepSize(0),
814  discrEtaDepSize(0);
815  IOHelperFcns::readVar( configDir, "discrSegDepSize", discrSegDepSize );
816  IOHelperFcns::readVar( configDir, "discrEtDepSize" , discrEtDepSize );
817  IOHelperFcns::readVar( configDir, "discrEtaDepSize", discrEtaDepSize );
818 
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 )));
824 
825  // Allocate index position retriever:
826  std::vector<unsigned int> discrIdxVec(3,0);
827  std::vector<unsigned int> extraIdxVec(2,0);
828 
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"));
834  }
835 
836  // Read description patterns:
837  unsigned mask(0);
838  try{
839  IOHelperFcns::readVar( configDir, "extraDescriptionPatterns", mask );
840  } catch ( std::exception &) {
841  // old file, all ok
842  }
843  Ringer::ExtraDescriptionPatterns extraDescriptionPatterns(mask);
844 
845  ExtraPatternsNormCollection extraDescriptionNorms( discrEtDepSize
846  , std::vector< Ringer::PreProcessing::Norm::ExtraPatternsNorm* >( discrEtaDepSize, nullptr )
847  );
848 
849  TIter iter( list.get() );
850  while ( TDirectory* dirObj = static_cast<TDirectory*>(iter()) ) {
851 
852  const char* folderName = dirObj->GetName();
853 
854  //ATH_MSG_VERBOSE("Scanning directory " << folderName );
855 
856  // Filter pre-processing wrapper dirs:
857  if ( IOHelperFcns::startsWith( IRingerProcedureWrapper<PreProcessing::IPreProcessor>::wrapName, folderName) )
858  {
859  // Ok, we don't need to scan this directory, we've handled it before.
860  //ATH_MSG_VERBOSE("Directory is PreProcessorWrapper, continuing.." );
861  continue;
862  }
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..." );
867  }
868  IOHelperFcns::getIdxVecFromStr( folderName, extraIdxVec );
869  auto* extraPatNorm = Ringer::PreProcessing::Norm::ExtraPatternsNormVarDep::read( dirObj );
870  extraDescriptionNorms[ extraIdxVec[0] ][ extraIdxVec[1] ] = extraPatNorm;
871  continue;
872  }
873  // Get information about the discriminator on the folder:
874  discrEnum_t discrType;
875  EtaDependency fileEtaDep;
876  EtDependency fileEtDep;
877  try {
878  IOHelperFcns::readVar<discrEnum_t, unsigned int>(dirObj,
879  "procType",
880  discrType);
881  IOHelperFcns::readVar<EtaDependency, unsigned int>(dirObj,
882  "etaDependency",
883  fileEtaDep);
884  IOHelperFcns::readVar<EtDependency, unsigned int>(dirObj,
885  "etDependency",
886  fileEtDep);
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: "
890  + e.what() );
891  }
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)) + ".");
896  }
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)) + ".");
900  }
901  // Retrieve position indexes where we shall retrieve this discriminator
902  IOHelperFcns::getIdxVecFromStr( folderName, discrIdxVec );
903 
904  // Check if everything is ok on indexes retrived:
905  if ( discrIdxVec.size() < 3 ||
906  discrIdxVec[0] >= discrSegDepSize ||
907  discrIdxVec[1] >= discrEtDepSize ||
908  discrIdxVec[2] >= discrEtaDepSize )
909  {
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));
915  }
916 
917  // Get a reference to the pointer (done only to reduce typing):
918  procedure_t *&thisDiscr = discrCol[discrIdxVec[0]]
919  [discrIdxVec[1]]
920  [discrIdxVec[2]];
921 
922  // Check which procedure_t this discrimination wrapper holds.
923  if ( std::is_same<procedure_t, IDiscriminatorVarDep >::value )
924  {
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) );
929  } else {
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));
937  }
938  thisDiscr = procedure_t::read( dirObj );
939  }
940  // ATH_MSG_VERBOSE("Successfully read directory " << folderName);
941  }
942 
943  // Create Discrimination wrapper:
944  RingerProcedureWrapper *newWrapper = nullptr;
945  if (ppWrapperCol.empty()) {
946  newWrapper = new RingerProcedureWrapper(discrCol);
947  } else {
948  newWrapper = new RingerProcedureWrapper(ppWrapperCol, discrCol);
949  }
950 
951  newWrapper->setExtraDescriptionPatterns( extraDescriptionPatterns );
952  newWrapper->setExtraDescriptionNorms( extraDescriptionNorms );
953 
954  return newWrapper;
955 
956 }
957 /// @}
958 
959 } // Namespace Ringer
960 
961 #endif // RINGERSELECTORTOOLS_PROCEDURES_RINGERDISCRIMINATIONWRAPPER_ICC