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 
17 
18 using namespace edm;
19 using namespace std;
20 
22 :theDischargeNoiseRate(0),
23 theIonFeedbackFirstPeakRate(0),
24 theIonFeedbackSecondPeakRate(0),
25 theNoisyPhi(0),
26 theRandFlat(0),
27 theRandGaussQ(0) {
29 
30  ParameterSet pSet = iConfig.getParameter < edm::ParameterSet > ("HPDNoiseLibrary");
31  FileInPath filepath = pSet.getParameter < edm::FileInPath > ("FileName");
32 
33  theHPDName = pSet.getUntrackedParameter < string > ("HPDName", "HPD");
34  string pName = filepath.fullPath();
35 
36  if (pName.find(".") == 0)
37  pName.erase(0, 2);
38  theReader = new HPDNoiseReader(pName);
39  theNames = theReader->allNames(); // all 72x2 HPDs
40 
41  fillRates();
42 }
43 
45  if (theRandFlat)
46  delete theRandFlat;
47 
48  if (theRandGaussQ)
49  delete theRandGaussQ;
50 }
51 
55  }
56 
58  "process CorrNoise = {"
59  "service = RandomNumberGeneratorService" "{" "untracked uint32 sourceSeed = 123456789" "}" "}";
60 
61  // create the services
63 
64  // make the services available
66 }
69  if (!rng.isAvailable()) {
70  throw cms::Exception("Configuration") << "HcalHPDNoiseLibrary requires the RandomNumberGeneratorService\n"
71  "which is not present in the configuration file. You must add the service\n"
72  "in the configuration file or remove the modules that require it.";
73  }
74  setRandomEngine(rng->getEngine());
75 }
76 void HPDNoiseLibraryReader::setRandomEngine(CLHEP::HepRandomEngine & engine) {
77  if (theRandGaussQ)
78  delete theRandGaussQ;
79 
80  if (theRandFlat)
81  delete theRandFlat;
82 
83  theRandGaussQ = new CLHEP::RandGaussQ(engine);
84  theRandFlat = new CLHEP::RandFlat(engine);
85 }
86 
88  for (size_t i = 0; i < theNames.size(); ++i) {
90  if (theReader->valid(hpdObj)) {
91  theDischargeNoiseRate.push_back(theReader->dischargeRate(hpdObj));
94  } else {
95  std::cerr << "HPD Handle Object is not valid!" << endl;
96  }
97  }
98 }
99 
101 
102 
103  HPDNoiseData *data = 0; //data->size() is checked wherever actually used
104 
105  // make sure that iphi from HcalDetId is found noisy at first.
106  // In other words, be sure that iphi is in the collection of
107  // noisy Phis
108  if (!(IsNoiseApplicable(iphi)))
109  return data;
110 
111  int zside = 1;
112 
113  if (iphi > 72) {
114  iphi = iphi - 72;
115  zside = -1;
116  }
118  if (zside == 1) {
119  name = "ZPlus" + theHPDName + itos(iphi);
120  } else if (zside == -1) {
121  name = "ZMinus" + theHPDName + itos(iphi);
122  } else {
123  cerr << " ZSide Calculation Error." << endl;
124  }
126  if (theReader->valid(hpdObj)) {
127  // randomly select one entry from library for this HPD
128  unsigned long entry = theRandFlat->fireInt(theReader->totalEntries(hpdObj));
129 
130  theReader->getEntry(hpdObj, entry, &data);
131  } else {
132  std::cerr << " HPD Name in the library is not valid." << std::endl;
133  }
134  return data;
135 }
136 
137 
139 
140  clearPhi();
141  double rndm[144];
142 
143  theRandFlat->shootArray(144, rndm);
144 
145  for (int i = 0; i < 144; ++i) {
146  if (rndm[i] < theDischargeNoiseRate[i]) {
147  theNoisyPhi.push_back(i + 1);
148  }
149  }
150 }
151 
153 
154  clearPhi();
155  double rndm[144];
156 
157  theRandFlat->shootArray(144, rndm);
158  for (int i = 0; i < 144; ++i) {
159  if (rndm[i] < theDischargeNoiseRate[i]) {
160  theNoisyPhi.push_back(i + 1);
161  }
162  }
163  // make sure one HPD is always noisy
164  if (theNoisyPhi.size() == 0) {
165  int iPhi = (theRandFlat->fireInt(144)) + 1; // integer from interval [0-144[ + 1
166 
167  theNoisyPhi.push_back(iPhi);
168  }
169 }
170 
171 vector <pair<HcalDetId, const float *> >HPDNoiseLibraryReader::getNoisyHcalDetIds() {
172 
173  vector <pair< HcalDetId, const float *> >result;
174 
175  // decide which phi are noisy by using noise rates
176  // and random numbers (to be called for each event)
177  getNoisyPhis();
178  for (int i = 0; i < int (theNoisyPhi.size()); ++i) {
179  int iphi = theNoisyPhi[i];
181 
182  data = getNoiseData(iphi);
183  for (unsigned int i = 0; i < data->size(); ++i) {
184 
185  result.emplace_back(data->getDataFrame(i).id(), data->getDataFrame(i).getFrame());
186  }
187  }
188  return result;
189 }
190 
191 vector <pair<HcalDetId, const float *> >HPDNoiseLibraryReader::getNoisyHcalDetIds(int timeSliceId)
192 {
193  vector <pair< HcalDetId, const float *> >result;
194  // decide which phi are noisy by using noise rates
195  // and random numbers (to be called for each event)
196  getNoisyPhis();
197  for (int i = 0; i < int (theNoisyPhi.size()); ++i) {
198  int iphi = theNoisyPhi[i];
200 
201  data = getNoiseData(iphi);
202  for (unsigned int i = 0; i < data->size(); ++i) {
203  float* data_ = const_cast<float*>(data->getDataFrame(i).getFrame());
204  shuffleData(timeSliceId, data_);
205  const float* _data_ =const_cast<const float*>(data_);
206  result.emplace_back(data->getDataFrame(i).id(), _data_);
207  }
208  }
209  return result;
210 
211 }
212 vector < pair < HcalDetId, const float *> >HPDNoiseLibraryReader::getBiasedNoisyHcalDetIds(int timeSliceId) {
213 
214  vector < pair < HcalDetId, const float *> >result;
215 
216  // decide which phi are noisy by using noise rates
217  // and random numbers (to be called for each event)
218  // at least one Phi is always noisy.
220  for (int i = 0; i < int (theNoisyPhi.size()); ++i) {
221  int iphi = theNoisyPhi[i];
223 
224  data = getNoiseData(iphi);
225  for (unsigned int i = 0; i < data->size(); ++i) {
226  float* data_ = const_cast<float*>(data->getDataFrame(i).getFrame());
227  shuffleData(timeSliceId, data_);
228  const float* _data_ =const_cast<const float*>(data_);
229  result.emplace_back(data->getDataFrame(i).id(), _data_);
230  }
231  }
232  return result;
233 }
234 
235 vector < pair < HcalDetId, const float *> >HPDNoiseLibraryReader::getBiasedNoisyHcalDetIds() {
236 
237  vector < pair < HcalDetId, const float *> >result;
238 
239  // decide which phi are noisy by using noise rates
240  // and random numbers (to be called for each event)
241  // at least one Phi is always noisy.
243  for (int i = 0; i < int (theNoisyPhi.size()); ++i) {
244  int iphi = theNoisyPhi[i];
246 
247  data = getNoiseData(iphi);
248  for (unsigned int i = 0; i < data->size(); ++i) {
249  result.emplace_back(data->getDataFrame(i).id(), data->getDataFrame(i).getFrame());
250  }
251  }
252  return result;
253 }
254 
256 
257  // constants for simulation/parameterization
258  double pe2Charge = 0.333333; // fC/p.e.
259  double GeVperfC = 0.177; // in unit GeV/fC and this will be updated when it start reading from DB.
260  double PedSigma = 0.8;
261  double noise = 0.; // fC
262 
263  int iphi = (id.ieta() > 0) ? (id.iphi()) : (id.iphi() + 72);
264  double rateInTail = theIonFeedbackFirstPeakRate[iphi - 1];
265  double rateInSecondTail = theIonFeedbackSecondPeakRate[iphi - 1];
266 
267  if (bias != 0.) {
268  rateInTail = rateInTail * bias;
269  rateInSecondTail = rateInSecondTail * bias;
270  } else {
271  edm::LogError("HPDNoise") << "HPDNoise: ion feedback error (biased or unbiased selection)." << bias << " failed";
272  throw cms::Exception("Unknown", "biase selection ")
273  << "Usage of " << bias << " fails\n";
274  }
275  double Charge = energy / GeVperfC;
276 
277  // three gauss fit is applied to data to get ion feedback distribution
278  // the script is at neutralino: /home/tyetkin/work/hpd_noise/PlotFromPelin.C
279  // a new fit woth double-sigmoids is under way.
280  // parameters (in fC)
281  // first gaussian
282  // double p0 = 9.53192e+05;
283  // double p1 = -3.13653e-01;
284  // double p2 = 2.78350e+00;
285 
286  // second gaussian
287  // double p3 = 2.41611e+03;
288  double p4 = 2.06117e+01;
289  double p5 = 1.09239e+01;
290 
291  // third gaussian
292  // double p6 = 3.42793e+01;
293  double p7 = 5.45548e+01;
294  double p8 = 1.59696e+01;
295 
296  if (Charge > 3 * PedSigma) { // 3 sigma away from pedestal mean
297  int npe = int (Charge / pe2Charge);
298  double a = 0.;
299  double b = 0.;
300 
301  for (int j = 0; j < npe; ++j) {
302  double probability = theRandFlat->shoot();
303 
304  if (probability < rateInTail) { // total tail
305  if (probability < rateInSecondTail) { // second tail
306  Rannor(a, b);
307  noise += b * p8 + p7;
308  } else {
309  Rannor(a, b);
310  noise += b * p5 + p4;
311  }
312  }
313  }
314  // add pedestal
315  if (noise > 0.)
316  noise += theRandGaussQ->fire(0, 2 * PedSigma);
317  }
318  return (noise * GeVperfC); // returns noise in GeV.
319 
320 }
321 
323 
324  bool isAccepted = false;
325  vector < int >::iterator phi_iter;
326 
327  phi_iter = find(theNoisyPhi.begin(), theNoisyPhi.end(), iphi);
328  if (phi_iter != theNoisyPhi.end()) {
329  isAccepted = true;
330  }
331  return isAccepted;
332 }
333 void HPDNoiseLibraryReader::shuffleData(int timeSliceId, float* &data)
334 {
335  if(timeSliceId == -1 || (timeSliceId>=10)) return;
336  //make a local copy of input data
337  float Data[10] = {0.,0.,0.,0.,0.,0.,0.,0.,0.,0.};
338  for(int i=0;i<10;++i){
339  Data[i] = data[i];
340  }
341  int ts_max = -1;
342  float max = -999.;
343  for(int i=0;i<10;++i){
344  if(Data[i]>max){
345  max = data[i];
346  ts_max = i;
347  }
348  }
349  if((ts_max == -1)){//couldn't find ts_max, return the same value.
350  return;
351  }else{
352  // always shift the noise to the right by putting zeroes to the previous slices.
353  // the noise is pedestal subtracted. 0 value is acceptable.
354  int k = -1;
355  for(int i=0;i<10;++i){
356  data[i] = 0.;
357  int newIdx = timeSliceId+k;
358  float dd = 0.;
359  if(newIdx < 10){
360  data[newIdx] = Data[ts_max+k];
361  dd = Data[ts_max+k];
362  i = newIdx;
363  }
364  data[i] = dd;
365  ++k;
366  }
367 
368  }
369 }
370 
371 //I couldn't find Rannor in CLHEP/Random. For now, use it from ROOT (copy/paste) by little modification.
372 void HPDNoiseLibraryReader::Rannor(double &a, double &b) {
373  double r,
374  x,
375  y,
376  z;
377 
378  y = theRandFlat->shoot();
379  z = theRandFlat->shoot();
380  x = z * 6.28318530717958623;
381  r = TMath::Sqrt(-2 * TMath::Log(y));
382  a = r * TMath::Sin(x);
383  b = r * TMath::Cos(x);
384 }
386  stringstream s;
387 
388  s << i;
389  return s.str();
390 }
391 
393  theNoisyPhi.clear();
394 }
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
static PluginManager & configure(const Config &)
const float * getFrame() const
array of 10 charges corresponding to one channel
float dischargeRate(Handle fHandle) const
discharge rate for the instance
CLHEP::RandGaussQ * theRandGaussQ
HPDNoiseLibraryReader(const edm::ParameterSet &)
std::vector< std::pair< HcalDetId, const float * > > getBiasedNoisyHcalDetIds()
Handle getHandle(const std::string &fName)
get handle to access data for one HPD instance
double getIonFeedbackNoise(HcalDetId id, double energy, double bias)
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:7
double pe2Charge
unsigned long totalEntries(Handle fHandle) const
total number of noise events for the HPD instance in the library
float float float z
std::vector< int > theNoisyPhi
float ionFeedbackSecondPeakRate(Handle fHandle) const
std::vector< float > theIonFeedbackSecondPeakRate
static ServiceToken createServicesFromConfig(std::string const &config)
bool valid(Handle fHandle) const
test if handle is valid
PluginManager::Config config()
Definition: standard.cc:21
const T & max(const T &a, const T &b)
double p4[4]
Definition: TauolaWrapper.h:92
std::vector< std::string > theNames
tuple result
Definition: query.py:137
bool isAvailable() const
Definition: Service.h:46
int j
Definition: DBlmapReader.cc:9
virtual CLHEP::HepRandomEngine & getEngine() const =0
Use this to get the random number engine, this is the only function most users should call...
HcalDetId id() const
detId for the frame
std::vector< std::pair< HcalDetId, const float * > > getNoisyHcalDetIds()
int k[5][pyjets_maxn]
std::vector< std::string > allNames() const
all HPD instances in the library
void Rannor(double &a, double &b)
double b
Definition: hdecay.h:120
std::vector< float > theDischargeNoiseRate
CLHEP::RandFlat * theRandFlat
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
Definition: DDAxes.h:10
HPDNoiseData * getNoiseData(int iphi)
unsigned size() const
number of noise channels in the event
Definition: HPDNoiseData.h:24
void shuffleData(int timeSliceId, float *&data)