LightYield.cc

00001 #include "LightYield.hh"
00002 #include "utilities.hh"
00003 #include "EventData.hh"
00004 
00005 #include "TGraphErrors.h"
00006 #include "TH1F.h"
00007 #include "TH1D.h"
00008 #include "TTree.h"
00009 #include "TPad.h"
00010 #include "TF1.h"
00011 #include "TSpectrum.h"
00012 #include "TString.h"
00013 #include "TRegexp.h"
00014 #include "TLine.h"
00015 #include "TLegend.h"
00016 #include "TPad.h"
00017 #include "TCanvas.h"
00018 #include "TROOT.h"
00019 #include "TTree.h"
00020 #include "TSystem.h"
00021 #include "TLine.h"
00022 
00023 #include <iostream>
00024 #include <iomanip>
00025 #include <algorithm>
00026 #include <sstream>
00027 #include <map>
00028 
00029 using namespace std;
00030 
00031 int LightYieldGraph::AddRun(int run, double epeak, int nbins,
00032              double emin, double emax)
00033 {
00034   //construct the filename
00035   stringstream filename;
00036   filename<<"/data/test_processing/single_pe/Run"<<setw(6)<<setfill('0')
00037           <<run<<".root";
00038   return AddFile(filename.str().c_str(), epeak, nbins, emin, emax);
00039 
00040 }
00041 
00042 int LightYieldGraph::AddRuns(const vector<int>& runs, double epeak, int nbins, 
00043               double emin, double emax)
00044 {
00045   int n = 0;
00046   for(size_t i=0; i< runs.size(); i++){
00047     n += AddRun(runs[i], epeak, nbins, emin, emax);
00048   }
00049   return n;
00050 }
00051 
00052 int LightYieldGraph::AddFile(const char* filename, double epeak, int nbins, 
00053              double emin, double emax)
00054 {
00055   cout<<"\n***********************************************\n";
00056   cout<<"Loading file "<<filename<<endl;
00057   if(histo) histo->Delete();
00058   histo = DrawSpectrum(filename,nbins,emin,emax);
00059   if(!histo) return 0;
00060   TTree* Events = GetEventsTree(filename);
00061   if(!Events) return 0;
00062   //find the start/end time of the event
00063   double start = Events->GetMinimum("timestamp");
00064   double end = Events->GetMaximum("timestamp");
00065   //fit the peak
00066   double yield, yield_err;
00067   int error = FitPhotopeak(histo, epeak, yield, yield_err);
00068   if(gPad){
00069     gPad->Modified();
00070     gPad->Update();
00071     gSystem->ProcessEvents();
00072     gSystem->Sleep(100);
00073   }
00074   //histo->Delete();
00075   
00076   if(!error){
00077     //insert the results
00078     _x.push_back((end+start)/2.);
00079     _ex.push_back((end-start)/2.);
00080     _y.push_back(yield);
00081     _ey.push_back(yield_err);
00082     return 1;
00083   }
00084   return 0;
00085 }
00086   
00087 int LightYieldGraph::FitPhotopeak(TH1* h, double epeak, 
00088                                   double& yield, double& yield_err)
00089 {
00090   TSpectrum spec(1);
00091   spec.Search(h);
00092   double searchpoint = spec.GetPositionX()[0];
00093   
00094   h->GetXaxis()->SetTitle("Energy [photoelectrons]");
00095   h->Draw("e");
00096   h->GetYaxis()->SetRangeUser(0, 1.1*h->GetMaximum());
00097   TH1* bg = spec.Background(h);
00098   bg->SetBit(TObject::kCanDelete, true);
00099   TH1* sig = (TH1*)(h->Clone());
00100   sig->SetBit(TObject::kCanDelete,true);
00101   sig->SetLineColor(kGreen);
00102   
00103   sig->Add(bg,-1);
00104   sig->Draw("same e");
00105   sig->Fit("gaus","m","same e",searchpoint*0.8,searchpoint*1.2);
00106   TF1* gaus = sig->GetFunction("gaus");
00107   if(!gaus){
00108     cerr<<"There was a problem fitting the function!\n";
00109     return 1;
00110   }
00111   gaus->SetLineColor(kGreen);
00112   
00113   bg->SetLineColor(kRed);
00114   bg->Draw("same e");
00115   
00116   TLine* line = new TLine(gaus->GetParameter(1),0,
00117                           gaus->GetParameter(1),h->GetMaximum());
00118   line->SetLineColor(kBlue);
00119   line->SetLineWidth(2);
00120   line->Draw();
00121   
00122 
00123   yield = searchpoint/epeak;
00124   yield_err = 0;
00125   
00126   cout<<"Results from TSpectrum: \n\t"
00127       <<"Peak = "<<spec.GetPositionX()[0]<<" p.e.; Light Yield = "
00128       <<yield<<" p.e./keV"<<endl;
00129   if(gaus){
00130     yield = gaus->GetParameter(1)/epeak;
00131     yield_err = gaus->GetParError(1)/epeak;
00132     cout<<"Results from BG Subtracted Gaus Fit: \n\t"
00133         <<"Peak = "<<gaus->GetParameter(1)<<" p.e.; Light Yield = "
00134         <<yield<<" +/- "<<yield_err<<" p.e./keV"<<endl;
00135     yield_err = max(yield_err, TMath::Abs(yield-spec.GetPositionX()[0]/epeak));
00136     
00137   }
00138   TLegend* leg = new TLegend(.6,.6,.9,.9);
00139   leg->AddEntry(h,"Raw Spectrum","lpe");
00140   leg->AddEntry(bg,"Background","lpe");
00141   leg->AddEntry(sig,"Signal","lpe");
00142   char title[20];
00143   sprintf(title,"Yield = %.2f pe/keV",yield);
00144   leg->AddEntry(line, title ,"l");
00145   leg->Draw();
00146 
00147   gPad->Update();
00148   return 0;
00149 }
00150 
00151   
00152 TGraphErrors* LightYieldGraph::DrawGraph()
00153 {
00154   TGraphErrors* graph = new TGraphErrors(_x.size(),&_x[0], &_y[0],
00155                                          &_ex[0], &_ey[0]);
00156   graph->SetName("lightyieldgraph");
00157   graph->SetTitle("Light Yield vs Time");
00158   graph->Draw("ape");
00159   TAxis* xax = graph->GetXaxis();
00160   xax->SetTitle("Run Time");
00161   xax->SetTimeDisplay(1);
00162   xax->SetTimeFormat("%m/%d");
00163   xax->SetTimeOffset(1,"gmt");
00164   xax->SetNdivisions(710);
00165   TAxis* yax = graph->GetYaxis();
00166   yax->SetTitle("Light Yield [pe/keV]");
00167   yax->SetTitleOffset(1.2);
00168   graph->Draw("ape");
00169   return graph;
00170 }
00171 
00172 TGraphErrors* PlotNa22LightYield()
00173 {
00174   //define the list of runs
00175   //use only runs where the collimator is at midplane
00176   std::vector<int> runs;
00177   runs.push_back(311);
00178   runs.push_back(314);
00179   runs.push_back(331);
00180   runs.push_back(337);
00181   runs.push_back(340);
00182   runs.push_back(342);
00183   runs.push_back(348);
00184   runs.push_back(349);
00185   runs.push_back(350);
00186   runs.push_back(351);
00187   runs.push_back(352);  
00188   runs.push_back(353);  
00189   runs.push_back(354);  
00190   runs.push_back(355);  
00191   runs.push_back(356);  
00192   runs.push_back(357);  
00193   runs.push_back(358);  
00194   runs.push_back(364);  
00195   runs.push_back(365);  
00196   runs.push_back(385);  
00197   runs.push_back(388);  
00198   runs.push_back(392);  
00199   runs.push_back(395);  
00200   runs.push_back(416);  
00201   runs.push_back(423);
00202   runs.push_back(434);
00203   runs.push_back(498);  
00204   runs.push_back(506);  
00205   runs.push_back(508);  
00206   runs.push_back(523);  
00207   runs.push_back(542);  
00208   runs.push_back(547);  
00209   runs.push_back(552);  
00210   runs.push_back(553);  
00211   runs.push_back(554);  
00212   runs.push_back(555);  
00213   runs.push_back(556);  
00214   runs.push_back(557);  
00215   runs.push_back(565);  
00216   runs.push_back(567);  
00217   
00218   LightYieldGraph ly;
00219   ly.AddRuns(runs, 511., 200, 1000, 2500);
00220   TGraphErrors* e = ly.DrawGraph();
00221   DrawOperationsBoxes();
00222   return e;
00223 }
00224   
00225 enum SPEFUNC_PARAMS {PED_AMP=0, PED_SIGMA, SPE_AMP, SPE_MEAN, SPE_SIGMA, 
00226                      EXPO_AMP, EXPO_SLOPE, TWOPE_RATIO};
00227 
00228 double singlepe_fitfunc(double* x, double* par)
00229 {
00230   double ped_amp =        par[PED_AMP];
00231   double ped_sigma =      par[PED_SIGMA];
00232   double spe_amp =        par[SPE_AMP];
00233   double spe_mean =       par[SPE_MEAN];
00234   double spe_sigma =      par[SPE_SIGMA];
00235   double expo_amp =       par[EXPO_AMP];
00236   double expo_slope =     par[EXPO_SLOPE];
00237   double twope_ratio =    par[TWOPE_RATIO];
00238   
00239   return ped_amp * TMath::Gaus(*x, 0., ped_sigma) + 
00240     spe_amp * TMath::Gaus(*x, spe_mean, 
00241                           sqrt(ped_sigma*ped_sigma + spe_sigma*spe_sigma)) + 
00242     twope_ratio * spe_amp * TMath::Gaus(*x, 2.*spe_mean,
00243                           sqrt(ped_sigma*ped_sigma+2*spe_sigma*spe_sigma)) +
00244     expo_amp * exp(-(*x)/expo_slope);
00245 }
00246 
00247 int LightYieldGraph::SetAliasesFromLocalData(TTree* Events, bool draw)
00248 {
00249   //histogram parameters
00250   const int nbins = 120;
00251   const double xmin = 10;
00252   const double xmax = 250;
00253   //fill spectra of single photoelectrons in the single_pe vector
00254   std::map<int,TH1D*> spectra;
00255   EventData* event = 0;
00256   Events->SetBranchAddress("EventData", &event);
00257   std::cout<<"Finding single photoelectron spectra from "<<Events->GetEntries()
00258            <<" triggers."<<std::endl;
00259   for(int i=0; i < Events->GetEntries(); i++){
00260     Events->GetEntry(i);
00261     for(size_t ch=0; ch < event->channels.size(); ch++){
00262       ChannelData& chdata = event->channels[ch];
00263       int id = chdata.channel_id;
00264       if(id < 0) continue;
00265       if( spectra.find(id) == spectra.end()){
00266         //create a new histogram for this channel
00267         char name[100];
00268         sprintf(name, "spe_spectrum_%d",id);
00269         spectra[id] = new TH1D(name,name,nbins,xmin,xmax);
00270       }
00271       for(size_t spe=0; spe < chdata.single_pe.size(); spe++){
00272         spectra[id]->Fill(chdata.single_pe[spe].integral);
00273       }
00274     }
00275   }
00276   
00277   std::cout<<"Found spectra for "<<spectra.size()<<" channels"<<std::endl;
00278   std::map<int, TH1D*>::iterator it = spectra.begin();
00279   std::stringstream sumalias("");
00280   for(it = spectra.begin() ; it != spectra.end(); it++){
00281     // find the means of all the histograms
00282     TH1* hist = (it->second);
00283     TSpectrum spec(10,0.5);
00284     spec.Search(hist,2,"",0.02);
00285     int n = spec.GetNPeaks();
00286     float* x = spec.GetPositionX();
00287     float mean = *(std::min_element(x, x+n));
00288     
00289     TF1* fitfunc = (TF1*)(gROOT->GetFunction("spe_fitfunc"));
00290     if(!fitfunc)
00291       fitfunc = new TF1("spe_fitfunc",singlepe_fitfunc,xmin,xmax,8);
00292     fitfunc->SetParNames("PED_AMP","PED_SIGMA","SPE_AMP","SPE_MEAN","SPE_SIGMA",
00293                          "EXPO_AMP","EXPO_SLOPE", "TWOPE_RATIO");
00294     fitfunc->SetParameters(hist->GetBinContent(1),
00295                            5.,
00296                            hist->GetBinContent(hist->FindBin(mean)),
00297                            mean,
00298                            mean/3.,
00299                            100,
00300                            10,
00301                            0.01);
00302     fitfunc->SetParLimits(PED_AMP,0,hist->GetEntries());
00303     fitfunc->SetParLimits(PED_SIGMA,0,40);
00304     fitfunc->SetParLimits(SPE_AMP,hist->GetEntries()/10000.,2.*hist->GetEntries());
00305     fitfunc->SetParLimits(SPE_MEAN,xmin,xmax);
00306     fitfunc->SetParLimits(SPE_SIGMA,0,xmax);
00307     fitfunc->SetParLimits(EXPO_AMP,0, hist->GetBinContent(1));
00308     fitfunc->SetParLimits(EXPO_SLOPE,0,2.*xmax);
00309     fitfunc->SetParLimits(TWOPE_RATIO,0,0.5);
00310     fitfunc->SetLineColor(kBlue);
00311     hist->Fit(fitfunc,"QM");                    
00312     
00313     mean = fitfunc->GetParameter(SPE_MEAN);
00314     //store the results
00315     _chan_spe[(it->first)].push_back(mean);
00316     _chan_spe_err[(it->first)].push_back(fitfunc->GetParError(SPE_MEAN));
00317     
00318     
00319     TLine* line = new TLine(mean,1,mean,fitfunc->GetParameter(SPE_AMP));
00320     line->SetLineColor(kGreen);
00321     line->SetLineWidth(2);
00322     hist->GetListOfFunctions()->Add(line);
00323     
00324     if(!sumalias.str().empty())
00325       sumalias<<"+";
00326     std::stringstream aliasname(""), aliasdef("");
00327     aliasname<<"npe"<<(it->first);
00328     sumalias<<aliasname.str();
00329     aliasdef<<"(-channels["<<(it->first)<<"].regions[1].integral/"<<mean<<")";
00330     std::cout<<"Setting alias "<<aliasname.str()<<" = "<<aliasdef.str()
00331              <<std::endl;
00332     Events->SetAlias(aliasname.str().c_str(), aliasdef.str().c_str());
00333   }
00334   Events->SetAlias("sumspec",sumalias.str().c_str());
00335 
00336   if(draw){  
00337     if(!gPad) new TCanvas;
00338     //go to the top level
00339     while(gPad->GetMother() != gPad) gPad->GetMother()->cd();
00340     TCanvas* can = (TCanvas*)gPad;
00341     can->Clear();
00342     DividePad(can, spectra.size());
00343     it = spectra.begin();
00344     for(size_t i=0; i < spectra.size(); i++){
00345       can->cd(i+1);
00346       TH1D* hist = it->second;
00347       hist->Draw();
00348       gPad->SetLogy();
00349       //gPad->Update();
00350       it++;
00351     }
00352     can->cd(0);
00353     can->Modified();
00354     can->Update();
00355     //std::string dummy;
00356     //std::cout<<"Press <enter> to continue"<<std::endl;
00357     //std::getline(std::cin, dummy);
00358   }
00359   for(it = spectra.begin(); it != spectra.end(); it++){
00360     delete (it->second);
00361   }
00362   return 0;
00363 }
00364 
00365 TH1* LightYieldGraph::DrawSpectrum(const char* filename, int nbins, 
00366                                    double xmin, double xmax)
00367 {
00368   TTree* Events = GetEventsTree(filename);
00369   if(!Events)
00370     return 0;
00371   SetAliasesFromLocalData(Events,true);
00372   TString title=TString("Spectrum, ") + 
00373     TString(filename)(TRegexp("Run......"));
00374   TH1D* hist = new TH1D("spectrum",title, nbins, xmin, xmax);
00375   Events->Draw("sumspec>>spectrum","!saturated && channels[].baseline.found_baseline","e");
00376   hist->GetXaxis()->SetTitle("Energy [photoelectrons]");
00377   return hist;
00378 }
00379 
00380 TGraphErrors* LightYieldGraph::DrawChannelSpeGraph(int channel)
00381 {
00382   //assume our graphs have the same number of points...
00383   TGraphErrors* graph = new TGraphErrors(_x.size(), &_x[0], &(_chan_spe[channel][0]),
00384                                          &_ex[0], &(_chan_spe_err[channel][0]));
00385   char name[100];
00386   sprintf(name, "spegraph%d", channel);
00387   graph->SetName(name);
00388   sprintf(name, "SPE Mean vs Time for Channel %d",channel);
00389   graph->SetTitle(name);
00390   graph->Draw("ape");
00391   TAxis* xax = graph->GetXaxis();
00392   xax->SetTitle("Run Time");
00393   xax->SetTimeDisplay(1);
00394   xax->SetTimeFormat("%m/%d");
00395   xax->SetTimeOffset(1,"gmt");
00396   xax->SetNdivisions(710);
00397   TAxis* yax = graph->GetYaxis();
00398   yax->SetTitle("SPE Mean [counts*samples]");
00399   yax->SetTitleOffset(1.2);
00400   graph->Draw("ape");
00401   return graph;
00402 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on 20 Jun 2014 for daqman by  doxygen 1.6.1