Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:15:10

0001 #include<iostream>
0002 
0003 #include "AZigzag.h"
0004 
0005 #include "TObject.h"
0006 #include "TCanvas.h"
0007 #include "TPad.h"
0008 #include "TBox.h"
0009 #include "TMath.h"
0010 #include "TSpectrum.h"
0011 #include "TPolyLine.h"
0012 #include "Quiver.h"
0013 #include "groot.h"
0014 
0015 #include <cmath>   //don't put this in class header.
0016 #include <math.h>
0017 #include <algorithm>
0018 #include <fstream>
0019 #include <string>
0020 #include "TPolyLine.h"
0021 #include "TH2D.h"
0022 #include "TH1D.h"
0023 #include "TF1.h"
0024 #include <algorithm>
0025 using namespace std;
0026 
0027 int AZigzag::nextID=0;
0028 
0029 bool AZigzag::FastQ = false; // FastQ is bad....
0030 bool AZigzag::UseSigma = true;
0031 std::vector<int> AZigzag::Raw[Nsrs];
0032 std::vector<double> AZigzag::Cal[Nsrs];
0033 
0034 double AZigzag::Pedestals[Nsrs] = {0};
0035 double AZigzag::Sigmas[Nsrs] = {0};
0036 double AZigzag::Gains[Nsrs] = {0};
0037 
0038 TRandom AZigzag::Randy;
0039 
0040 std::vector<double> AZigzag::CommonMode[Nhybrid];
0041 
0042 TH1D* AZigzag::Pulse=0; /* @TODO Do we need this? */
0043 TF1*  AZigzag::blue=0; /* @TODO Do we need this? */
0044 TH1D* AZigzag::commy[Nhybrid] = {0};
0045 
0046 double AZigzag::SigmaCut=4;
0047 double AZigzag::PulseCut=100;
0048 string AZigzag::CommonModeMethod="median";
0049 
0050 AZigzag::AZigzag( CheveronPad_t paddef )
0051 {
0052   fPads = paddef;
0053 
0054   double minR = *min_element(fPads.r.begin(),fPads.r.end());
0055   double maxR = *max_element(fPads.r.begin(),fPads.r.end());
0056   double minPhi = *min_element(fPads.phi.begin(),fPads.phi.end());
0057   double maxPhi = *max_element(fPads.phi.begin(),fPads.phi.end());
0058   
0059   myR = (minR+maxR)/2.0;
0060   myPhi = (minPhi+maxPhi)/2.0;
0061 
0062   // Set the complex mappig pointers as null at creation.
0063   PreLogical  = 0;
0064   PostLogical = 0;
0065   PreWaveform = 0;
0066   PostWaveform= 0;
0067 
0068   myID = nextID++;
0069 
0070   Randy.SetSeed();
0071 }
0072 
0073 
0074 void AZigzag::Draw(double MAX) 
0075 {
0076   int N = fPads.fX.size();
0077   TPolyLine* Ziggy = new TPolyLine(N, &(fPads.fX[0]), &(fPads.fY[0]));
0078   
0079   /*cout << " N" << N;
0080   cout << " x" << fPads.fX[0];
0081   cout << " y" << fPads.fY[0];
0082   cout << endl;
0083   */
0084   Ziggy->SetFillStyle(1001);
0085   Ziggy->SetFillColor(18);
0086   
0087 
0088   //  51-100 looks like a ROYGBIV scale in root.
0089   if ( IsHit() ) 
0090     {
0091       double f = q/MAX;
0092       if (f>1) f=1;
0093       int CLR = 51 + f*49;
0094       Ziggy->SetFillColor(CLR);
0095     }
0096 
0097   Ziggy->SetLineStyle(1);
0098   Ziggy->SetLineWidth(1);
0099   Ziggy->SetLineColor(18);
0100   
0101   Ziggy->Draw("f");
0102 }
0103 
0104 int AZigzag::color(int) {}
0105 
0106 
0107 void AZigzag::WriteCalibration()
0108 {
0109   string dir( getenv("MYCALIB") );
0110   string file("ZIGZAG_CALIBRATIONS.TXT");
0111   string result = dir + file;
0112   cout << "Looking to write Zigzag Calibrations in " << result << endl;
0113   ofstream fin(result.c_str());
0114 
0115   if (!fin.is_open())
0116     {
0117       cout <<  "Groot could not open the file ZIGZAG_CALIBRATIONS.TXT." << endl;
0118       return;
0119     }
0120 
0121   
0122   for (int i=0; i<Nsrs; i++)
0123     {
0124       fin << Pedestals[i] << " " << Sigmas[i] << " " << Gains[i] << endl;
0125       cout << Pedestals[i] << " " << Sigmas[i] << " " << Gains[i] << endl;
0126     }
0127   fin.close();
0128 }
0129 
0130 void AZigzag::ReadCalibration()
0131 {
0132   cout << "Reading ZIGZAG calibrations..." << endl;
0133 
0134   string dir( getenv("MYCALIB") );
0135   string file("ZIGZAG_CALIBRATIONS.TXT");
0136   string result = dir + file;
0137   cout << "Looking to read Zigzag Calibrations in " << result << endl;
0138   ifstream fin(result.c_str());
0139   
0140   if (!fin.is_open())
0141     {
0142       cout <<  "Groot could not open the file ZIGZAG_CALIBRATIONS.TXT." << endl;
0143       cout <<  "Please initialize the variable $MYCALIB in your .login." << endl;
0144       cout <<  "Then move the ZIGZAG_CALIBRATIONS.TXT file to there." << endl;
0145       cout <<  "Here we will make fake calibrations..." << endl;
0146       for ( int i=0; i < Nsrs; i++ )
0147     {
0148       Pedestals[i]  = 0;
0149       Sigmas[i]     = 0;
0150       Gains[i]      = 1;
0151     }
0152       cout << "FAKED!" << endl;
0153       return;
0154     }
0155 
0156   cout << "FOUND!  Reading Calibrations..." << endl;
0157   for ( int i=0; i < Nsrs; i++ )
0158     {
0159       fin >> Pedestals[i] >> Sigmas[i] >> Gains[i];
0160       //cout << Pedestals[i] << " " << Sigmas[i] << " " << Gains[i] << endl;
0161     }
0162   fin.close();
0163 
0164   cout << "DONE." << endl;
0165 }
0166 
0167 void AZigzag::DetermineCommonMode()
0168 {
0169   groot* Tree = groot::instance();
0170 
0171   string method = CommonModeMethod;
0172 
0173   for (int i=0; i<Nhybrid; i++)
0174     {
0175       CommonMode[i].clear();
0176     }
0177 
0178   if (method == "off")
0179     {
0180       for (int i=0; i<Nhybrid; i++)
0181     {
0182       for (int j=0; j<Raw[0].size(); j++)
0183         {
0184           CommonMode[i].push_back(0);
0185         }
0186     }
0187     }
0188   else if (method == "median")
0189     {
0190       vector<double> pedheights[Nhybrid]; // one vector of doubles for the non-fired chans from every hybrid.      
0191 
0192       //  Loop over the time slices...
0193       for (int i=0; i<Raw[0].size(); i++)
0194     {
0195 
0196       //  The pedheights[hybrid] is reused in every timeslice i, gotta clear it...
0197       for (int q=0; q<Nhybrid; q++)
0198         {
0199           pedheights[q].clear();
0200         }
0201       
0202       // loop over all zigzags for this timeslice add value to pedheight vector.
0203       for (int j=0; j< Tree->theZigzags.size(); j++)
0204         {
0205           int which = (Tree->theZigzags[j])->MyHybrid;
0206           double hit = Pedestals[(Tree->theZigzags[j])->MyID()] - Raw[(Tree->theZigzags[j])->MyID()][i];
0207 
0208           pedheights[which].push_back(hit);
0209         }
0210 
0211       // Now all zigzags have made entries to pedheights vectors.
0212       // Determine the medians of each such pedheights distribution.
0213       // Save these as the CommonMode Value...
0214       for (int q=0; q<Nhybrid; q++)
0215         {
0216           if (pedheights[q].size()>10)
0217         {
0218           sort(pedheights[q].begin(),pedheights[q].end());
0219           int index = pedheights[q].size()/2;
0220           CommonMode[q].push_back(pedheights[q][index]);
0221         }
0222           else
0223         {
0224           CommonMode[q].push_back(0);
0225         }
0226             }
0227     }
0228     }
0229 
0230   else if (method == "gauss" || method == "spectrum")
0231     {
0232       for (int i=0; i<Nhybrid; i++)
0233     {
0234       char name[500];
0235       sprintf(name,"commy%02d",i);
0236       commy[i] = new TH1D(name,name,40,-330,70);
0237     }
0238       
0239       TF1* gss = new TF1("gss", "[0]*exp(-((x-[1])*(x-[1])/(2*[2]*[2])))", -100, 100);
0240       gss->SetParLimits(0,0,128);
0241       gss->SetParLimits(1,-330,70);
0242       gss->SetParLimits(2,7,40);
0243       
0244       for (int i=0; i<Raw[0].size(); i++)
0245     {
0246       
0247       /* loop over all zigzag types */
0248       for (int j=0; j< Tree->theZigzags.size(); j++)
0249         {
0250           int which = (Tree->theZigzags[j])->MyHybrid;
0251           commy[which]->Fill(Pedestals[(Tree->theZigzags[j])->MyID()] - Raw[(Tree->theZigzags[j])->MyID()][i]);
0252         }
0253       
0254       for (int k=0; k<Nhybrid; k++)
0255         {
0256           if (commy[k]->Integral(1,commy[k]->GetNbinsX())>64)
0257         {
0258           if ( method == "gauss" )
0259             {
0260               int bin = commy[k]->GetMaximumBin();
0261               
0262               gss->SetParameter(0,commy[k]->GetBinContent(bin));
0263               gss->SetParameter(1,commy[k]->GetBinCenter(bin));
0264               gss->SetParameter(2,17);
0265               commy[k]->Fit(gss,"WWQM0");
0266 
0267               //CommonCompare->Fill( CommonMode[k][i],  commy[k]->GetFunction("gss")->GetParameter(1));
0268               //cout << "timeslice: " << k;
0269               //cout << " vector method = " << CommonMode[k][i];
0270               //cout << " gauss method = " << commy[k]->GetFunction("gss")->GetParameter(1);
0271               //cout << endl;
0272               CommonMode[k].push_back(commy[k]->GetFunction("gss")->GetParameter(1));
0273               
0274               if (i==7)
0275             {
0276               char name[50];
0277               sprintf(name,"cmm%d",k);
0278               commy[k]->Clone(name);
0279             }
0280               
0281             }
0282           else // method == "spectrum"
0283             {
0284               TSpectrum sspec(10);
0285               int nPeaks = sspec.Search( commy[k] , 2 , "goff" );
0286               
0287               float peak_max_x = 0;
0288               float peak_max_y = 0;
0289               
0290               float *xpeaks = sspec.GetPositionX();
0291               float *ypeaks = sspec.GetPositionY();
0292               
0293               for ( int peak_j = 0; peak_j < nPeaks; peak_j++ )
0294             {
0295               //cout << "Found peak at x = " << xpeaks[peak_j] << " , y = " << ypeaks[peak_j] << endl;
0296               if (  ypeaks[peak_j] > peak_max_y )
0297                 {
0298                   peak_max_x = xpeaks[peak_j];
0299                   peak_max_y = ypeaks[peak_j];
0300                 }
0301             }
0302               
0303               CommonMode[k].push_back( peak_max_x );
0304               //cout << "**using peak at x = " << peak_max_x << " , y = " << peak_max_y << endl;
0305             }
0306           commy[k]->Reset();
0307         }
0308           else
0309         {
0310           CommonMode[k].push_back(0);
0311         }
0312         }
0313     }
0314       for (int m=0; m<Nhybrid; m++)
0315     {
0316       commy[m]->Delete();
0317     }
0318       gss->Delete();
0319     }
0320   
0321   else
0322     {
0323       cerr << "ERROR:  AZigzag::DetermineCommonMode -> Unknown method " << method << endl; 
0324     }
0325   
0326 }
0327 
0328 void AZigzag::ApplyCalibration()
0329 {
0330   groot* Tree = groot::instance();
0331 
0332   for (int i=0; i<Nsrs; i++) //loop over all zigzag types
0333     {
0334       Cal[i].clear();
0335       if (Tree->ZigzagMap[i])
0336     {
0337       for(int j=0; j<Raw[i].size(); j++)
0338         {
0339           int which = Tree->ZigzagMap[i]->MyHybrid;
0340           Cal[i].push_back(Gains[i]*(Pedestals[i]-Raw[i][j]-CommonMode[which][j]));
0341         }
0342     }
0343     }  
0344 }
0345 
0346 void AZigzag::DetermineQ(double Mintime, double Maxtime)
0347 {
0348   if (FastQ)
0349     {
0350       maxq = -100;
0351       maxt = -100;
0352       for (int i=0; i<Cal[myID].size(); i++)
0353         {
0354       if (Cal[myID][i] > maxq)
0355         {
0356           maxq = Cal[myID][i];
0357           maxt = i;
0358         }
0359         }
0360       q = maxq;
0361       t = maxt;
0362 
0363       return;
0364     }
0365     
0366 
0367   //  After some analysis of pulser data, we have 
0368   //  determined a fit function that does a good job at extracting the charge.  
0369   //
0370   //  The function in question is a fermi function multipled by a gaussian.
0371   //  The initial trial was a fermi function multiplied by an exponential,
0372   //  but that choice poorly described the tail.
0373   //
0374   //                                                   MB & TKH 3-8-2013
0375   if (!blue)
0376     {
0377       Pulse = new TH1D("Pulse", "Pulse", Cal[myID].size(), -0.5, (double)Cal[myID].size()-0.5);
0378       blue  = new TF1("blue", "[0]/(exp(-(x-[1])/[2])+1)*exp(-((x-[1])^2/[3]))", 0, 30);
0379       
0380       //blue->FixParameter(1,7);  // Expt on 3-8-2013
0381       blue->FixParameter(2,0.42);  // Expt on 3-8-2013
0382       blue->FixParameter(3,53.7);  // Expt on 3-8-2013
0383     }
0384 
0385 
0386   //Here we are just averaging over time slices as a first approximation...
0387   //NOTE:  root will treat errors on each bin as sqrt(content). This is 
0388   //not true nor appropriate for an ADC. Instead we should treat them as constant errors.
0389   //I will choose the sigma of the channel in question as the error!
0390   for (int i=0; i<Cal[myID].size(); i++)
0391     {
0392       Pulse->SetBinContent(i+1,Cal[myID][i]);
0393       Pulse->SetBinError(i+1,Sigmas[myID]);
0394     }
0395   double max = Pulse->GetBinContent(Pulse->GetMaximumBin());
0396   double min = Pulse->GetBinContent(Pulse->GetMinimumBin());
0397   double t0  = Pulse->GetBinCenter(Pulse->GetMaximumBin())-2.0;
0398 
0399   blue->SetParameter(0,max);
0400   blue->SetParameter(1,(Mintime+Maxtime)/2.0);
0401 
0402   //  Note:  The above-parameterized curve does NOT peak at a.
0403   //  It peaks at a*AFACTOR !!!
0404   double AFACTOR = 0.933;
0405   blue->SetParLimits(0, min/AFACTOR-2.0*Sigmas[myID], max/AFACTOR+2.0*Sigmas[myID]);
0406   blue->SetParLimits(1, Mintime, Maxtime);
0407 
0408   Pulse->Fit(blue,"Q0");
0409 
0410   q = blue->GetParameter(0)*AFACTOR;
0411   t = blue->GetParameter(1);
0412 }
0413 
0414 
0415 void AZigzag::Report()
0416 {
0417   //cout << "Q: " << q;
0418   //cout << "\tT: " << t;
0419   //cout << "\tID: " << myID;
0420   //cout << "\tHBD: " << MyHybrid;
0421   //cout << "\tiR: " << iR+1;
0422   //cout << "\tiPhi: " << iPhi;
0423   //if (IsHit()) cout << " **HIT** " << endl;
0424 }
0425 
0426 
0427 double AZigzag::XCenter() { return myR*cos(myPhi); }
0428 
0429 double AZigzag::YCenter() { return myR*sin(myPhi); }
0430 
0431 double AZigzag::ZCenter() { return 0; }
0432 
0433 double AZigzag::RCenter() { return myR; }
0434 
0435 double AZigzag::PCenter() { return myPhi; }