scfit.cc

00001 /* 
00002 Used laserrun.cc for structure
00003 */
00004 
00005 
00006 //include all header files as in laserrun except ones know won't need
00007 #include "FitOverROI.hh"
00008 #include "FitTH1F.hh"
00009 #include "TNamed.h"
00010 #include "TString.h"
00011 #include "TCanvas.h"
00012 #include "EventData.hh"
00013 #include "TRint.h"
00014 #include "utilities.hh"
00015 #include "RootGraphix.hh"
00016 #include <sstream>
00017 #include <fstream>
00018 #include <map>
00019 #include <vector>
00020 #include <iostream>
00021 #include <iomanip>
00022 #include <cstdlib>
00023 #include "TTree.h"
00024 #include "TFile.h"
00025 #include "TF1.h"
00026 //header files from FitOverROI
00027 #include "TMath.h"
00028 #include "TROOT.h"
00029 #include "TFitResult.h"
00030 #include "TSpectrum.h"
00031 #include "TPad.h"
00032 #include "TLine.h"
00033 #include "TAxis.h"
00034 #include "TList.h"
00035 #include "TCut.h"
00036 #include "TGraph.h"
00037 #include "TGraphErrors.h"
00038 #include <algorithm>
00039 #include <numeric>
00040 #include <string>
00041 #include "TMultiGraph.h"
00042 #include "TAttMarker.h"
00043 #include "TStyle.h"
00044 #include "TAttLine.h"
00045 
00046 
00047 using namespace std;
00048 
00049 class tab{
00050 public:
00051   int n;
00052   char f;
00053   tab(int nspaces, char fill=' ') : n(nspaces),f(fill) {}
00054 };
00055 
00056 //i suppose these should be in a header file.
00057 double base_start_time = -1; //baseline start time
00058 double base_end_time = -0.2;  //baseline end time
00059 double sample_rate = 250.; //250 samples per us
00060 double fit_min = 1.0; //start of fit window
00061 double fit_max = 6.0; //end of fit window
00062 bool background = true; //use constant background in fit?
00063 
00064 #define mLifetime 1.5;
00065 #define mShot_noise 0.5;
00066 #define mAmplitude 10000; //10 basic avg, 10000 sum, .001 energy
00067 #define mConst 0;
00068 
00069 ostream& operator<<(ostream& out, tab t)
00070 { return out<<left<<setfill(t.f)<<setw(t.n); }
00071 
00072 
00073 Double_t ExpFunc(double* x, double* params) {
00074   double y = x[0];
00075   double lifetime = params[0];
00076   //double shot_noise = params[1];
00077   double scale = params[2];
00078   double constant = params[3];
00079   double funct = TMath::Power(TMath::E(),-y/lifetime);
00080   /*
00081   double funct = (1/lifetime)*
00082     TMath::Power(TMath::E(),shot_noise*shot_noise/
00083                  (2*lifetime*lifetime) - y/lifetime) * 
00084     1/2*(1+TMath::Erf((y - shot_noise*shot_noise/lifetime) /
00085                       (sqrt(2)*shot_noise)));
00086   */
00087   return scale*funct+constant;
00088 }
00089 
00090 
00091 //draw all splits for single channel or vice versa
00092 void DrawMany(map<int, TGraphErrors*>* avgwaveforms, RootGraphix* root, TCanvas* c) {
00093   c->Clear();
00094   int padn=1;
00095   DividePad(c, avgwaveforms->size());
00096   int color = 1;
00097   for( std::map<int,TGraphErrors*>::iterator it = avgwaveforms->begin();
00098        it != avgwaveforms->end(); it++) {
00099     c->cd(padn++);
00100     RootGraphix::Lock lock = root->AcquireLock();
00101     gPad->SetLogy();
00102     TGraphErrors* graph = (it->second);
00103     TAxis* xaxis = graph->GetXaxis();
00104     xaxis->SetRangeUser(-2, 10);    //plot only (-2,10) us
00105     TAxis* yaxis = graph->GetYaxis();
00106     yaxis->SetRangeUser(1., yaxis->GetXmax());
00107     graph->SetLineColor(color);
00108     graph->SetMarkerColor(color);
00109     graph->Draw("ALP");
00110     //color += 1;
00111   }
00112   c->cd(0);
00113   c->Update();
00114 
00115 }
00116 
00117 void DrawSingle(TGraphErrors* graph, RootGraphix* root, TCanvas* c) {
00118   c->Clear();
00119   RootGraphix::Lock lock = root->AcquireLock();
00120   gPad->SetLogy();
00121   TAxis* xaxis = graph->GetXaxis();
00122   xaxis->SetRangeUser(-2, 10);
00123   xaxis->SetTitle("time [#mus]");
00124   graph->Draw("ALP");
00125   c->Update();
00126 }
00127 
00128 void PlotResiduals(TGraphErrors* graph, RootGraphix* root, TCanvas* c) {
00129   c->Clear();
00130   RootGraphix::Lock lock = root->AcquireLock();
00131   TF1* func = graph->GetFunction("exp_func_f");
00132   double* x = graph->GetX();
00133   double* y = graph->GetY();
00134   int nsamps = graph->GetN();
00135   double resid_x[nsamps];
00136   double resid_y[nsamps];
00137   //calculate residuals for all values from fit_min to end
00138   for (int i=0; i<nsamps; i++) {
00139     resid_x[i] = x[i];
00140     if (x[i]<fit_min) {
00141       resid_y[i] = 0;
00142     }
00143     else {
00144       resid_y[i] = y[i]-func->Eval(x[i]);
00145     }
00146   }
00147   TGraph* residuals = new TGraph(nsamps, resid_x, resid_y);
00148   residuals->SetTitle(graph->GetTitle());
00149   TAxis* xaxis = residuals->GetXaxis();
00150   xaxis->SetRangeUser(func->GetXmin(), func->GetXmax()); //plot from fit_min to fit_max
00151   xaxis->SetTitle("time [#mus]");
00152   TAxis* yaxis = residuals->GetYaxis();
00153   yaxis->SetTitle("residuals [a.u.]");
00154   residuals->SetMarkerStyle(kFullDotMedium);
00155   residuals->Draw("AP");
00156   c->SetGridy(1);
00157   c->Update();
00158 }
00159 
00160 int TimeToSample(double time, double sample_rate, int trigger_index, int split) {
00161   int samp = (int)(time*sample_rate+trigger_index);
00162   samp = (int)TMath::Floor((double) samp / (double) split );
00163   return samp;
00164 }
00165 
00166 //calculate straight baseline mean and variance
00167 void Baseline(double* baseline_mean, double* baseline_var, TGraphErrors* graph, int split) {
00168   double* y = graph->GetY();
00169   double* x = graph->GetX();
00170   double baseline = 0;
00171   double sumsq = 0;
00172   const int trigger_index = (int)TMath::Floor(sample_rate*TMath::Abs(x[0])); //trigger at 0
00173   const int base_start_index = TimeToSample(base_start_time, sample_rate, trigger_index, split);
00174   const int base_end_index = TimeToSample(base_end_time, sample_rate, trigger_index, split);
00175   for (int i = base_start_index; i<base_end_index; i++) {
00176     baseline += y[i]/((double) base_end_index - (double) base_start_index);
00177     sumsq += y[i]*y[i]/((double) base_end_index - (double) base_start_index);
00178   }
00179   *baseline_var = sumsq - baseline*baseline;
00180   *baseline_mean = baseline;
00181   
00182 }
00183 
00184 
00185 //loop over all entries of a map<int, map<int, TGraphErrors*> >
00186 void Loop(void (*func)(TGraphErrors* wave, int), 
00187           map<int, map<int, TGraphErrors*> >* split_waves, int split) {
00188   for (map<int, map<int, TGraphErrors*> >::iterator it = split_waves->begin();
00189        it != split_waves->end(); it++) {
00190     for (map<int, TGraphErrors*>::iterator it2 = it->second.begin();
00191          it2 != it->second.end(); it2++) {
00192       TGraphErrors* wave = it2->second;
00193       (*func)(wave, split);
00194     }
00195   }
00196 }
00197 
00198 //add baseline errors in quadrature with waveform errors
00199 void AddBaselineErrors(TGraphErrors* wave, int nSplit) {
00200   double* ey = wave->GetEY();
00201   double baseline_mean = 0;
00202   double baseline_var = 0;
00203   Baseline(&baseline_mean, &baseline_var, wave, nSplit);
00204   for (int i=0; i<wave->GetN(); i++) {
00205     ey[i] = sqrt(baseline_var+ey[i]*ey[i]);
00206   }
00207 }
00208 
00209 void loopAddBaselineErrors(map<int, map<int, TGraphErrors*> >* split_waves_by_ch, int nSplit) {
00210   Loop(AddBaselineErrors, split_waves_by_ch, nSplit);
00211 }
00212 
00213 //subtract baseline from waveform
00214 void Subtract(TGraphErrors* wave, int nSplit) {
00215   double baseline_mean = 0;
00216   double baseline_var = 0;
00217   Baseline(&baseline_mean, &baseline_var, wave, nSplit);
00218   double* y = wave->GetY();
00219   for (int i=0; i<wave->GetN(); i++) {
00220     y[i] = y[i] - baseline_mean;
00221   }
00222 }
00223 
00224 void loopSubtract(map<int, map<int, TGraphErrors*> >* split_waves_by_split, int nSplit) {
00225   Loop(Subtract, split_waves_by_split, nSplit);
00226 }
00227 
00228 //fit using MINUIT
00229 void Fit(TGraphErrors* wave, int nSplit) {
00230   
00231   int nparams = 4;
00232   double params[nparams];
00233   params[0] = mLifetime;  //lifetime
00234   params[1] = mShot_noise; //shot_noise
00235   params[2] = mAmplitude //scale factor
00236   params[3] = mConst; //constant background
00237   
00238   TF1* exp_func_f = new TF1("exp_func_f",ExpFunc,fit_min, fit_max, nparams);
00239   
00240   exp_func_f->SetLineColor(kGreen);
00241   exp_func_f->SetParameters(params);
00242   exp_func_f->SetLineWidth(3);
00243   exp_func_f->SetParNames("lifetime","shot_noise","scale","constant");
00244   exp_func_f->FixParameter(1, 0);
00245   if (!background)
00246     exp_func_f->FixParameter(3, 0);
00247   TFitResultPtr fit_result = wave->Fit(exp_func_f,"MRE+");
00248   
00249   /*
00250   //plot additional exponentials with tau +/- 0.1 us 
00251   TList* funclist = wave->GetListOfFunctions();
00252   
00253   TF1* exp_func1 = new TF1("exp_func1", ExpFunc, fit_min,fit_max,nparams);
00254   (wave->GetFunction("exp_func_f"))->Copy(*exp_func1);
00255   exp_func1->SetLineColor(kBlue);
00256   exp_func1->SetParameters(exp_func_f->GetParameters());
00257   exp_func1->SetParameter(0, exp_func_f->GetParameter(0)+0.1);
00258   exp_func1->SetRange(0.2, wave->GetXaxis()->GetXmax());
00259   funclist->AddLast(exp_func1);
00260   
00261   TF1* exp_func2 = new TF1("exp_func2",ExpFunc,fit_min,fit_max, nparams);
00262   (wave->GetFunction("exp_func_f"))->Copy(*exp_func2);
00263   exp_func2->SetLineColor(kBlue);
00264   exp_func2->SetParameters(exp_func_f->GetParameters());
00265   exp_func2->SetParameter(0, exp_func_f->GetParameter(0)-0.1);
00266   exp_func2->SetRange(0.2, wave->GetXaxis()->GetXmax());
00267   funclist->AddLast(exp_func2);
00268   */
00269 }
00270 
00271 void loopFit(map<int, map<int, TGraphErrors*> >* split_waves, int nSplit) {
00272   Loop(Fit, split_waves, nSplit);
00273 }
00274 
00275 //split average waveform into pieces
00276 void Split(map<int, TGraphErrors*>* avgwaveforms, map<int, map<int,TGraphErrors*> >* split_waves, int split) {
00277   //split_waves: pointer to map of [ch] to [map of (split) to (TGraph)]
00278   
00279   for (std::map<int,TGraphErrors*>::iterator it = avgwaveforms->begin();
00280        it != avgwaveforms->end(); it++) {
00281     TGraphErrors* avggraph = (it->second);
00282     int splitN = (int)TMath::Floor((double) avggraph->GetN()/(double) split);
00283     
00284     double* x = avggraph->GetX();
00285     double* y = avggraph->GetY();
00286     double* ey = avggraph->GetEY();
00287     //populate split_waves with "split" number of waves
00288     int ch = (it->first);
00289     std::map<int,TGraphErrors*> waves;
00290     int n = (it->first);
00291     char name[25];
00292     for (int i=0; i<split; i++) {
00293       TGraphErrors* graph = new TGraphErrors(splitN);
00294       waves.insert(std::make_pair(i, graph));
00295       sprintf(name,"ch%d split%d", n, i);
00296       waves[i]->SetName(name);
00297       waves[i]->SetTitle(name);
00298     }
00299     
00300     //populate each graph with a wave
00301     for (int j=0; j<avggraph->GetN(); j++) {
00302       if (j % split == 0 && j<(avggraph->GetN()-split+1)) {
00303         int jj = (int)TMath::Floor((double) j / (double) split);
00304         for (int i=0; i<split; i++) {
00305           waves[i]->SetPoint(jj, x[j+i], y[j+i]);
00306           waves[i]->SetPointError(jj, 0, ey[j+i]);
00307         }
00308       }
00309     }
00310     
00311     split_waves->insert(std::make_pair(ch, waves));
00312   }
00313 }
00314 
00315 void Reorganize(map<int, map<int, TGraphErrors*> >* split_waves_by_ch, 
00316                 map<int, map<int, TGraphErrors*> >* split_waves_by_split) {
00317   for (map<int, map<int, TGraphErrors*> >::iterator it = split_waves_by_ch->begin();
00318        it != split_waves_by_ch->end(); it++) {
00319     map<int, TGraphErrors*> ch = it->second;
00320     int ch_i = it->first;
00321     for (map<int, TGraphErrors*>::iterator it2 = ch.begin(); it2 != ch.end(); it2++) {
00322       TGraphErrors* wave = it2->second;
00323       int split_i = it2->first;
00324       if (!(split_waves_by_split->count(split_i)>0)) {
00325         map<int, TGraphErrors*> wave_i;
00326         split_waves_by_split->insert(make_pair(split_i, wave_i));
00327       }
00328       (split_waves_by_split->find(split_i))->second.insert(make_pair(ch_i, wave));
00329     }
00330   }
00331 }
00332 
00333 
00334 //print all fitted parameters
00335 void PrintResults(map<int, map<int, TGraphErrors*> >* split_waves_by_ch, int nSplit, int run) {
00336   int width = 80;
00337   cout<<"\n"<<tab(width,'*')<<""<<"\n"<<"Results for run"<<run<<" \n"<<tab(width,'*')<<""<<endl;
00338   
00339   for (map<int, map<int, TGraphErrors*> >::iterator it = split_waves_by_ch->begin();
00340        it != split_waves_by_ch->end(); it++) {
00341     cout << "\nChannel " << it->first << "\n" << tab(width, '-') << "" << endl;
00342     cout<<tab(10)<<"split"<<tab(20)<<"lifetime"<<tab(20)<<"amplitude"<<tab(20)<<"background"<<tab(20)<<"chi2/ndf"<<endl;
00343     cout << tab(width,'-') << "" << endl;
00344     map<int, TGraphErrors*> waves = it->second;
00345     for (map<int, TGraphErrors*>::iterator it2 = waves.begin();
00346          it2 != waves.end(); it2++) {
00347       TGraphErrors* graph = it2->second;
00348       TF1* func = graph->GetFunction("exp_func_f");
00349       char lifetime[50];
00350       char amplitude[50];
00351       char offset[50];
00352       char chisq[50];
00353       sprintf(lifetime, "%#.5g +- %.4f", func->GetParameter(0), func->GetParError(0));
00354       sprintf(amplitude, "%#.5g +- %.4f", func->GetParameter(2), func->GetParError(2));
00355       sprintf(offset, "%#.5g +- %.4f", func->GetParameter(3), func->GetParError(3));
00356       sprintf(chisq, "%#.5g/%d", func->GetChisquare(), func->GetNDF());
00357       cout<<tab(10)<<it2->first<<tab(20)<<lifetime<<tab(20)<<amplitude<<tab(20)<<offset<<tab(20)<<chisq<<endl;
00358     }
00359     
00360   }
00361 }
00362 
00363 int ProcessRun(const char* fname) {
00364   
00365   
00366   
00367   //open the root file
00368   RootGraphix root;
00369   root.Initialize();
00370   TFile *f = OpenFile(fname, "UPDATE");
00371   if (!f) {cout<<"File not opened!"<<endl;}
00372   TTree* Events = GetEventsTree(fname);
00373   if (!Events) {cout<<"!Events"<<endl; return -1;}
00374   
00375   EventData* event = 0;
00376   Events->SetBranchAddress("event",&event);
00377   Events->GetEntry(0);
00378   cout<<"There are "<<Events->GetEntries()<<" entries in this tree."<<endl;
00379 
00380   int nChans = event->channels.size();
00381   int run = event->run_id;
00382   printf("run %d\n", run);
00383   
00384   //put all the TGraphErrors into a map
00385   std::map<int, TGraphErrors*> avgwaveforms;
00386   for (int i=0; i<nChans; i++) {
00387     int chan = event->channels.at(i).channel_num;
00388     if (chan < 0) { //there are average waveforms for positive channels only
00389       continue;
00390     }
00391     if (chan == 6 || chan == 7) { //don't include channels 6 (crappy) or 7 (different tube)
00392       continue; 
00393     }
00394     TGraphErrors* avgch = (TGraphErrors*) GetAverageGraph(fname, chan);
00395     avgwaveforms.insert( std::make_pair(chan, avgch));
00396   }
00397   
00398   //split avgwaveforms--------
00399   int nSplit = 8;
00400   //split_waves_by_ch: map of [ch] to [map of (split) to (TGraph*)]
00401   std::map<int, map<int, TGraphErrors*> > split_waves_by_ch;
00402   Split(&avgwaveforms, &split_waves_by_ch, nSplit);
00403   
00404   //reorganize split_waveforms for convenience
00405   //split_waves_by_split: map of [split] to [map of (ch) to (TGraph*)]
00406   map<int, map<int, TGraphErrors*> > split_waves_by_split;
00407   Reorganize(&split_waves_by_ch, &split_waves_by_split);
00408   
00409   
00410   //do analysis----------------
00411   
00412   //add baseline errors in quadrature; do separately for each split
00413   loopAddBaselineErrors(&split_waves_by_split, nSplit);
00414   
00415   //subtract any baseline offset
00416   loopSubtract(&split_waves_by_split, nSplit);
00417 
00418   //do the fits
00419   loopFit(&split_waves_by_split, nSplit);
00420   
00421   
00422   //print results--------------
00423   PrintResults(&split_waves_by_ch, nSplit, run);
00424   
00425   
00426   
00427   //draw stuff-----------------
00428   
00429   //draw all splits for single channel or vice versa
00430   TCanvas* c = new TCanvas("c","fname");
00431   int chsplit = 4; //plot everything for this channel (or split)
00432   //for single split:
00433   DrawMany(&split_waves_by_split[chsplit], &root, c); //or split_waves_by_ch[chsplit] for single channel
00434   gStyle->SetOptFit();
00435    
00436   //draw single ch, single split
00437   TCanvas* c3 = new TCanvas("c3", "ch_single");
00438   int plot_ch = 4;
00439   int plot_split = 5;
00440   TGraphErrors* ch_single = split_waves_by_ch[plot_ch][plot_split];
00441   DrawSingle(ch_single, &root, c3);
00442   
00443   //plot residuals in fitted region for single ch,split
00444   TCanvas* c1 = new TCanvas("c1", "residuals");
00445   PlotResiduals(ch_single, &root, c1);
00446   
00447   
00448   char pause2;
00449   cout << endl << "Enter anything to quit." << endl;
00450   cin>>pause2;
00451   
00452   
00453   
00454   return 0;
00455 }
00456 
00457 
00458 int main( int argc, char** argv) 
00459 {
00460   
00461   //generate the run filename; make sure root file is there manually!
00462   std::stringstream rootfile, rawfile;
00463   /*
00464   int run = atoi(argv[1]);
00465   //rootfile << "./Run";
00466   rootfile << "/data/test_processing/afan/Run";
00467   rawfile  << "/data/rawdata/Run";
00468   rootfile<<std::setw(6)<<std::setfill('0')<<run<<".root";
00469   rawfile<<std::setw(6)<<std::setfill('0')<<run<<".out.gz";
00470   printf("%d \n", run);
00471   */
00472   
00473   /*
00474   runid = atoi(argv[1]);
00475   rootfile << "/data/test_processing/afan/lifetimes/Run";
00476   rootfile <<std::setw(6)<<std::setfill('0')<<runid<<".root";
00477   printf("%d \n", runid);
00478   */
00479   
00480   rootfile<<argv[1]; //to enter location explicitly at command line
00481 
00482 
00483   return ProcessRun(rootfile.str().c_str());
00484 }
00485 
00486 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on 20 Jun 2014 for daqman by  doxygen 1.6.1