CMS 3D CMS Logo

EcalUncalibRecHitMultiFitAlgo.cc
Go to the documentation of this file.
2 
4 
7 
9  _computeErrors(true),
10  _doPrefit(false),
11  _prefitMaxChiSq(1.0),
12  _dynamicPedestals(false),
13  _mitigateBadSamples(false),
14  _selectiveBadSampleCriteria(false),
15  _addPedestalUncertainty(0.),
16  _simplifiedNoiseModelForGainSwitch(true),
17  _gainSwitchUseMaxSample(false){
18 
19  _singlebx.resize(1);
20  _singlebx << 0;
21 
25 
26 }
27 
29 EcalUncalibratedRecHit EcalUncalibRecHitMultiFitAlgo::makeRecHit(const EcalDataFrame& dataFrame, const EcalPedestals::Item * aped, const EcalMGPAGainRatio * aGain, const SampleMatrixGainArray &noisecors, const FullSampleVector &fullpulse, const FullSampleMatrix &fullpulsecov, const BXVector &activeBX) {
30 
31  uint32_t flags = 0;
32 
33  const unsigned int nsample = EcalDataFrame::MAXSAMPLES;
34 
35  double maxamplitude = -std::numeric_limits<double>::max();
36  const unsigned int iSampleMax = 5;
37  const unsigned int iFullPulseMax = 9;
38 
39  double pedval = 0.;
40 
41  SampleVector amplitudes;
42  SampleGainVector gainsNoise;
43  SampleGainVector gainsPedestal;
44  SampleGainVector badSamples = SampleGainVector::Zero();
45  bool hasSaturation = dataFrame.isSaturated();
46  bool hasGainSwitch = hasSaturation || dataFrame.hasSwitchToGain6() || dataFrame.hasSwitchToGain1();
47 
48  //no dynamic pedestal in case of gain switch, since then the fit becomes too underconstrained
49  bool dynamicPedestal = _dynamicPedestals && !hasGainSwitch;
50 
51  for(unsigned int iSample = 0; iSample < nsample; iSample++) {
52 
53  const EcalMGPASample &sample = dataFrame.sample(iSample);
54 
55  double amplitude = 0.;
56  int gainId = sample.gainId();
57 
58  double pedestal = 0.;
59  double gainratio = 1.;
60 
61  if (gainId==0 || gainId==3) {
62  pedestal = aped->mean_x1;
63  gainratio = aGain->gain6Over1()*aGain->gain12Over6();
64  gainsNoise[iSample] = 2;
65  gainsPedestal[iSample] = dynamicPedestal ? 2 : -1; //-1 for static pedestal
66  }
67  else if (gainId==1) {
68  pedestal = aped->mean_x12;
69  gainratio = 1.;
70  gainsNoise[iSample] = 0;
71  gainsPedestal[iSample] = dynamicPedestal ? 0 : -1; //-1 for static pedestal
72  }
73  else if (gainId==2) {
74  pedestal = aped->mean_x6;
75  gainratio = aGain->gain12Over6();
76  gainsNoise[iSample] = 1;
77  gainsPedestal[iSample] = dynamicPedestal ? 1 : -1; //-1 for static pedestals
78  }
79 
80  if (dynamicPedestal) {
81  amplitude = (double)(sample.adc())*gainratio;
82  }
83  else {
84  amplitude = ((double)(sample.adc()) - pedestal) * gainratio;
85  }
86 
87  if (gainId == 0) {
88  edm::LogError("EcalUncalibRecHitMultiFitAlgo")<< "Saturation encountered. Multifit is not intended to be used for saturated channels.";
89  //saturation
90  if (dynamicPedestal) {
91  amplitude = 4095.*gainratio;
92  }
93  else {
94  amplitude = (4095. - pedestal) * gainratio;
95  }
96  }
97 
98  amplitudes[iSample] = amplitude;
99 
100  if (iSample==iSampleMax) {
101  maxamplitude = amplitude;
102  pedval = pedestal;
103  }
104 
105  }
106 
107  double amplitude, amperr, chisq;
108  bool status = false;
109 
110  //special handling for gain switch, where sample before maximum is potentially affected by slew rate limitation
111  //optionally apply a stricter criteria, assuming slew rate limit is only reached in case where maximum sample has gain switched but previous sample has not
112  //option 1: use simple max-sample algorithm
113  if (hasGainSwitch && _gainSwitchUseMaxSample) {
114  double maxpulseamplitude = maxamplitude / fullpulse[iFullPulseMax];
115  EcalUncalibratedRecHit rh( dataFrame.id(), maxpulseamplitude, pedval, 0., 0., flags );
116  rh.setAmplitudeError(0.);
117  for (unsigned int ipulse=0; ipulse<_pulsefunc.BXs().rows(); ++ipulse) {
118  int bx = _pulsefunc.BXs().coeff(ipulse);
119  if (bx!=0) {
120  rh.setOutOfTimeAmplitude(bx+5, 0.0);
121  }
122  }
123  return rh;
124  }
125 
126  //option2: A floating negative single-sample offset is added to the fit
127  //such that the affected sample is treated only as a lower limit for the true amplitude
128  bool mitigateBadSample = _mitigateBadSamples && hasGainSwitch && iSampleMax>0;
129  mitigateBadSample &= (!_selectiveBadSampleCriteria || (gainsNoise.coeff(iSampleMax-1)!=gainsNoise.coeff(iSampleMax)) );
130  if (mitigateBadSample) {
131  badSamples[iSampleMax-1] = 1;
132  }
133 
134  //compute noise covariance matrix, which depends on the sample gains
135  SampleMatrix noisecov;
136  if (hasGainSwitch) {
137  std::array<double,3> pedrmss = {{aped->rms_x12, aped->rms_x6, aped->rms_x1}};
138  std::array<double,3> gainratios = {{ 1., aGain->gain12Over6(), aGain->gain6Over1()*aGain->gain12Over6()}};
140  int gainidxmax = gainsNoise[iSampleMax];
141  noisecov = gainratios[gainidxmax]*gainratios[gainidxmax]*pedrmss[gainidxmax]*pedrmss[gainidxmax]*noisecors[gainidxmax];
142  if (!dynamicPedestal && _addPedestalUncertainty>0.) {
143  //add fully correlated component to noise covariance to inflate pedestal uncertainty
144  noisecov += _addPedestalUncertainty*_addPedestalUncertainty*SampleMatrix::Ones();
145  }
146  }
147  else {
148  noisecov = SampleMatrix::Zero();
149  for (unsigned int gainidx=0; gainidx<noisecors.size(); ++gainidx) {
150  SampleGainVector mask = gainidx*SampleGainVector::Ones();
151  SampleVector pedestal = (gainsNoise.array()==mask.array()).cast<SampleVector::value_type>();
152  if (pedestal.maxCoeff()>0.) {
153  //select out relevant components of each correlation matrix, and assume no correlation between samples with
154  //different gain
155  noisecov += gainratios[gainidx]*gainratios[gainidx]*pedrmss[gainidx]*pedrmss[gainidx]*pedestal.asDiagonal()*noisecors[gainidx]*pedestal.asDiagonal();
156  if (!dynamicPedestal && _addPedestalUncertainty>0.) {
157  //add fully correlated component to noise covariance to inflate pedestal uncertainty
158  noisecov += gainratios[gainidx]*gainratios[gainidx]*_addPedestalUncertainty*_addPedestalUncertainty*pedestal.asDiagonal()*SampleMatrix::Ones()*pedestal.asDiagonal();
159  }
160  }
161  }
162  }
163  }
164  else {
165  noisecov = aped->rms_x12*aped->rms_x12*noisecors[0];
166  if (!dynamicPedestal && _addPedestalUncertainty>0.) {
167  //add fully correlated component to noise covariance to inflate pedestal uncertainty
168  noisecov += _addPedestalUncertainty*_addPedestalUncertainty*SampleMatrix::Ones();
169  }
170  }
171 
172  //optimized one-pulse fit for hlt
173  bool usePrefit = false;
174  if (_doPrefit) {
175  status = _pulsefuncSingle.DoFit(amplitudes,noisecov,_singlebx,fullpulse,fullpulsecov,gainsPedestal,badSamples);
176  amplitude = status ? _pulsefuncSingle.X()[0] : 0.;
177  amperr = status ? _pulsefuncSingle.Errors()[0] : 0.;
178  chisq = _pulsefuncSingle.ChiSq();
179 
180  if (chisq < _prefitMaxChiSq) {
181  usePrefit = true;
182  }
183  }
184 
185  if (!usePrefit) {
186 
188  status = _pulsefunc.DoFit(amplitudes,noisecov,activeBX,fullpulse,fullpulsecov,gainsPedestal,badSamples);
189  chisq = _pulsefunc.ChiSq();
190 
191  if (!status) {
192  edm::LogWarning("EcalUncalibRecHitMultiFitAlgo::makeRecHit") << "Failed Fit" << std::endl;
193  }
194 
195  unsigned int ipulseintime = 0;
196  for (unsigned int ipulse=0; ipulse<_pulsefunc.BXs().rows(); ++ipulse) {
197  if (_pulsefunc.BXs().coeff(ipulse)==0) {
198  ipulseintime = ipulse;
199  break;
200  }
201  }
202 
203  amplitude = status ? _pulsefunc.X()[ipulseintime] : 0.;
204  amperr = status ? _pulsefunc.Errors()[ipulseintime] : 0.;
205 
206  }
207 
208  double jitter = 0.;
209 
210  EcalUncalibratedRecHit rh( dataFrame.id(), amplitude , pedval, jitter, chisq, flags );
211  rh.setAmplitudeError(amperr);
212 
213  if (!usePrefit) {
214  for (unsigned int ipulse=0; ipulse<_pulsefunc.BXs().rows(); ++ipulse) {
215  int bx = _pulsefunc.BXs().coeff(ipulse);
216  if (bx!=0 && std::abs(bx)<100) {
217  rh.setOutOfTimeAmplitude(bx+5, status ? _pulsefunc.X().coeff(ipulse) : 0.);
218  }
219  else if (bx==(100+gainsPedestal[iSampleMax])) {
220  rh.setPedestal(status ? _pulsefunc.X().coeff(ipulse) : 0.);
221  }
222  }
223  }
224 
225  return rh;
226 }
227 
void setMaxIterWarnings(bool b)
bool hasSwitchToGain1() const
DetId id() const
Definition: EcalDataFrame.h:24
void setMaxIters(int n)
std::array< SampleMatrix, NGains > SampleMatrixGainArray
bool hasSwitchToGain6() const
void disableErrorCalculation()
bool isSaturated() const
Definition: EcalDataFrame.h:38
const PulseVector & Errors() const
EcalMGPASample sample(int i) const
Definition: EcalDataFrame.h:29
std::vector< Variable::Flags > flags
Definition: MVATrainer.cc:135
bool DoFit(const SampleVector &samples, const SampleMatrix &samplecov, const BXVector &bxs, const FullSampleVector &fullpulse, const FullSampleMatrix &fullpulsecov, const SampleGainVector &gains=-1 *SampleGainVector::Ones(), const SampleGainVector &badSamples=SampleGainVector::Zero())
int gainId() const
get the gainId (2 bits)
const PulseVector & X() const
Eigen::Matrix< char, SampleVectorSize, 1 > SampleGainVector
Eigen::Matrix< double, FullSampleVectorSize, 1 > FullSampleVector
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
float gain6Over1() const
void setAmplitudeError(float amplitudeerror)
EcalUncalibratedRecHit makeRecHit(const EcalDataFrame &dataFrame, const EcalPedestals::Item *aped, const EcalMGPAGainRatio *aGain, const SampleMatrixGainArray &noisecors, const FullSampleVector &fullpulse, const FullSampleMatrix &fullpulsecov, const BXVector &activeBX)
compute rechits
Eigen::Matrix< double, SampleVectorSize, 1 > SampleVector
double ChiSq() const
Eigen::Matrix< double, FullSampleVectorSize, FullSampleVectorSize > FullSampleMatrix
void resize(int bx, unsigned size)
Eigen::Matrix< double, SampleVectorSize, SampleVectorSize > SampleMatrix
float gain12Over6() const
constexpr int gainId(sample_type sample)
get the gainId (2 bits)
const BXVector & BXs() const
static constexpr int MAXSAMPLES
Definition: EcalDataFrame.h:48
int adc() const
get the ADC sample (12 bits)