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  _singlebx.resize(1);
19  _singlebx << 0;
20 
24 }
25 
28  const EcalPedestals::Item *aped,
29  const EcalMGPAGainRatio *aGain,
30  const SampleMatrixGainArray &noisecors,
31  const FullSampleVector &fullpulse,
32  const FullSampleMatrix &fullpulsecov,
33  const BXVector &activeBX) {
34  uint32_t flags = 0;
35 
36  const unsigned int nsample = EcalDataFrame::MAXSAMPLES;
37 
38  double maxamplitude = -std::numeric_limits<double>::max();
39  const unsigned int iSampleMax = 5;
40  const unsigned int iFullPulseMax = 9;
41 
42  double pedval = 0.;
43 
44  SampleVector amplitudes;
45  SampleGainVector gainsNoise;
46  SampleGainVector gainsPedestal;
47  SampleGainVector badSamples = SampleGainVector::Zero();
48  bool hasSaturation = dataFrame.isSaturated();
49  bool hasGainSwitch = hasSaturation || dataFrame.hasSwitchToGain6() || dataFrame.hasSwitchToGain1();
50 
51  //no dynamic pedestal in case of gain switch, since then the fit becomes too underconstrained
52  bool dynamicPedestal = _dynamicPedestals && !hasGainSwitch;
53 
54  for (unsigned int iSample = 0; iSample < nsample; iSample++) {
55  const EcalMGPASample &sample = dataFrame.sample(iSample);
56 
57  double amplitude = 0.;
58  int gainId = sample.gainId();
59 
60  double pedestal = 0.;
61  double gainratio = 1.;
62 
63  if (gainId == 0 || gainId == 3) {
64  pedestal = aped->mean_x1;
65  gainratio = aGain->gain6Over1() * aGain->gain12Over6();
66  gainsNoise[iSample] = 2;
67  gainsPedestal[iSample] = dynamicPedestal ? 2 : -1; //-1 for static pedestal
68  } else if (gainId == 1) {
69  pedestal = aped->mean_x12;
70  gainratio = 1.;
71  gainsNoise[iSample] = 0;
72  gainsPedestal[iSample] = dynamicPedestal ? 0 : -1; //-1 for static pedestal
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  } else {
83  amplitude = ((double)(sample.adc()) - pedestal) * gainratio;
84  }
85 
86  if (gainId == 0) {
87  edm::LogError("EcalUncalibRecHitMultiFitAlgo")
88  << "Saturation encountered. Multifit is not intended to be used for saturated channels.";
89  //saturation
90  if (dynamicPedestal) {
91  amplitude = 4095. * gainratio;
92  } else {
93  amplitude = (4095. - pedestal) * gainratio;
94  }
95  }
96 
97  amplitudes[iSample] = amplitude;
98 
99  if (iSample == iSampleMax) {
100  maxamplitude = amplitude;
101  pedval = pedestal;
102  }
103  }
104 
105  double amplitude, amperr, chisq;
106  bool status = false;
107 
108  //special handling for gain switch, where sample before maximum is potentially affected by slew rate limitation
109  //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
110  //option 1: use simple max-sample algorithm
111  if (hasGainSwitch && _gainSwitchUseMaxSample) {
112  double maxpulseamplitude = maxamplitude / fullpulse[iFullPulseMax];
113  EcalUncalibratedRecHit rh(dataFrame.id(), maxpulseamplitude, pedval, 0., 0., flags);
114  rh.setAmplitudeError(0.);
115  for (unsigned int ipulse = 0; ipulse < _pulsefunc.BXs().rows(); ++ipulse) {
116  int bx = _pulsefunc.BXs().coeff(ipulse);
117  if (bx != 0) {
118  rh.setOutOfTimeAmplitude(bx + 5, 0.0);
119  }
120  }
121  return rh;
122  }
123 
124  //option2: A floating negative single-sample offset is added to the fit
125  //such that the affected sample is treated only as a lower limit for the true amplitude
126  bool mitigateBadSample = _mitigateBadSamples && hasGainSwitch && iSampleMax > 0;
127  mitigateBadSample &=
128  (!_selectiveBadSampleCriteria || (gainsNoise.coeff(iSampleMax - 1) != gainsNoise.coeff(iSampleMax)));
129  if (mitigateBadSample) {
130  badSamples[iSampleMax - 1] = 1;
131  }
132 
133  //compute noise covariance matrix, which depends on the sample gains
134  SampleMatrix noisecov;
135  if (hasGainSwitch) {
136  std::array<double, 3> pedrmss = {{aped->rms_x12, aped->rms_x6, aped->rms_x1}};
137  std::array<double, 3> gainratios = {{1., aGain->gain12Over6(), aGain->gain6Over1() * aGain->gain12Over6()}};
139  int gainidxmax = gainsNoise[iSampleMax];
140  noisecov = gainratios[gainidxmax] * gainratios[gainidxmax] * pedrmss[gainidxmax] * pedrmss[gainidxmax] *
141  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  } else {
147  noisecov = SampleMatrix::Zero();
148  for (unsigned int gainidx = 0; gainidx < noisecors.size(); ++gainidx) {
149  SampleGainVector mask = gainidx * SampleGainVector::Ones();
150  SampleVector pedestal = (gainsNoise.array() == mask.array()).cast<SampleVector::value_type>();
151  if (pedestal.maxCoeff() > 0.) {
152  //select out relevant components of each correlation matrix, and assume no correlation between samples with
153  //different gain
154  noisecov += gainratios[gainidx] * gainratios[gainidx] * pedrmss[gainidx] * pedrmss[gainidx] *
155  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 *
159  pedestal.asDiagonal() * SampleMatrix::Ones() * pedestal.asDiagonal();
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 =
176  _pulsefuncSingle.DoFit(amplitudes, noisecov, _singlebx, fullpulse, fullpulsecov, gainsPedestal, badSamples);
177  amplitude = status ? _pulsefuncSingle.X()[0] : 0.;
178  amperr = status ? _pulsefuncSingle.Errors()[0] : 0.;
179  chisq = _pulsefuncSingle.ChiSq();
180 
181  if (chisq < _prefitMaxChiSq) {
182  usePrefit = true;
183  }
184  }
185 
186  if (!usePrefit) {
187  if (!_computeErrors)
189  status = _pulsefunc.DoFit(amplitudes, noisecov, activeBX, fullpulse, fullpulsecov, gainsPedestal, badSamples);
190  chisq = _pulsefunc.ChiSq();
191 
192  if (!status) {
193  edm::LogWarning("EcalUncalibRecHitMultiFitAlgo::makeRecHit") << "Failed Fit" << std::endl;
194  }
195 
196  unsigned int ipulseintime = 0;
197  for (unsigned int ipulse = 0; ipulse < _pulsefunc.BXs().rows(); ++ipulse) {
198  if (_pulsefunc.BXs().coeff(ipulse) == 0) {
199  ipulseintime = ipulse;
200  break;
201  }
202  }
203 
204  amplitude = status ? _pulsefunc.X()[ipulseintime] : 0.;
205  amperr = status ? _pulsefunc.Errors()[ipulseintime] : 0.;
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  } else if (bx == (100 + gainsPedestal[iSampleMax])) {
219  rh.setPedestal(status ? _pulsefunc.X().coeff(ipulse) : 0.);
220  }
221  }
222  }
223 
224  return rh;
225 }
void setMaxIterWarnings(bool b)
void setMaxIters(int n)
std::array< SampleMatrix, NGains > SampleMatrixGainArray
bool isSaturated() const
Definition: EcalDataFrame.h:38
Eigen::Matrix< double, FullSampleVectorSize, FullSampleVectorSize > FullSampleMatrix
bool hasSwitchToGain1() const
void disableErrorCalculation()
Eigen::Matrix< double, FullSampleVectorSize, 1 > FullSampleVector
bool hasSwitchToGain6() const
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())
Log< level::Error, false > LogError
const BXVector & BXs() const
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
EcalMGPASample sample(int i) const
Definition: EcalDataFrame.h:29
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
float gain12Over6() const
constexpr int gainId(sample_type sample)
get the gainId (2 bits)
void resize(int bx, unsigned size)
Eigen::Matrix< double, SampleVectorSize, 1 > SampleVector
float gain6Over1() const
Eigen::Matrix< double, SampleVectorSize, SampleVectorSize > SampleMatrix
const PulseVector & Errors() const
Eigen::Matrix< char, SampleVectorSize, 1 > SampleGainVector
DetId id() const
Definition: EcalDataFrame.h:24
double ChiSq() const
static constexpr int MAXSAMPLES
Definition: EcalDataFrame.h:48
Log< level::Warning, false > LogWarning
const PulseVector & X() const