CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
HPDNoiseLibraryReader.cc
Go to the documentation of this file.
1 
2 // --------------------------------------------------------
3 // A class to read HPD noise from the library.
4 // The deliverable of the class is the collection of
5 // noisy HcalDetIds with associated noise in units of fC for
6 // 10 time samples. During the library production a higher
7 // theshold is used to find a noisy HPD. A lower threshold is
8 // used to eliminate adding unnecessary quite channels to HPD
9 // noise event collection. Therefore user may not see whole 18
10 // channels for noisy HPD.
11 //
12 // Project: HPD noise library reader
13 // Author: T.Yetkin University of Iowa, Feb. 7, 2008
14 // --------------------------------------------------------
15 
18 
19 #include "CLHEP/Random/RandFlat.h"
20 #include "CLHEP/Random/RandGaussQ.h"
21 
22 using namespace edm;
23 using namespace std;
24 
26 :theDischargeNoiseRate(0),
27 theIonFeedbackFirstPeakRate(0),
28 theIonFeedbackSecondPeakRate(0),
29 theNoisyPhi(0) {
30 
31  ParameterSet pSet = iConfig.getParameter < edm::ParameterSet > ("HPDNoiseLibrary");
32  FileInPath filepath = pSet.getParameter < edm::FileInPath > ("FileName");
33 
34  theHPDName = pSet.getUntrackedParameter < string > ("HPDName", "HPD");
35  string pName = filepath.fullPath();
36 
37  if (pName.find(".") == 0)
38  pName.erase(0, 2);
39  theReader = new HPDNoiseReader(pName);
40  theNames = theReader->allNames(); // all 72x2 HPDs
41 
42  fillRates();
43 }
44 
46 }
47 
49  for (size_t i = 0; i < theNames.size(); ++i) {
51  if (theReader->valid(hpdObj)) {
52  theDischargeNoiseRate.push_back(theReader->dischargeRate(hpdObj));
55  } else {
56  std::cerr << "HPD Handle Object is not valid!" << endl;
57  }
58  }
59 }
60 
61 HPDNoiseData *HPDNoiseLibraryReader::getNoiseData(int iphi, CLHEP::HepRandomEngine* engine) {
62 
63 
64  HPDNoiseData *data = 0; //data->size() is checked wherever actually used
65 
66  // make sure that iphi from HcalDetId is found noisy at first.
67  // In other words, be sure that iphi is in the collection of
68  // noisy Phis
69  if (!(IsNoiseApplicable(iphi)))
70  return data;
71 
72  int zside = 1;
73 
74  if (iphi > 72) {
75  iphi = iphi - 72;
76  zside = -1;
77  }
79  if (zside == 1) {
80  name = "ZPlus" + theHPDName + itos(iphi);
81  } else if (zside == -1) {
82  name = "ZMinus" + theHPDName + itos(iphi);
83  } else {
84  cerr << " ZSide Calculation Error." << endl;
85  }
87  if (theReader->valid(hpdObj)) {
88  // randomly select one entry from library for this HPD
89  unsigned long entry = CLHEP::RandFlat::shootInt(engine, theReader->totalEntries(hpdObj));
90 
91  theReader->getEntry(hpdObj, entry, &data);
92  } else {
93  std::cerr << " HPD Name in the library is not valid." << std::endl;
94  }
95  return data;
96 }
97 
98 
99 void HPDNoiseLibraryReader::getNoisyPhis(CLHEP::HepRandomEngine* engine) {
100 
101  clearPhi();
102  double rndm[144];
103 
104  CLHEP::RandFlat::shootArray(engine, 144, rndm);
105 
106  for (int i = 0; i < 144; ++i) {
107  if (rndm[i] < theDischargeNoiseRate[i]) {
108  theNoisyPhi.push_back(i + 1);
109  }
110  }
111 }
112 
113 void HPDNoiseLibraryReader::getBiasedNoisyPhis(CLHEP::HepRandomEngine* engine) {
114 
115  clearPhi();
116  double rndm[144];
117 
118  CLHEP::RandFlat::shootArray(engine, 144, rndm);
119  for (int i = 0; i < 144; ++i) {
120  if (rndm[i] < theDischargeNoiseRate[i]) {
121  theNoisyPhi.push_back(i + 1);
122  }
123  }
124  // make sure one HPD is always noisy
125  if (theNoisyPhi.size() == 0) {
126  int iPhi = (CLHEP::RandFlat::shootInt(engine, 144)) + 1; // integer from interval [0-144[ + 1
127 
128  theNoisyPhi.push_back(iPhi);
129  }
130 }
131 
132 vector <pair<HcalDetId, const float *> >HPDNoiseLibraryReader::getNoisyHcalDetIds(CLHEP::HepRandomEngine* engine) {
133 
134  vector <pair< HcalDetId, const float *> >result;
135 
136  // decide which phi are noisy by using noise rates
137  // and random numbers (to be called for each event)
138  getNoisyPhis(engine);
139  for (int i = 0; i < int (theNoisyPhi.size()); ++i) {
140  int iphi = theNoisyPhi[i];
142 
143  data = getNoiseData(iphi, engine);
144  for (unsigned int i = 0; i < data->size(); ++i) {
145 
146  result.emplace_back(data->getDataFrame(i).id(), data->getDataFrame(i).getFrame());
147  }
148  }
149  return result;
150 }
151 
152 vector <pair<HcalDetId, const float *> >HPDNoiseLibraryReader::getNoisyHcalDetIds(int timeSliceId, CLHEP::HepRandomEngine* engine)
153 {
154  vector <pair< HcalDetId, const float *> >result;
155  // decide which phi are noisy by using noise rates
156  // and random numbers (to be called for each event)
157  getNoisyPhis(engine);
158  for (int i = 0; i < int (theNoisyPhi.size()); ++i) {
159  int iphi = theNoisyPhi[i];
161 
162  data = getNoiseData(iphi, engine);
163  for (unsigned int i = 0; i < data->size(); ++i) {
164  float* data_ = const_cast<float*>(data->getDataFrame(i).getFrame());
165  shuffleData(timeSliceId, data_);
166  const float* _data_ =const_cast<const float*>(data_);
167  result.emplace_back(data->getDataFrame(i).id(), _data_);
168  }
169  }
170  return result;
171 
172 }
173 vector < pair < HcalDetId, const float *> >HPDNoiseLibraryReader::getBiasedNoisyHcalDetIds(int timeSliceId, CLHEP::HepRandomEngine* engine) {
174 
175  vector < pair < HcalDetId, const float *> >result;
176 
177  // decide which phi are noisy by using noise rates
178  // and random numbers (to be called for each event)
179  // at least one Phi is always noisy.
180  getBiasedNoisyPhis(engine);
181  for (int i = 0; i < int (theNoisyPhi.size()); ++i) {
182  int iphi = theNoisyPhi[i];
184 
185  data = getNoiseData(iphi, engine);
186  for (unsigned int i = 0; i < data->size(); ++i) {
187  float* data_ = const_cast<float*>(data->getDataFrame(i).getFrame());
188  shuffleData(timeSliceId, data_);
189  const float* _data_ =const_cast<const float*>(data_);
190  result.emplace_back(data->getDataFrame(i).id(), _data_);
191  }
192  }
193  return result;
194 }
195 
196 vector < pair < HcalDetId, const float *> >HPDNoiseLibraryReader::getBiasedNoisyHcalDetIds(CLHEP::HepRandomEngine* engine) {
197 
198  vector < pair < HcalDetId, const float *> >result;
199 
200  // decide which phi are noisy by using noise rates
201  // and random numbers (to be called for each event)
202  // at least one Phi is always noisy.
203  getBiasedNoisyPhis(engine);
204  for (int i = 0; i < int (theNoisyPhi.size()); ++i) {
205  int iphi = theNoisyPhi[i];
207 
208  data = getNoiseData(iphi, engine);
209  for (unsigned int i = 0; i < data->size(); ++i) {
210  result.emplace_back(data->getDataFrame(i).id(), data->getDataFrame(i).getFrame());
211  }
212  }
213  return result;
214 }
215 
216 double HPDNoiseLibraryReader::getIonFeedbackNoise(HcalDetId id, double energy, double bias, CLHEP::HepRandomEngine* engine) {
217 
218  // constants for simulation/parameterization
219  double pe2Charge = 0.333333; // fC/p.e.
220  double GeVperfC = 0.177; // in unit GeV/fC and this will be updated when it start reading from DB.
221  double PedSigma = 0.8;
222  double noise = 0.; // fC
223 
224  int iphi = (id.ieta() > 0) ? (id.iphi()) : (id.iphi() + 72);
225  double rateInTail = theIonFeedbackFirstPeakRate[iphi - 1];
226  double rateInSecondTail = theIonFeedbackSecondPeakRate[iphi - 1];
227 
228  if (bias != 0.) {
229  rateInTail = rateInTail * bias;
230  rateInSecondTail = rateInSecondTail * bias;
231  } else {
232  edm::LogError("HPDNoise") << "HPDNoise: ion feedback error (biased or unbiased selection)." << bias << " failed";
233  throw cms::Exception("Unknown", "biase selection ")
234  << "Usage of " << bias << " fails\n";
235  }
236  double Charge = energy / GeVperfC;
237 
238  // three gauss fit is applied to data to get ion feedback distribution
239  // the script is at neutralino: /home/tyetkin/work/hpd_noise/PlotFromPelin.C
240  // a new fit woth double-sigmoids is under way.
241  // parameters (in fC)
242  // first gaussian
243  // double p0 = 9.53192e+05;
244  // double p1 = -3.13653e-01;
245  // double p2 = 2.78350e+00;
246 
247  // second gaussian
248  // double p3 = 2.41611e+03;
249  double p4 = 2.06117e+01;
250  double p5 = 1.09239e+01;
251 
252  // third gaussian
253  // double p6 = 3.42793e+01;
254  double p7 = 5.45548e+01;
255  double p8 = 1.59696e+01;
256 
257  if (Charge > 3 * PedSigma) { // 3 sigma away from pedestal mean
258  int npe = int (Charge / pe2Charge);
259  double a = 0.;
260  double b = 0.;
261 
262  for (int j = 0; j < npe; ++j) {
263  double probability = CLHEP::RandFlat::shoot(engine);
264 
265  if (probability < rateInTail) { // total tail
266  if (probability < rateInSecondTail) { // second tail
267  Rannor(a, b, engine);
268  noise += b * p8 + p7;
269  } else {
270  Rannor(a, b, engine);
271  noise += b * p5 + p4;
272  }
273  }
274  }
275  // add pedestal
276  if (noise > 0.)
277  noise += CLHEP::RandGaussQ::shoot(engine, 0, 2 * PedSigma);
278  }
279  return (noise * GeVperfC); // returns noise in GeV.
280 
281 }
282 
284 
285  bool isAccepted = false;
286  vector < int >::iterator phi_iter;
287 
288  phi_iter = find(theNoisyPhi.begin(), theNoisyPhi.end(), iphi);
289  if (phi_iter != theNoisyPhi.end()) {
290  isAccepted = true;
291  }
292  return isAccepted;
293 }
294 void HPDNoiseLibraryReader::shuffleData(int timeSliceId, float* &data)
295 {
296  if(timeSliceId == -1 || (timeSliceId>=10)) return;
297  //make a local copy of input data
298  float Data[10] = {0.,0.,0.,0.,0.,0.,0.,0.,0.,0.};
299  for(int i=0;i<10;++i){
300  Data[i] = data[i];
301  }
302  int ts_max = -1;
303  float max = -999.;
304  for(int i=0;i<10;++i){
305  if(Data[i]>max){
306  max = data[i];
307  ts_max = i;
308  }
309  }
310  if((ts_max == -1)){//couldn't find ts_max, return the same value.
311  return;
312  }else{
313  // always shift the noise to the right by putting zeroes to the previous slices.
314  // the noise is pedestal subtracted. 0 value is acceptable.
315  int k = -1;
316  for(int i=0;i<10;++i){
317  data[i] = 0.;
318  int newIdx = timeSliceId+k;
319  float dd = 0.;
320  if(newIdx < 10){
321  data[newIdx] = Data[ts_max+k];
322  dd = Data[ts_max+k];
323  i = newIdx;
324  }
325  data[i] = dd;
326  ++k;
327  }
328 
329  }
330 }
331 
332 //I couldn't find Rannor in CLHEP/Random. For now, use it from ROOT (copy/paste) by little modification.
333 void HPDNoiseLibraryReader::Rannor(double &a, double &b, CLHEP::HepRandomEngine* engine) {
334  double r,
335  x,
336  y,
337  z;
338 
339  y = CLHEP::RandFlat::shoot(engine);
340  z = CLHEP::RandFlat::shoot(engine);
341  x = z * 6.28318530717958623;
342  r = TMath::Sqrt(-2 * TMath::Log(y));
343  a = r * TMath::Sin(x);
344  b = r * TMath::Cos(x);
345 }
347  stringstream s;
348 
349  s << i;
350  return s.str();
351 }
352 
354  theNoisyPhi.clear();
355 }
T getParameter(std::string const &) const
T getUntrackedParameter(std::string const &, T const &) const
int i
Definition: DBlmapReader.cc:9
std::vector< float > theIonFeedbackFirstPeakRate
const HPDNoiseDataFrame & getDataFrame(size_t i) const
retrive frame for the given index
Definition: HPDNoiseData.cc:21
const float * getFrame() const
array of 10 charges corresponding to one channel
float dischargeRate(Handle fHandle) const
discharge rate for the instance
HPDNoiseLibraryReader(const edm::ParameterSet &)
const double pe2Charge
Handle getHandle(const std::string &fName)
get handle to access data for one HPD instance
int zside(DetId const &)
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
std::vector< std::pair< HcalDetId, const float * > > getBiasedNoisyHcalDetIds(CLHEP::HepRandomEngine *)
unsigned long totalEntries(Handle fHandle) const
total number of noise events for the HPD instance in the library
std::vector< int > theNoisyPhi
tuple result
Definition: mps_fire.py:84
void Rannor(double &a, double &b, CLHEP::HepRandomEngine *)
float ionFeedbackSecondPeakRate(Handle fHandle) const
std::vector< float > theIonFeedbackSecondPeakRate
bool valid(Handle fHandle) const
test if handle is valid
double getIonFeedbackNoise(HcalDetId id, double energy, double bias, CLHEP::HepRandomEngine *)
double p4[4]
Definition: TauolaWrapper.h:92
std::vector< std::string > theNames
int j
Definition: DBlmapReader.cc:9
HcalDetId id() const
detId for the frame
void getBiasedNoisyPhis(CLHEP::HepRandomEngine *)
std::vector< std::string > allNames() const
all HPD instances in the library
double b
Definition: hdecay.h:120
std::vector< float > theDischargeNoiseRate
HPDNoiseData * getNoiseData(int iphi, CLHEP::HepRandomEngine *)
float ionFeedbackFirstPeakRate(Handle fHandle) const
ionfeedback rate for the instance
char data[epos_bytes_allocation]
Definition: EPOS_Wrapper.h:82
double a
Definition: hdecay.h:121
void getEntry(Handle fHandle, HPDNoiseData **fData)
retrive one entry from the sequentially
list entry
Definition: mps_splice.py:62
void getNoisyPhis(CLHEP::HepRandomEngine *)
std::vector< std::pair< HcalDetId, const float * > > getNoisyHcalDetIds(CLHEP::HepRandomEngine *)
unsigned size() const
number of noise channels in the event
Definition: HPDNoiseData.h:24
void shuffleData(int timeSliceId, float *&data)