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
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
00063 double start = Events->GetMinimum("timestamp");
00064 double end = Events->GetMaximum("timestamp");
00065
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
00075
00076 if(!error){
00077
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
00175
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
00250 const int nbins = 120;
00251 const double xmin = 10;
00252 const double xmax = 250;
00253
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
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
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
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
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
00350 it++;
00351 }
00352 can->cd(0);
00353 can->Modified();
00354 can->Update();
00355
00356
00357
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
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 }