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  double maxgainratio = -std::numeric_limits<double>::max();
37  unsigned int iSampleMax = 0;
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 (gainratio > maxgainratio || gainId==0 || amplitude>maxamplitude) {
101  //if (iSample==5) {
102  maxamplitude = amplitude;
103  maxgainratio = gainratio;
104  iSampleMax = iSample;
105  pedval = pedestal;
106  }
107 
108  }
109 
110  double amplitude, amperr, chisq;
111  bool status = false;
112 
113  //special handling for gain switch, where sample before maximum is potentially affected by slew rate limitation
114  //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
115  //option 1: use simple max-sample algorithm
116  if (hasGainSwitch && _gainSwitchUseMaxSample) {
117  EcalUncalibratedRecHit rh( dataFrame.id(), maxamplitude, pedval, 0., 0., flags );
118  rh.setAmplitudeError(0.);
119  for (unsigned int ipulse=0; ipulse<_pulsefunc.BXs().rows(); ++ipulse) {
120  int bx = _pulsefunc.BXs().coeff(ipulse);
121  if (bx!=0) {
122  rh.setOutOfTimeAmplitude(bx+5, 0.0);
123  }
124  }
125  return rh;
126  }
127 
128  //option2: A floating negative single-sample offset is added to the fit
129  //such that the affected sample is treated only as a lower limit for the true amplitude
130  bool mitigateBadSample = _mitigateBadSamples && hasGainSwitch && iSampleMax>0;
131  mitigateBadSample &= (!_selectiveBadSampleCriteria || (gainsNoise.coeff(iSampleMax-1)!=gainsNoise.coeff(iSampleMax)) );
132  if (mitigateBadSample) {
133  badSamples[iSampleMax-1] = 1;
134  }
135 
136  //compute noise covariance matrix, which depends on the sample gains
137  SampleMatrix noisecov;
138  if (hasGainSwitch) {
139  std::array<double,3> pedrmss = {{aped->rms_x12, aped->rms_x6, aped->rms_x1}};
140  std::array<double,3> gainratios = {{ 1., aGain->gain12Over6(), aGain->gain6Over1()*aGain->gain12Over6()}};
142  int gainidxmax = gainsNoise[iSampleMax];
143  noisecov = gainratios[gainidxmax]*gainratios[gainidxmax]*pedrmss[gainidxmax]*pedrmss[gainidxmax]*noisecors[gainidxmax];
144  if (!dynamicPedestal && _addPedestalUncertainty>0.) {
145  //add fully correlated component to noise covariance to inflate pedestal uncertainty
146  noisecov += _addPedestalUncertainty*_addPedestalUncertainty*SampleMatrix::Ones();
147  }
148  }
149  else {
150  noisecov = SampleMatrix::Zero();
151  for (unsigned int gainidx=0; gainidx<noisecors.size(); ++gainidx) {
152  SampleGainVector mask = gainidx*SampleGainVector::Ones();
153  SampleVector pedestal = (gainsNoise.array()==mask.array()).cast<SampleVector::value_type>();
154  if (pedestal.maxCoeff()>0.) {
155  //select out relevant components of each correlation matrix, and assume no correlation between samples with
156  //different gain
157  noisecov += gainratios[gainidx]*gainratios[gainidx]*pedrmss[gainidx]*pedrmss[gainidx]*pedestal.asDiagonal()*noisecors[gainidx]*pedestal.asDiagonal();
158  if (!dynamicPedestal && _addPedestalUncertainty>0.) {
159  //add fully correlated component to noise covariance to inflate pedestal uncertainty
160  noisecov += gainratios[gainidx]*gainratios[gainidx]*_addPedestalUncertainty*_addPedestalUncertainty*pedestal.asDiagonal()*SampleMatrix::Ones()*pedestal.asDiagonal();
161  }
162  }
163  }
164  }
165  }
166  else {
167  noisecov = aped->rms_x12*aped->rms_x12*noisecors[0];
168  if (!dynamicPedestal && _addPedestalUncertainty>0.) {
169  //add fully correlated component to noise covariance to inflate pedestal uncertainty
170  noisecov += _addPedestalUncertainty*_addPedestalUncertainty*SampleMatrix::Ones();
171  }
172  }
173 
174  //optimized one-pulse fit for hlt
175  bool usePrefit = false;
176  if (_doPrefit) {
177  status = _pulsefuncSingle.DoFit(amplitudes,noisecov,_singlebx,fullpulse,fullpulsecov,gainsPedestal,badSamples);
178  amplitude = status ? _pulsefuncSingle.X()[0] : 0.;
179  amperr = status ? _pulsefuncSingle.Errors()[0] : 0.;
180  chisq = _pulsefuncSingle.ChiSq();
181 
182  if (chisq < _prefitMaxChiSq) {
183  usePrefit = true;
184  }
185  }
186 
187  if (!usePrefit) {
188 
190  status = _pulsefunc.DoFit(amplitudes,noisecov,activeBX,fullpulse,fullpulsecov,gainsPedestal,badSamples);
191  chisq = _pulsefunc.ChiSq();
192 
193  if (!status) {
194  edm::LogWarning("EcalUncalibRecHitMultiFitAlgo::makeRecHit") << "Failed Fit" << std::endl;
195  }
196 
197  unsigned int ipulseintime = 0;
198  for (unsigned int ipulse=0; ipulse<_pulsefunc.BXs().rows(); ++ipulse) {
199  if (_pulsefunc.BXs().coeff(ipulse)==0) {
200  ipulseintime = ipulse;
201  break;
202  }
203  }
204 
205  amplitude = status ? _pulsefunc.X()[ipulseintime] : 0.;
206  amperr = status ? _pulsefunc.Errors()[ipulseintime] : 0.;
207 
208  }
209 
210  double jitter = 0.;
211 
212  EcalUncalibratedRecHit rh( dataFrame.id(), amplitude , pedval, jitter, chisq, flags );
213  rh.setAmplitudeError(amperr);
214 
215  if (!usePrefit) {
216  for (unsigned int ipulse=0; ipulse<_pulsefunc.BXs().rows(); ++ipulse) {
217  int bx = _pulsefunc.BXs().coeff(ipulse);
218  if (bx!=0 && std::abs(bx)<100) {
219  rh.setOutOfTimeAmplitude(bx+5, status ? _pulsefunc.X().coeff(ipulse) : 0.);
220  }
221  else if (bx==(100+gainsPedestal[iSampleMax])) {
222  rh.setPedestal(status ? _pulsefunc.X().coeff(ipulse) : 0.);
223  }
224  }
225  }
226 
227  return rh;
228 }
229 
void setMaxIterWarnings(bool b)
bool hasSwitchToGain1() const
DetId id() const
Definition: EcalDataFrame.h:24
void setMaxIters(int n)
Eigen::Matrix< char, SampleVectorSize, 1 > SampleGainVector
int gainId(sample_type sample)
get the gainId (2 bits)
bool hasSwitchToGain6() const
void disableErrorCalculation()
bool isSaturated() const
Definition: EcalDataFrame.h:38
Eigen::Matrix< double, SampleVectorSize, 1 > SampleVector
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)
Eigen::Matrix< double, SampleVectorSize, SampleVectorSize > SampleMatrix
const PulseVector & X() const
std::array< SampleMatrix, NGains > SampleMatrixGainArray
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
double ChiSq() const
void resize(int bx, unsigned size)
float gain12Over6() const
const BXVector & BXs() const
Eigen::Matrix< double, FullSampleVectorSize, 1 > FullSampleVector
Eigen::Matrix< double, FullSampleVectorSize, FullSampleVectorSize > FullSampleMatrix
static const int MAXSAMPLES
Definition: EcalDataFrame.h:48
int adc() const
get the ADC sample (12 bits)