CMS 3D CMS Logo

List of all members | Classes | Public Types | Public Member Functions | Public Attributes | Private Member Functions | Private Attributes
EcalDeadChannelRecoveryNN< DetIdT > Class Template Reference

#include <EcalDeadChannelRecoveryNN.h>

Classes

struct  MultiLayerPerceptronContext
 

Public Types

enum  CellID {
  CC = 0, UU = 1, DD = 2, LL = 3,
  LU = 4, LD = 5, RR = 6, RU = 7,
  RD = 8
}
 

Public Member Functions

 EcalDeadChannelRecoveryNN ()
 
double estimateEnergy (double *M3x3Input, double epsilon=0.0000001)
 
double makeNxNMatrice_RelDC (DetIdT itID, const EcalRecHitCollection &hit_collection, double *MNxN_RelDC, bool *AccFlag)
 
double makeNxNMatrice_RelMC (DetIdT itID, const EcalRecHitCollection &hit_collection, double *MNxN_RelMC, bool *AccFlag)
 
double recover (const DetIdT id, const EcalRecHitCollection &hit_collection, double Sum8Cut, bool *AcceptFlag)
 
double reorderMxNMatrix (EBDetId it, const std::vector< DetId > &window, const EcalRecHitCollection &hit_collection, double *MNxN, bool *AcceptFlag)
 
void setCaloTopology (const CaloTopology *topo)
 
 ~EcalDeadChannelRecoveryNN ()
 

Public Attributes

const int CellX [9]
 
const int CellY [9]
 

Private Member Functions

void load ()
 
void load_file (MultiLayerPerceptronContext &ctx, std::string fn)
 

Private Attributes

MultiLayerPerceptronContext ctx_ [9]
 
const CaloSubdetectorTopologytopology_
 

Detailed Description

template<typename DetIdT>
class EcalDeadChannelRecoveryNN< DetIdT >

Definition at line 20 of file EcalDeadChannelRecoveryNN.h.

Member Enumeration Documentation

template<typename DetIdT>
enum EcalDeadChannelRecoveryNN::CellID

Constructor & Destructor Documentation

template<typename T >
EcalDeadChannelRecoveryNN< T >::EcalDeadChannelRecoveryNN ( )

Definition at line 11 of file EcalDeadChannelRecoveryNN.cc.

References triggerObjects_cff::id, and svgfig::load().

11  {
12  for (int id = 0; id < 9; ++id) {
13  ctx_[id].mlp = nullptr;
14  }
15 
16  this->load();
17 }
MultiLayerPerceptronContext ctx_[9]
template<typename T >
EcalDeadChannelRecoveryNN< T >::~EcalDeadChannelRecoveryNN ( )

Definition at line 20 of file EcalDeadChannelRecoveryNN.cc.

References triggerObjects_cff::id.

20  {
21  for (int id = 0; id < 9; ++id) {
22  if (ctx_[id].mlp) {
23  // @TODO segfaults for an uknown reason
24  // delete ctx[id].mlp;
25  // delete ctx[id].tree;
26  }
27  }
28 }
MultiLayerPerceptronContext ctx_[9]

Member Function Documentation

template<typename T >
double EcalDeadChannelRecoveryNN< T >::estimateEnergy ( double *  M3x3Input,
double  epsilon = 0.0000001 
)

Definition at line 177 of file EcalDeadChannelRecoveryNN.cc.

References Abs(), EcalDeadChannelRecoveryNN< DetIdT >::CC, EcalDeadChannelRecoveryNN< DetIdT >::ctx_, EcalDeadChannelRecoveryNN< DetIdT >::DD, mps_fire::i, input, EcalDeadChannelRecoveryNN< DetIdT >::LD, EcalDeadChannelRecoveryNN< DetIdT >::LL, EcalDeadChannelRecoveryNN< DetIdT >::LU, EcalDeadChannelRecoveryNN< DetIdT >::RD, EcalDeadChannelRecoveryNN< DetIdT >::RR, EcalDeadChannelRecoveryNN< DetIdT >::RU, and EcalDeadChannelRecoveryNN< DetIdT >::UU.

Referenced by EcalDeadChannelRecoveryNN< DetIdT >::recover().

177  {
178  int missing[9];
179  int missing_index = 0;
180 
181  for (int i = 0; i < 9; i++) {
182  if (TMath::Abs(M3x3Input[i]) < epsilon) {
183  missing[missing_index++] = i;
184  } else {
185  // Generally the "dead" cells are allowed to have negative energies (since they will be estimated by the ANN anyway).
186  // But all the remaining "live" ones must have positive values otherwise the logarithm fails.
187 
188  if (M3x3Input[i] < 0.0) { return -2000000.0; }
189  }
190  }
191 
192  // Currently EXACTLY ONE AND ONLY ONE dead cell is corrected. Return -1000000.0 if zero DC's detected and -101.0 if more than one DC's exist.
193  int idxDC = -1 ;
194  if (missing_index == 0) { return -1000000.0; } // Zero DC's were detected
195  if (missing_index > 1) { return -1000001.0; } // More than one DC's detected.
196  if (missing_index == 1) { idxDC = missing[0]; }
197 
198  // Arrange inputs into an array of 8, excluding the dead cell;
199  int input_order[9] = { CC, RR, LL, UU, DD, RU, RD, LU, LD };
200  int input_index = 0;
201  Double_t input[8];
202 
203  for (int id : input_order) {
204  if (id == idxDC)
205  continue;
206 
207  input[input_index++] = TMath::Log(M3x3Input[id]);
208  }
209 
210  // Select the case to apply the appropriate NN and return the result.
211  M3x3Input[idxDC] = TMath::Exp(ctx_[idxDC].mlp->Evaluate(0, input));
212  return M3x3Input[idxDC];
213 }
static std::string const input
Definition: EdmProvDump.cc:45
T Abs(T a)
Definition: MathUtil.h:49
MultiLayerPerceptronContext ctx_[9]
template<typename DetIdT>
void EcalDeadChannelRecoveryNN< DetIdT >::load ( )
private
template<typename T >
void EcalDeadChannelRecoveryNN< T >::load_file ( MultiLayerPerceptronContext ctx,
std::string  fn 
)
private

Definition at line 43 of file EcalDeadChannelRecoveryNN.cc.

References edm::FileInPath::fullPath(), EcalDeadChannelRecoveryNN< DetIdT >::MultiLayerPerceptronContext::mlp, eostools::move(), callgraph::path, AlCaHLTBitMon_QueryRunRegistry::string, lumiQTWidget::t, EcalDeadChannelRecoveryNN< DetIdT >::MultiLayerPerceptronContext::tmp, and EcalDeadChannelRecoveryNN< DetIdT >::MultiLayerPerceptronContext::tree.

Referenced by EcalDeadChannelRecoveryNN< EBDetId >::load(), and EcalDeadChannelRecoveryNN< EEDetId >::load().

43  {
45 
46  auto t = std::make_unique<TTree>("t", "dummy MLP tree");
47  t->SetDirectory(nullptr);
48 
49  t->Branch("z1", &(ctx.tmp[0]), "z1/D");
50  t->Branch("z2", &(ctx.tmp[1]), "z2/D");
51  t->Branch("z3", &(ctx.tmp[2]), "z3/D");
52  t->Branch("z4", &(ctx.tmp[3]), "z4/D");
53  t->Branch("z5", &(ctx.tmp[4]), "z5/D");
54  t->Branch("z6", &(ctx.tmp[5]), "z6/D");
55  t->Branch("z7", &(ctx.tmp[6]), "z7/D");
56  t->Branch("z8", &(ctx.tmp[7]), "z8/D");
57  t->Branch("zf", &(ctx.tmp[8]), "zf/D");
58 
59  ctx.tree = std::move(t);
60  //The TMultiLayerPerceptron will create a TEventList
61  // and it will attach itself to the gDirectory
62  // which will be some random TFile in the job
63  // Need to reset gDirectory back to what it was to
64  // avoid causing other code in other modules from
65  // crashing.
66  {
67  auto resetGDirectory = [](TDirectory* oldDir) {gDirectory = oldDir;};
68  std::unique_ptr<TDirectory, decltype(resetGDirectory)> guard(gDirectory, resetGDirectory);
69  gDirectory = nullptr;
70  ctx.mlp =
71  std::make_unique<TMultiLayerPerceptron>("@z1,@z2,@z3,@z4,@z5,@z6,@z7,@z8:10:5:zf", ctx.tree.get());
72  }
73  ctx.mlp->LoadWeights(path.c_str());
74 }
std::string fullPath() const
Definition: FileInPath.cc:197
def move(src, dest)
Definition: eostools.py:511
template<typename DetIdT>
double EcalDeadChannelRecoveryNN< DetIdT >::makeNxNMatrice_RelDC ( DetIdT  itID,
const EcalRecHitCollection hit_collection,
double *  MNxN_RelDC,
bool *  AccFlag 
)
template<typename DetIdT>
double EcalDeadChannelRecoveryNN< DetIdT >::makeNxNMatrice_RelMC ( DetIdT  itID,
const EcalRecHitCollection hit_collection,
double *  MNxN_RelMC,
bool *  AccFlag 
)

Definition at line 216 of file EcalDeadChannelRecoveryNN.cc.

References edm::SortedCollection< T, SORT >::end(), funct::false, edm::SortedCollection< T, SORT >::find(), CaloSubdetectorTopology::getWindow(), EcalDeadChannelRecoveryNN< DetIdT >::makeNxNMatrice_RelDC(), EcalDeadChannelRecoveryNN< DetIdT >::topology_, and funct::true.

Referenced by EcalDeadChannelRecoveryNN< DetIdT >::recover().

216  {
217  // Since ANN corrects within a 3x3 window, the possible candidate 3x3 windows that contain
218  // the "dead" crystal form a 5x5 window around it (totaly eight 3x3 windows overlapping).
219  // Get this 5x5 and locate the Max.Contain.Crystal within.
220 
221  // Get the 5x5 window around the "dead" crystal -> vector "NxNaroundDC"
222  std::vector<DetId> NxNaroundDC = topology_->getWindow(itID, 5, 5);
223 
224  DetIdT CellMax ; // Create a null DetId
225  double EnergyMax = 0.0;
226 
227  // Loop over all cells in the vector "NxNaroundDC", and for each cell find it's energy
228  // (from the EcalRecHits collection). Use this energy to detect the Max.Cont.Crystal.
229  std::vector<DetId>::const_iterator theCells;
230 
231  for (theCells = NxNaroundDC.begin(); theCells != NxNaroundDC.end(); ++theCells) {
232  DetIdT cell = DetIdT(*theCells);
233 
234  if (! cell.null()) {
235  EcalRecHitCollection::const_iterator goS_it = hit_collection.find(cell);
236 
237  if ( goS_it != hit_collection.end() && goS_it->energy() >= EnergyMax ) {
238  EnergyMax = goS_it->energy();
239  CellMax = cell;
240  }
241  }
242  }
243 
244  // No Max.Cont.Crystal found, return back with no changes.
245  if ( CellMax.null() ) { *AcceptFlag=false ; return 0.0 ; }
246 
247 #if 1
248  // Not a smart check, because why not just get 4x4 matrix and have a guaranteed hit?
249 
250  // Check that the "dead" crystal belongs to the 3x3 around Max.Cont.Crystal
251  bool dcIn3x3 = false ;
252 
253  std::vector<DetId> NxNaroundMaxCont = topology_->getWindow(CellMax,3,3);
254  std::vector<DetId>::const_iterator testCell;
255  for (testCell = NxNaroundMaxCont.begin(); testCell != NxNaroundMaxCont.end(); ++testCell) {
256  if ( itID == DetIdT(*testCell) ) { dcIn3x3 = true ; }
257  }
258 
259  // If the "dead" crystal is outside the 3x3 then do nothing.
260  if (!dcIn3x3) { *AcceptFlag=false ; return 0.0 ; }
261 #endif
262 
263  return makeNxNMatrice_RelDC(CellMax, hit_collection, MNxN_RelMC, AcceptFlag);
264 }
std::vector< EcalRecHit >::const_iterator const_iterator
double makeNxNMatrice_RelDC(DetIdT itID, const EcalRecHitCollection &hit_collection, double *MNxN_RelDC, bool *AccFlag)
const CaloSubdetectorTopology * topology_
const_iterator end() const
virtual std::vector< DetId > getWindow(const DetId &id, const int &northSouthSize, const int &eastWestSize) const
iterator find(key_type k)
template<typename T>
double EcalDeadChannelRecoveryNN< T >::recover ( const T  id,
const EcalRecHitCollection hit_collection,
double  Sum8Cut,
bool *  AcceptFlag 
)

Definition at line 107 of file EcalDeadChannelRecoveryNN.cc.

References EcalDeadChannelRecoveryNN< DetIdT >::CC, EcalDeadChannelRecoveryNN< DetIdT >::DD, EcalDeadChannelRecoveryNN< DetIdT >::estimateEnergy(), funct::false, mps_fire::i, EcalDeadChannelRecoveryNN< DetIdT >::LD, EcalDeadChannelRecoveryNN< DetIdT >::LL, EcalDeadChannelRecoveryNN< DetIdT >::LU, EcalDeadChannelRecoveryNN< DetIdT >::makeNxNMatrice_RelDC(), EcalDeadChannelRecoveryNN< DetIdT >::makeNxNMatrice_RelMC(), EcalDeadChannelRecoveryNN< DetIdT >::RD, EcalDeadChannelRecoveryNN< DetIdT >::RR, EcalDeadChannelRecoveryNN< DetIdT >::RU, and EcalDeadChannelRecoveryNN< DetIdT >::UU.

108 {
109  // use the correct probability matrix
110  typedef class EcalCrystalMatrixProbality<T> P;
111 
112  double NewEnergy = 0.0;
113 
114  double NewEnergy_RelMC = 0.0;
115  double NewEnergy_RelDC = 0.0;
116 
117  double MNxN_RelMC[9] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } ;
118  double MNxN_RelDC[9] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } ;
119 
120  double sum8 = 0.0;
121 
122  double sum8_RelMC = makeNxNMatrice_RelMC(id, hit_collection, MNxN_RelMC,AcceptFlag);
123  double sum8_RelDC = makeNxNMatrice_RelDC(id, hit_collection, MNxN_RelDC,AcceptFlag);
124 
125  // Only if "AcceptFlag" is true call the ANN
126  if ( *AcceptFlag ) {
127  if (sum8_RelDC > Sum8Cut && sum8_RelMC > Sum8Cut) {
128  NewEnergy_RelMC = estimateEnergy(MNxN_RelMC);
129  NewEnergy_RelDC = estimateEnergy(MNxN_RelDC);
130 
131  // Matrices "MNxN_RelMC" and "MNxN_RelDC" have now the full set of energies, the original ones plus
132  // whatever "estimates" by the ANN for the "dead" xtal. Use those full matrices and calculate probabilities.
133  //
134  double SumMNxN_RelMC = MNxN_RelMC[LU] + MNxN_RelMC[UU] + MNxN_RelMC[RU] +
135  MNxN_RelMC[LL] + MNxN_RelMC[CC] + MNxN_RelMC[RR] +
136  MNxN_RelMC[LD] + MNxN_RelMC[DD] + MNxN_RelMC[RD] ;
137 
138  double frMNxN_RelMC[9]; for (int i=0; i<9; i++) { frMNxN_RelMC[i] = MNxN_RelMC[i] / SumMNxN_RelMC ; }
139 
140  double prMNxN_RelMC = P::Diagonal( frMNxN_RelMC[LU] ) * P::UpDown( frMNxN_RelMC[UU] ) * P::Diagonal( frMNxN_RelMC[RU] ) *
141  P::ReftRight( frMNxN_RelMC[LL] ) * P::Central( frMNxN_RelMC[CC] ) * P::ReftRight( frMNxN_RelMC[RR] ) *
142  P::Diagonal( frMNxN_RelMC[LD] ) * P::UpDown( frMNxN_RelMC[DD] ) * P::Diagonal( frMNxN_RelMC[RD] ) ;
143 
144  double SumMNxN_RelDC = MNxN_RelDC[LU] + MNxN_RelDC[UU] + MNxN_RelDC[RU] +
145  MNxN_RelDC[LL] + MNxN_RelDC[CC] + MNxN_RelDC[RR] +
146  MNxN_RelDC[LD] + MNxN_RelDC[DD] + MNxN_RelDC[RD] ;
147 
148  double frMNxN_RelDC[9]; for (int i=0; i<9; i++) { frMNxN_RelDC[i] = MNxN_RelDC[i] / SumMNxN_RelDC ; }
149 
150  double prMNxN_RelDC = P::Diagonal( frMNxN_RelDC[LU] ) * P::UpDown( frMNxN_RelDC[UU] ) * P::Diagonal( frMNxN_RelDC[RU] ) *
151  P::ReftRight( frMNxN_RelDC[LL] ) * P::Central( frMNxN_RelDC[CC] ) * P::ReftRight( frMNxN_RelDC[RR] ) *
152  P::Diagonal( frMNxN_RelDC[LD] ) * P::UpDown( frMNxN_RelDC[DD] ) * P::Diagonal( frMNxN_RelDC[RD] ) ;
153 
154  if ( prMNxN_RelDC > prMNxN_RelMC ) { NewEnergy = NewEnergy_RelDC ; sum8 = sum8_RelDC ; }
155  if ( prMNxN_RelDC <= prMNxN_RelMC ) { NewEnergy = NewEnergy_RelMC ; sum8 = sum8_RelMC ; }
156 
157 
158  // If the return value of "CorrectDeadChannelsNN" is one of the followin negative values then
159  // it corresponds to an error condition. See "CorrectDeadChannelsNN.cc" for possible values.
160  if ( NewEnergy == -1000000.0 ||
161  NewEnergy == -1000001.0 ||
162  NewEnergy == -2000000.0 ||
163  NewEnergy == -3000000.0 ||
164  NewEnergy == -3000001.0 ) { *AcceptFlag=false ; NewEnergy = 0.0 ; }
165  }
166  }
167 
168  // Protect against non physical high values
169  // From the distribution of (max.cont.xtal / Sum8) we get as limit 5 (hard) and 10 (softer)
170  // Choose 10 as highest possible energy to be assigned to the dead channel under any scenario.
171  if ( NewEnergy > 10.0 * sum8 ) { *AcceptFlag=false ; NewEnergy = 0.0 ; }
172 
173  return NewEnergy;
174 }
double makeNxNMatrice_RelMC(DetIdT itID, const EcalRecHitCollection &hit_collection, double *MNxN_RelMC, bool *AccFlag)
double makeNxNMatrice_RelDC(DetIdT itID, const EcalRecHitCollection &hit_collection, double *MNxN_RelDC, bool *AccFlag)
double estimateEnergy(double *M3x3Input, double epsilon=0.0000001)
std::pair< OmniClusterRef, TrackingParticleRef > P
long double T
template<typename DetIdT>
double EcalDeadChannelRecoveryNN< DetIdT >::reorderMxNMatrix ( EBDetId  it,
const std::vector< DetId > &  window,
const EcalRecHitCollection hit_collection,
double *  MNxN,
bool *  AcceptFlag 
)
template<typename DetIdT>
void EcalDeadChannelRecoveryNN< DetIdT >::setCaloTopology ( const CaloTopology topo)

Member Data Documentation

template<typename DetIdT>
const int EcalDeadChannelRecoveryNN< DetIdT >::CellX[9]
Initial value:
= { 0, 0, 0 , -1, -1, -1 ,
1, 1, 1 }

Definition at line 52 of file EcalDeadChannelRecoveryNN.h.

template<typename DetIdT>
const int EcalDeadChannelRecoveryNN< DetIdT >::CellY[9]
Initial value:
= { 0, -1, 1 , 0, -1, 1 ,
0, -1, 1 }

Definition at line 55 of file EcalDeadChannelRecoveryNN.h.

template<typename DetIdT>
MultiLayerPerceptronContext EcalDeadChannelRecoveryNN< DetIdT >::ctx_[9]
private
template<typename DetIdT>
const CaloSubdetectorTopology* EcalDeadChannelRecoveryNN< DetIdT >::topology_
private