Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AZigzag.C
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file AZigzag.C
1 #include<iostream>
2 
3 #include "AZigzag.h"
4 
5 #include "TObject.h"
6 #include "TCanvas.h"
7 #include "TPad.h"
8 #include "TBox.h"
9 #include "TMath.h"
10 #include "TSpectrum.h"
11 #include "TPolyLine.h"
12 #include "Quiver.h"
13 #include "groot.h"
14 
15 #include <cmath> //don't put this in class header.
16 #include <math.h>
17 #include <algorithm>
18 #include <fstream>
19 #include <string>
20 #include "TPolyLine.h"
21 #include "TH2D.h"
22 #include "TH1D.h"
23 #include "TF1.h"
24 #include <algorithm>
25 using namespace std;
26 
27 int AZigzag::nextID=0;
28 
29 bool AZigzag::FastQ = false; // FastQ is bad....
30 bool AZigzag::UseSigma = true;
31 std::vector<int> AZigzag::Raw[Nsrs];
32 std::vector<double> AZigzag::Cal[Nsrs];
33 
34 double AZigzag::Pedestals[Nsrs] = {0};
35 double AZigzag::Sigmas[Nsrs] = {0};
36 double AZigzag::Gains[Nsrs] = {0};
37 
38 TRandom AZigzag::Randy;
39 
40 std::vector<double> AZigzag::CommonMode[Nhybrid];
41 
42 TH1D* AZigzag::Pulse=0; /* @TODO Do we need this? */
43 TF1* AZigzag::blue=0; /* @TODO Do we need this? */
44 TH1D* AZigzag::commy[Nhybrid] = {0};
45 
46 double AZigzag::SigmaCut=4;
47 double AZigzag::PulseCut=100;
48 string AZigzag::CommonModeMethod="median";
49 
51 {
52  fPads = paddef;
53 
54  double minR = *min_element(fPads.r.begin(),fPads.r.end());
55  double maxR = *max_element(fPads.r.begin(),fPads.r.end());
56  double minPhi = *min_element(fPads.phi.begin(),fPads.phi.end());
57  double maxPhi = *max_element(fPads.phi.begin(),fPads.phi.end());
58 
59  myR = (minR+maxR)/2.0;
60  myPhi = (minPhi+maxPhi)/2.0;
61 
62  // Set the complex mappig pointers as null at creation.
63  PreLogical = 0;
64  PostLogical = 0;
65  PreWaveform = 0;
66  PostWaveform= 0;
67 
68  myID = nextID++;
69 
70  Randy.SetSeed();
71 }
72 
73 
74 void AZigzag::Draw(double MAX)
75 {
76  int N = fPads.fX.size();
77  TPolyLine* Ziggy = new TPolyLine(N, &(fPads.fX[0]), &(fPads.fY[0]));
78 
79  /*cout << " N" << N;
80  cout << " x" << fPads.fX[0];
81  cout << " y" << fPads.fY[0];
82  cout << endl;
83  */
84  Ziggy->SetFillStyle(1001);
85  Ziggy->SetFillColor(18);
86 
87 
88  // 51-100 looks like a ROYGBIV scale in root.
89  if ( IsHit() )
90  {
91  double f = q/MAX;
92  if (f>1) f=1;
93  int CLR = 51 + f*49;
94  Ziggy->SetFillColor(CLR);
95  }
96 
97  Ziggy->SetLineStyle(1);
98  Ziggy->SetLineWidth(1);
99  Ziggy->SetLineColor(18);
100 
101  Ziggy->Draw("f");
102 }
103 
104 int AZigzag::color(int) {}
105 
106 
108 {
109  string dir( getenv("MYCALIB") );
110  string file("ZIGZAG_CALIBRATIONS.TXT");
111  string result = dir + file;
112  cout << "Looking to write Zigzag Calibrations in " << result << endl;
113  ofstream fin(result.c_str());
114 
115  if (!fin.is_open())
116  {
117  cout << "Groot could not open the file ZIGZAG_CALIBRATIONS.TXT." << endl;
118  return;
119  }
120 
121 
122  for (int i=0; i<Nsrs; i++)
123  {
124  fin << Pedestals[i] << " " << Sigmas[i] << " " << Gains[i] << endl;
125  cout << Pedestals[i] << " " << Sigmas[i] << " " << Gains[i] << endl;
126  }
127  fin.close();
128 }
129 
131 {
132  cout << "Reading ZIGZAG calibrations..." << endl;
133 
134  string dir( getenv("MYCALIB") );
135  string file("ZIGZAG_CALIBRATIONS.TXT");
136  string result = dir + file;
137  cout << "Looking to read Zigzag Calibrations in " << result << endl;
138  ifstream fin(result.c_str());
139 
140  if (!fin.is_open())
141  {
142  cout << "Groot could not open the file ZIGZAG_CALIBRATIONS.TXT." << endl;
143  cout << "Please initialize the variable $MYCALIB in your .login." << endl;
144  cout << "Then move the ZIGZAG_CALIBRATIONS.TXT file to there." << endl;
145  cout << "Here we will make fake calibrations..." << endl;
146  for ( int i=0; i < Nsrs; i++ )
147  {
148  Pedestals[i] = 0;
149  Sigmas[i] = 0;
150  Gains[i] = 1;
151  }
152  cout << "FAKED!" << endl;
153  return;
154  }
155 
156  cout << "FOUND! Reading Calibrations..." << endl;
157  for ( int i=0; i < Nsrs; i++ )
158  {
159  fin >> Pedestals[i] >> Sigmas[i] >> Gains[i];
160  //cout << Pedestals[i] << " " << Sigmas[i] << " " << Gains[i] << endl;
161  }
162  fin.close();
163 
164  cout << "DONE." << endl;
165 }
166 
168 {
169  groot* Tree = groot::instance();
170 
171  string method = CommonModeMethod;
172 
173  for (int i=0; i<Nhybrid; i++)
174  {
175  CommonMode[i].clear();
176  }
177 
178  if (method == "off")
179  {
180  for (int i=0; i<Nhybrid; i++)
181  {
182  for (int j=0; j<Raw[0].size(); j++)
183  {
184  CommonMode[i].push_back(0);
185  }
186  }
187  }
188  else if (method == "median")
189  {
190  vector<double> pedheights[Nhybrid]; // one vector of doubles for the non-fired chans from every hybrid.
191 
192  // Loop over the time slices...
193  for (int i=0; i<Raw[0].size(); i++)
194  {
195 
196  // The pedheights[hybrid] is reused in every timeslice i, gotta clear it...
197  for (int q=0; q<Nhybrid; q++)
198  {
199  pedheights[q].clear();
200  }
201 
202  // loop over all zigzags for this timeslice add value to pedheight vector.
203  for (int j=0; j< Tree->theZigzags.size(); j++)
204  {
205  int which = (Tree->theZigzags[j])->MyHybrid;
206  double hit = Pedestals[(Tree->theZigzags[j])->MyID()] - Raw[(Tree->theZigzags[j])->MyID()][i];
207 
208  pedheights[which].push_back(hit);
209  }
210 
211  // Now all zigzags have made entries to pedheights vectors.
212  // Determine the medians of each such pedheights distribution.
213  // Save these as the CommonMode Value...
214  for (int q=0; q<Nhybrid; q++)
215  {
216  if (pedheights[q].size()>10)
217  {
218  sort(pedheights[q].begin(),pedheights[q].end());
219  int index = pedheights[q].size()/2;
220  CommonMode[q].push_back(pedheights[q][index]);
221  }
222  else
223  {
224  CommonMode[q].push_back(0);
225  }
226  }
227  }
228  }
229 
230  else if (method == "gauss" || method == "spectrum")
231  {
232  for (int i=0; i<Nhybrid; i++)
233  {
234  char name[500];
235  sprintf(name,"commy%02d",i);
236  commy[i] = new TH1D(name,name,40,-330,70);
237  }
238 
239  TF1* gss = new TF1("gss", "[0]*exp(-((x-[1])*(x-[1])/(2*[2]*[2])))", -100, 100);
240  gss->SetParLimits(0,0,128);
241  gss->SetParLimits(1,-330,70);
242  gss->SetParLimits(2,7,40);
243 
244  for (int i=0; i<Raw[0].size(); i++)
245  {
246 
247  /* loop over all zigzag types */
248  for (int j=0; j< Tree->theZigzags.size(); j++)
249  {
250  int which = (Tree->theZigzags[j])->MyHybrid;
251  commy[which]->Fill(Pedestals[(Tree->theZigzags[j])->MyID()] - Raw[(Tree->theZigzags[j])->MyID()][i]);
252  }
253 
254  for (int k=0; k<Nhybrid; k++)
255  {
256  if (commy[k]->Integral(1,commy[k]->GetNbinsX())>64)
257  {
258  if ( method == "gauss" )
259  {
260  int bin = commy[k]->GetMaximumBin();
261 
262  gss->SetParameter(0,commy[k]->GetBinContent(bin));
263  gss->SetParameter(1,commy[k]->GetBinCenter(bin));
264  gss->SetParameter(2,17);
265  commy[k]->Fit(gss,"WWQM0");
266 
267  //CommonCompare->Fill( CommonMode[k][i], commy[k]->GetFunction("gss")->GetParameter(1));
268  //cout << "timeslice: " << k;
269  //cout << " vector method = " << CommonMode[k][i];
270  //cout << " gauss method = " << commy[k]->GetFunction("gss")->GetParameter(1);
271  //cout << endl;
272  CommonMode[k].push_back(commy[k]->GetFunction("gss")->GetParameter(1));
273 
274  if (i==7)
275  {
276  char name[50];
277  sprintf(name,"cmm%d",k);
278  commy[k]->Clone(name);
279  }
280 
281  }
282  else // method == "spectrum"
283  {
284  TSpectrum sspec(10);
285  int nPeaks = sspec.Search( commy[k] , 2 , "goff" );
286 
287  float peak_max_x = 0;
288  float peak_max_y = 0;
289 
290  float *xpeaks = sspec.GetPositionX();
291  float *ypeaks = sspec.GetPositionY();
292 
293  for ( int peak_j = 0; peak_j < nPeaks; peak_j++ )
294  {
295  //cout << "Found peak at x = " << xpeaks[peak_j] << " , y = " << ypeaks[peak_j] << endl;
296  if ( ypeaks[peak_j] > peak_max_y )
297  {
298  peak_max_x = xpeaks[peak_j];
299  peak_max_y = ypeaks[peak_j];
300  }
301  }
302 
303  CommonMode[k].push_back( peak_max_x );
304  //cout << "**using peak at x = " << peak_max_x << " , y = " << peak_max_y << endl;
305  }
306  commy[k]->Reset();
307  }
308  else
309  {
310  CommonMode[k].push_back(0);
311  }
312  }
313  }
314  for (int m=0; m<Nhybrid; m++)
315  {
316  commy[m]->Delete();
317  }
318  gss->Delete();
319  }
320 
321  else
322  {
323  cerr << "ERROR: AZigzag::DetermineCommonMode -> Unknown method " << method << endl;
324  }
325 
326 }
327 
329 {
330  groot* Tree = groot::instance();
331 
332  for (int i=0; i<Nsrs; i++) //loop over all zigzag types
333  {
334  Cal[i].clear();
335  if (Tree->ZigzagMap[i])
336  {
337  for(int j=0; j<Raw[i].size(); j++)
338  {
339  int which = Tree->ZigzagMap[i]->MyHybrid;
340  Cal[i].push_back(Gains[i]*(Pedestals[i]-Raw[i][j]-CommonMode[which][j]));
341  }
342  }
343  }
344 }
345 
346 void AZigzag::DetermineQ(double Mintime, double Maxtime)
347 {
348  if (FastQ)
349  {
350  maxq = -100;
351  maxt = -100;
352  for (int i=0; i<Cal[myID].size(); i++)
353  {
354  if (Cal[myID][i] > maxq)
355  {
356  maxq = Cal[myID][i];
357  maxt = i;
358  }
359  }
360  q = maxq;
361  t = maxt;
362 
363  return;
364  }
365 
366 
367  // After some analysis of pulser data, we have
368  // determined a fit function that does a good job at extracting the charge.
369  //
370  // The function in question is a fermi function multipled by a gaussian.
371  // The initial trial was a fermi function multiplied by an exponential,
372  // but that choice poorly described the tail.
373  //
374  // MB & TKH 3-8-2013
375  if (!blue)
376  {
377  Pulse = new TH1D("Pulse", "Pulse", Cal[myID].size(), -0.5, (double)Cal[myID].size()-0.5);
378  blue = new TF1("blue", "[0]/(exp(-(x-[1])/[2])+1)*exp(-((x-[1])^2/[3]))", 0, 30);
379 
380  //blue->FixParameter(1,7); // Expt on 3-8-2013
381  blue->FixParameter(2,0.42); // Expt on 3-8-2013
382  blue->FixParameter(3,53.7); // Expt on 3-8-2013
383  }
384 
385 
386  //Here we are just averaging over time slices as a first approximation...
387  //NOTE: root will treat errors on each bin as sqrt(content). This is
388  //not true nor appropriate for an ADC. Instead we should treat them as constant errors.
389  //I will choose the sigma of the channel in question as the error!
390  for (int i=0; i<Cal[myID].size(); i++)
391  {
392  Pulse->SetBinContent(i+1,Cal[myID][i]);
393  Pulse->SetBinError(i+1,Sigmas[myID]);
394  }
395  double max = Pulse->GetBinContent(Pulse->GetMaximumBin());
396  double min = Pulse->GetBinContent(Pulse->GetMinimumBin());
397  double t0 = Pulse->GetBinCenter(Pulse->GetMaximumBin())-2.0;
398 
399  blue->SetParameter(0,max);
400  blue->SetParameter(1,(Mintime+Maxtime)/2.0);
401 
402  // Note: The above-parameterized curve does NOT peak at a.
403  // It peaks at a*AFACTOR !!!
404  double AFACTOR = 0.933;
405  blue->SetParLimits(0, min/AFACTOR-2.0*Sigmas[myID], max/AFACTOR+2.0*Sigmas[myID]);
406  blue->SetParLimits(1, Mintime, Maxtime);
407 
408  Pulse->Fit(blue,"Q0");
409 
410  q = blue->GetParameter(0)*AFACTOR;
411  t = blue->GetParameter(1);
412 }
413 
414 
416 {
417  //cout << "Q: " << q;
418  //cout << "\tT: " << t;
419  //cout << "\tID: " << myID;
420  //cout << "\tHBD: " << MyHybrid;
421  //cout << "\tiR: " << iR+1;
422  //cout << "\tiPhi: " << iPhi;
423  //if (IsHit()) cout << " **HIT** " << endl;
424 }
425 
426 
427 double AZigzag::XCenter() { return myR*cos(myPhi); }
428 
429 double AZigzag::YCenter() { return myR*sin(myPhi); }
430 
431 double AZigzag::ZCenter() { return 0; }
432 
433 double AZigzag::RCenter() { return myR; }
434 
435 double AZigzag::PCenter() { return myPhi; }