CMS 3D CMS Logo

ZdcSimpleRecAlgo.cc
Go to the documentation of this file.
4 #include <algorithm> // for "max"
5 #include <iostream>
6 #include <cmath>
7 
8 constexpr double MaximumFractionalError = 0.0005; // 0.05% error allowed from this source
9 
11  bool correctForTimeslew, bool correctForPulse, float phaseNS, int recoMethod, int lowGainOffset, double lowGainFrac)
12  : recoMethod_(recoMethod),
13  correctForTimeslew_(correctForTimeslew),
14  correctForPulse_(correctForPulse),
15  phaseNS_(phaseNS),
16  lowGainOffset_(lowGainOffset),
17  lowGainFrac_(lowGainFrac) {}
18 
19 ZdcSimpleRecAlgo::ZdcSimpleRecAlgo(int recoMethod) : recoMethod_(recoMethod), correctForTimeslew_(false) {}
20 
21 void ZdcSimpleRecAlgo::initPulseCorr(int toadd, const HcalTimeSlew* hcalTimeSlew_delay) {
22  if (correctForPulse_) {
23  pulseCorr_ = std::make_unique<HcalPulseContainmentCorrection>(
24  toadd, phaseNS_, false, MaximumFractionalError, hcalTimeSlew_delay);
25  }
26 }
27 //static float timeshift_ns_zdc(float wpksamp);
28 
30  template <class Digi, class RecHit>
31  inline RecHit reco1(const Digi& digi,
32  const HcalCoder& coder,
33  const HcalCalibrations& calibs,
34  const std::vector<unsigned int>& myNoiseTS,
35  const std::vector<unsigned int>& mySignalTS,
36  int lowGainOffset,
37  double lowGainFrac,
38  bool slewCorrect,
40  HcalTimeSlew::BiasSetting slewFlavor) {
41  CaloSamples tool;
42  coder.adc2fC(digi, tool);
43  int ifirst = mySignalTS[0];
44  int n = mySignalTS.size();
45  double ampl = 0;
46  int maxI = -1;
47  double maxA = -1e10;
48  double ta = 0;
49  double fc_ampl = 0;
50  double lowGEnergy = 0;
51  double TempLGAmp = 0;
52  // TS increment for regular energy to lowGainEnergy
53  // Signal in higher TS (effective "low Gain") has a fraction of the whole signal
54  // This constant for fC --> GeV is dervied from 2010 PbPb analysis of single neutrons
55  // assumed similar fraction for EM and HAD sections
56  // this variable converts from current assumed TestBeam values for fC--> GeV
57  // to the lowGain TS region fraction value (based on 1N Had, assume EM same response)
58  // regular energy
59  for (int i = ifirst; i < tool.size() && i < n + ifirst; i++) {
60  int capid = digi[i].capid();
61  ta = (tool[i] - calibs.pedestal(capid)); // pedestal subtraction
62  fc_ampl += ta;
63  ta *= calibs.respcorrgain(capid); // fC --> GeV
64  ampl += ta;
65  if (ta > maxA) {
66  maxA = ta;
67  maxI = i;
68  }
69  }
70  // calculate low Gain Energy (in 2010 PbPb, signal TS 4,5,6, lowGain TS: 6,7,8)
71  int topLowGain = 10;
72  if ((n + ifirst + lowGainOffset) <= 10) {
73  topLowGain = n + ifirst + lowGainOffset;
74  } else {
75  topLowGain = 10;
76  }
77  for (int iLG = (ifirst + lowGainOffset); iLG < tool.size() && iLG < topLowGain; iLG++) {
78  int capid = digi[iLG].capid();
79  TempLGAmp = (tool[iLG] - calibs.pedestal(capid)); // pedestal subtraction
80  TempLGAmp *= calibs.respcorrgain(capid); // fC --> GeV
81  TempLGAmp *= lowGainFrac; // TS (signalRegion) --> TS (lowGainRegion)
82  lowGEnergy += TempLGAmp;
83  }
84  double time = -9999;
85  // Time based on regular energy (lowGainEnergy signal assumed to happen at same Time)
87  if (maxI == 0 || maxI == (tool.size() - 1)) {
88  LogDebug("HCAL Pulse") << "ZdcSimpleRecAlgo::reco1 :"
89  << " Invalid max amplitude position, "
90  << " max Amplitude: " << maxI << " first: " << ifirst << " last: " << (tool.size() - 1)
91  << std::endl;
92  } else {
93  int capid = digi[maxI - 1].capid();
94  double Energy0 = ((tool[maxI - 1]) * calibs.respcorrgain(capid));
95  // if any of the energies used in the weight are negative, make them 0 instead
96  // these are actually QIE values, not energy
97  if (Energy0 < 0) {
98  Energy0 = 0.;
99  }
100  capid = digi[maxI].capid();
101  double Energy1 = ((tool[maxI]) * calibs.respcorrgain(capid));
102  if (Energy1 < 0) {
103  Energy1 = 0.;
104  }
105  capid = digi[maxI + 1].capid();
106  double Energy2 = ((tool[maxI + 1]) * calibs.respcorrgain(capid));
107  if (Energy2 < 0) {
108  Energy2 = 0.;
109  }
110  //
111  double TSWeightEnergy = ((maxI - 1) * Energy0 + maxI * Energy1 + (maxI + 1) * Energy2);
112  double EnergySum = Energy0 + Energy1 + Energy2;
113  double AvgTSPos = 0.;
114  if (EnergySum != 0)
115  AvgTSPos = TSWeightEnergy / EnergySum;
116  // If time is zero, set it to the "nonsensical" -99
117  // Time should be between 75ns and 175ns (Timeslices 3-7)
118  if (AvgTSPos == 0) {
119  time = -99;
120  } else {
121  time = (AvgTSPos * 25.0);
122  }
123  if (corr != nullptr) {
124  // Apply phase-based amplitude correction:
125  ampl *= corr->getCorrection(fc_ampl);
126  }
127  }
128  return RecHit(digi.id(), ampl, time, lowGEnergy);
129  }
130 } // namespace ZdcSimpleRecAlgoImpl
131 
132 namespace ZdcSimpleRecAlgoImpl {
133  template <class Digi, class RecHit>
134  inline RecHit reco2(const Digi& digi,
135  const HcalCoder& coder,
136  const HcalCalibrations& calibs,
137  const std::vector<unsigned int>& myNoiseTS,
138  const std::vector<unsigned int>& mySignalTS,
139  int lowGainOffset,
140  double lowGainFrac,
141  bool slewCorrect,
143  HcalTimeSlew::BiasSetting slewFlavor) {
144  CaloSamples tool;
145  coder.adc2fC(digi, tool);
146  // Reads noiseTS and signalTS from database
147  int ifirst = mySignalTS[0];
148  // int n = mySignalTS.size();
149  double ampl = 0;
150  int maxI = -1;
151  double maxA = -1e10;
152  double ta = 0;
153  double fc_ampl = 0;
154  double lowGEnergy = 0;
155  double TempLGAmp = 0;
156  // TS increment for regular energy to lowGainEnergy
157  // Signal in higher TS (effective "low Gain") has a fraction of the whole signal
158  // This constant for fC --> GeV is dervied from 2010 PbPb analysis of single neutrons
159  // assumed similar fraction for EM and HAD sections
160  // this variable converts from current assumed TestBeam values for fC--> GeV
161  // to the lowGain TS region fraction value (based on 1N Had, assume EM same response)
162  double Allnoise = 0;
163  int noiseslices = 0;
164  int CurrentTS = 0;
165  double noise = 0;
166  // regular energy (both use same noise)
167  for (unsigned int iv = 0; iv < myNoiseTS.size(); ++iv) {
168  CurrentTS = myNoiseTS[iv];
169  if (CurrentTS >= digi.size())
170  continue;
171  Allnoise += tool[CurrentTS];
172  noiseslices++;
173  }
174  if (noiseslices != 0) {
175  noise = (Allnoise) / double(noiseslices);
176  } else {
177  noise = 0;
178  }
179  for (unsigned int ivs = 0; ivs < mySignalTS.size(); ++ivs) {
180  CurrentTS = mySignalTS[ivs];
181  if (CurrentTS >= digi.size())
182  continue;
183  int capid = digi[CurrentTS].capid();
184  // if(noise<0){
185  // // flag hit as having negative noise, and don't subtract anything, because
186  // // it will falsely increase the energy
187  // noisefactor=0.;
188  // }
189  ta = tool[CurrentTS] - noise;
190  fc_ampl += ta;
191  ta *= calibs.respcorrgain(capid); // fC --> GeV
192  ampl += ta;
193  if (ta > maxA) {
194  maxA = ta;
195  maxI = CurrentTS;
196  }
197  }
198  // calculate low Gain Energy (in 2010 PbPb, signal TS 4,5,6, lowGain TS: 6,7,8)
199  for (unsigned int iLGvs = 0; iLGvs < mySignalTS.size(); ++iLGvs) {
200  CurrentTS = mySignalTS[iLGvs] + lowGainOffset;
201  if (CurrentTS >= digi.size())
202  continue;
203  int capid = digi[CurrentTS].capid();
204  TempLGAmp = tool[CurrentTS] - noise;
205  TempLGAmp *= calibs.respcorrgain(capid); // fC --> GeV
206  TempLGAmp *= lowGainFrac; // TS (signalRegion) --> TS (lowGainRegion)
207  lowGEnergy += TempLGAmp;
208  }
209  // if(ta<0){
210  // // flag hits that have negative energy
211  // }
212 
213  double time = -9999;
214  // Time based on regular energy (lowGainEnergy signal assumed to happen at same Time)
216  if (maxI == 0 || maxI == (tool.size() - 1)) {
217  LogDebug("HCAL Pulse") << "ZdcSimpleRecAlgo::reco2 :"
218  << " Invalid max amplitude position, "
219  << " max Amplitude: " << maxI << " first: " << ifirst << " last: " << (tool.size() - 1)
220  << std::endl;
221  } else {
222  int capid = digi[maxI - 1].capid();
223  double Energy0 = ((tool[maxI - 1]) * calibs.respcorrgain(capid));
224  // if any of the energies used in the weight are negative, make them 0 instead
225  // these are actually QIE values, not energy
226  if (Energy0 < 0) {
227  Energy0 = 0.;
228  }
229  capid = digi[maxI].capid();
230  double Energy1 = ((tool[maxI]) * calibs.respcorrgain(capid));
231  if (Energy1 < 0) {
232  Energy1 = 0.;
233  }
234  capid = digi[maxI + 1].capid();
235  double Energy2 = ((tool[maxI + 1]) * calibs.respcorrgain(capid));
236  if (Energy2 < 0) {
237  Energy2 = 0.;
238  }
239  //
240  double TSWeightEnergy = ((maxI - 1) * Energy0 + maxI * Energy1 + (maxI + 1) * Energy2);
241  double EnergySum = Energy0 + Energy1 + Energy2;
242  double AvgTSPos = 0.;
243  if (EnergySum != 0)
244  AvgTSPos = TSWeightEnergy / EnergySum;
245  // If time is zero, set it to the "nonsensical" -99
246  // Time should be between 75ns and 175ns (Timeslices 3-7)
247  if (AvgTSPos == 0) {
248  time = -99;
249  } else {
250  time = (AvgTSPos * 25.0);
251  }
252  if (corr != nullptr) {
253  // Apply phase-based amplitude correction:
254  ampl *= corr->getCorrection(fc_ampl);
255  }
256  }
257  return RecHit(digi.id(), ampl, time, lowGEnergy);
258  }
259 } // namespace ZdcSimpleRecAlgoImpl
260 
262  const std::vector<unsigned int>& myNoiseTS,
263  const std::vector<unsigned int>& mySignalTS,
264  const HcalCoder& coder,
265  const HcalCalibrations& calibs) const {
266  if (recoMethod_ == 1)
267  return ZdcSimpleRecAlgoImpl::reco1<ZDCDataFrame, ZDCRecHit>(
268  digi, coder, calibs, myNoiseTS, mySignalTS, lowGainOffset_, lowGainFrac_, false, nullptr, HcalTimeSlew::Fast);
269  if (recoMethod_ == 2)
270  return ZdcSimpleRecAlgoImpl::reco2<ZDCDataFrame, ZDCRecHit>(
271  digi, coder, calibs, myNoiseTS, mySignalTS, lowGainOffset_, lowGainFrac_, false, nullptr, HcalTimeSlew::Fast);
272 
273  edm::LogError("ZDCSimpleRecAlgoImpl::reconstruct, recoMethod was not declared");
274  throw cms::Exception("ZDCSimpleRecoAlgos::exiting process");
275 }
RecHit reco1(const Digi &digi, const HcalCoder &coder, const HcalCalibrations &calibs, const std::vector< unsigned int > &myNoiseTS, const std::vector< unsigned int > &mySignalTS, int lowGainOffset, double lowGainFrac, bool slewCorrect, const HcalPulseContainmentCorrection *corr, HcalTimeSlew::BiasSetting slewFlavor)
int size() const
get the size
Definition: CaloSamples.h:24
int32_t *__restrict__ iv
void initPulseCorr(int toadd, const HcalTimeSlew *hcalTimeSlew_delay)
Log< level::Error, false > LogError
constexpr double pedestal(int fCapId) const
get pedestal for capid=0..3
dictionary corr
ZdcSimpleRecAlgo(bool correctForTimeslew, bool correctForContainment, float fixedPhaseNs, int recoMethod, int lowGainOffset, double lowGainFrac)
ZDCRecHit reconstruct(const ZDCDataFrame &digi, const std::vector< unsigned int > &myNoiseTS, const std::vector< unsigned int > &mySignalTS, const HcalCoder &coder, const HcalCalibrations &calibs) const
constexpr double respcorrgain(int fCapId) const
get response corrected gain for capid=0..3
std::unique_ptr< HcalPulseContainmentCorrection > pulseCorr_
virtual void adc2fC(const HBHEDataFrame &df, CaloSamples &lf) const =0
RecHit reco2(const Digi &digi, const HcalCoder &coder, const HcalCalibrations &calibs, const std::vector< unsigned int > &myNoiseTS, const std::vector< unsigned int > &mySignalTS, int lowGainOffset, double lowGainFrac, bool slewCorrect, const HcalPulseContainmentCorrection *corr, HcalTimeSlew::BiasSetting slewFlavor)
constexpr double MaximumFractionalError
#define LogDebug(id)