CMS 3D CMS Logo

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