00001 #include "utilities.hh"
00002 #include "EventData.hh"
00003
00004 #include "TFile.h"
00005 #include "TString.h"
00006 #include "TTree.h"
00007 #include "TGraph.h"
00008 #include "TGraphErrors.h"
00009 #include "TROOT.h"
00010 #include "TSeqCollection.h"
00011 #include "TMath.h"
00012 #include "TPad.h"
00013 #include "TBox.h"
00014 #include "TPave.h"
00015 #include "TTimeStamp.h"
00016 #include "TH1.h"
00017 #include "TH2.h"
00018 #include "TF1.h"
00019 #include "TH1F.h"
00020 #include "TH1D.h"
00021 #include "TProfile.h"
00022 #include "TPaveText.h"
00023 #include "TSystem.h"
00024 #include "TClass.h"
00025 #include "TList.h"
00026 #include "TClassMenuItem.h"
00027
00028
00029
00030 #include "TGFileDialog.h"
00031
00032 #include "Reader.hh"
00033 #include "EventHandler.hh"
00034 #include "ConvertData.hh"
00035
00036 #include <algorithm>
00037 #include <numeric>
00038 #include <iostream>
00039 #include <fstream>
00040 #include <sstream>
00041 #include <iomanip>
00042 using namespace std;
00043
00044 TFile* OpenFile(const char* filename, const char* option)
00045 {
00046
00047 TSeqCollection* files = gROOT->GetListOfFiles();
00048 for(int i=0; i< files->GetSize(); i++){
00049 if( TString(files->At(i)->GetName()) == TString(filename))
00050 return (TFile*)(files->At(i));
00051 }
00052
00053
00054 TFile* f = new TFile(filename,option);
00055 if(!f || !f->IsOpen() || f->IsZombie()){
00056 cerr<<"Unable to open file "<<filename<<endl;
00057 return 0;
00058 }
00059 return f;
00060 }
00061
00062 TTree* GetEventsTree(const char* filename)
00063 {
00064 TFile* f = OpenFile(filename);
00065 if(!f)
00066 return 0;
00067 TTree* Events = (TTree*)(f->Get("Events"));
00068 if(!Events){
00069 cerr<<"Unable to open Events tree from file "<<filename<<endl;
00070 return 0;
00071 }
00072 return Events;
00073 }
00074
00075 TGraph* GetAverageGraph(const char* filename, int channel)
00076 {
00077 TFile* f = OpenFile(filename);
00078 if(!f)
00079 return 0;
00080 TString name = "average_channel";
00081 name += channel;
00082 TGraph* g = (TGraph*)(f->Get(name));
00083 if(!g){
00084 cerr<<"Unable to open graph "<<name<<" from file "<<filename<<endl;
00085 return 0;
00086 }
00087 return g;
00088 }
00089
00090 TGraphErrors* GetAverageGraph(int run_no, int channel) {
00091 std::string run;
00092 std::stringstream out;
00093 out << run_no;
00094 run = out.str();
00095 std::string filename(6-run.size(), '0');
00096 filename = "/data/s1waveform/Run" + filename + run + ".root";
00097
00098 return (TGraphErrors*) GetAverageGraph(filename.c_str(), channel);
00099 }
00100
00101 int DividePad(TPad* p, int nplots)
00102 {
00103 int npadsx = 1, npadsy=1;
00104 if( nplots < 2)
00105 {}
00106 else if( nplots == 2)
00107 npadsx=2;
00108 else if (nplots < 5){
00109 npadsx=2; npadsy=2;
00110 }
00111 else if(nplots < 7){
00112 npadsx=3; npadsy=2;
00113 }
00114 else if(nplots < 10){
00115 npadsx=3; npadsy=3;
00116 }
00117 else if(nplots < 13){
00118 npadsx=4, npadsy=3;
00119 }
00120 else if(nplots < 17){
00121 npadsx=4; npadsy=4;
00122 }
00123 else{
00124 npadsx=(int)TMath::Ceil(sqrt(nplots));
00125 npadsy=(int)TMath::Ceil(sqrt(nplots));
00126 }
00127 p->Divide(npadsx,npadsy);
00128 return npadsx*npadsy;
00129 }
00130
00131 int explode_string(const std::string& s, char delim,
00132 std::vector<std::string>& out)
00133 {
00134
00135 size_t start = 0;
00136 while(1){
00137 size_t end = s.find(delim,start);
00138 if(end == std::string::npos)
00139 break;
00140 out.push_back(s.substr(start, end-start));
00141 start = end+1;
00142 }
00143 out.push_back(s.substr(start,std::string::npos));
00144 return out.size();
00145 }
00146
00147 std::vector<std::string> explode_cut(const TCut& cut)
00148 {
00149 std::vector<std::string> out;
00150
00151
00152 std::string s = cut.GetTitle();
00153 size_t pos = 0;
00154 int prev = 0;
00155 while(pos < s.size() && pos != std::string::npos){
00156
00157 pos = s.find(")&&",pos);
00158 if(pos == std::string::npos) pos = s.size()-1;
00159
00160 int open = 0;
00161 int pos2 = pos;
00162 while(--pos2 > prev){
00163 if(s[pos2] == ')') ++open;
00164 else if(s[pos2] == '('){
00165 if(open == 0) break;
00166 else --open;
00167 }
00168 }
00169 out.push_back(s.substr(pos2+1,pos-pos2-1-open));
00170 ++pos;
00171 prev = pos+2;
00172 }
00173 return out;
00174 }
00175
00176 void DrawOperationsBoxes(bool drawbubble, bool drawrecirc)
00177 {
00178 double dummy, y1, y2;
00179 gPad->Update();
00180 gPad->GetRangeAxis(dummy,y1,dummy,y2);
00181
00182 if(drawbubble){
00183 double x1[] = { TTimeStamp(2010,04,15,11,06,55,0,0).GetSec(),
00184 TTimeStamp(2010,05,03,15,51,33,0,0).GetSec(),
00185 TTimeStamp(2010,05,05,10,54,19,0,0).GetSec(),
00186 TTimeStamp(2010,05,05,15,57,33,0,0).GetSec()
00187 };
00188 double x2[] = { TTimeStamp(2010,04,15,16,38,48,0,0).GetSec(),
00189 TTimeStamp(2010,05,03,20,40,28,0,0).GetSec(),
00190 TTimeStamp(2010,05,05,13,29,44,0,0).GetSec(),
00191 TTimeStamp(2010,05,05,18,45,53,0,0).GetSec()
00192 };
00193
00194 for(size_t i = 0; i < sizeof(x1)/sizeof(double); i++){
00195 TBox b(x1[i], y1, x2[i], y2);
00196 b.SetFillStyle(3002);
00197 b.SetFillColor(kRed);
00198 b.DrawClone();
00199 }
00200 }
00201 if(drawrecirc){
00202 double x1[] = { TTimeStamp(2010,05,07,15,40,32,0,0).GetSec(),
00203 TTimeStamp(2010,07,14,17,23,00,0,0).GetSec()
00204 };
00205 double x2[] = { TTimeStamp(2010,05,07,23,59,59,0,0).GetSec(),
00206 TTimeStamp(2010,07,15,16,27,21,0,0).GetSec()
00207 };
00208 for(size_t i = 0; i < sizeof(x1)/sizeof(double); i++){
00209 TBox b(x1[i], y1, x2[i], y2);
00210 b.SetFillStyle(3002);
00211 b.SetFillColor(kBlue);
00212 b.DrawClone();
00213 }
00214 }
00215 }
00216
00217 double GetBaseline(TGraph* g, int npts, bool subtract)
00218 {
00219 double* gy = g->GetY();
00220 double baseline = accumulate(gy,gy+npts,0.)/(1.*npts);
00221 if(subtract){
00222 for(int i=0; i < g->GetN(); i++) gy[i] -= baseline;
00223 }
00224 return baseline;
00225 }
00226
00227 TGraph* GetRealEvent(const char* filename, int eventnum, int channel)
00228 {
00229 Reader reader(filename);
00230 if(!reader.IsOk()){
00231 std::cerr<<"Unable to open file "<<filename<<std::endl;
00232 return 0;
00233 }
00234
00235 EventHandler* handler = EventHandler::GetInstance();
00236 handler->AddModule<ConvertData>();
00237 handler->Initialize();
00238 RawEventPtr event = reader.GetEventWithID(eventnum);
00239 if(event == RawEventPtr()){
00240 std::cerr<<"Unable to load event with id "<<eventnum<<std::endl;
00241 return 0;
00242 }
00243 handler->Process(event);
00244 EventPtr evt = handler->GetCurrentEvent();
00245 handler->Finalize();
00246
00247 ChannelData* chdata = evt->GetEventData()->GetChannelByID(channel);
00248 if(!chdata){
00249 std::cerr<<"Unable to load data for channel "<<channel<<std::endl;
00250 return 0;
00251 }
00252 return chdata->GetTGraph();
00253 }
00254
00255 ChannelData* GetChannelData(const char* filename, int eventnum, int channel)
00256 {
00257 Reader reader(filename);
00258 if(!reader.IsOk()){
00259 std::cerr<<"Unable to open file "<<filename<<std::endl;
00260 return 0;
00261 }
00262
00263 EventHandler* handler = EventHandler::GetInstance();
00264 handler->AddModule<ConvertData>();
00265 handler->Initialize();
00266
00267 ChannelData* chdata = 0;
00268
00269 while(reader.IsOk() && !reader.eof()){
00270 RawEventPtr event = reader.GetEventWithID(eventnum++);
00271 if(event == RawEventPtr()){
00272 std::cerr<<"Unable to load event with id "<<eventnum<<std::endl;
00273 return 0;
00274 }
00275 if(eventnum%5000 == 0)
00276 Message(INFO)<<"Processing event "<<eventnum<<std::endl;
00277
00278 handler->Process(event);
00279 }
00280 EventPtr evt = handler->GetCurrentEvent();
00281 handler->Finalize();
00282
00283 chdata = evt->GetEventData()->GetChannelByID(channel);
00284 if(!chdata){
00285 std::cerr<<"Unable to load data for channel "<<channel<<std::endl;
00286 return 0;
00287 }
00288
00289 return chdata;
00290 }
00291
00292 double CorrelationCoefficient(int npts, double* x, double* y)
00293 {
00294 double sumx=0, sumy=0, sumx2=0, sumy2=0, sumxy=0;
00295 for(int i=0; i< npts; i++){
00296 sumx += x[i];
00297 sumy += y[i];
00298 sumx2 += x[i]*x[i];
00299 sumy2 += y[i]*y[i];
00300 sumxy += x[i]*y[i];
00301 }
00302
00303 return (npts * sumxy - sumx*sumy) /
00304 ( sqrt(npts*sumx2 - sumx*sumx) * sqrt(npts*sumy2 - sumy*sumy) );
00305 }
00306
00307 TCut GetStandardCuts()
00308 {
00309 TCut energy_min = "event.s1_full>50";
00310 TCut energy_max = "event.s1_full < 10000";
00311 TCut saturated = "!event.saturated";
00312
00313 TCut s1length = "GetPulse(0)->end_time-GetPulse(0)->start_time<20";
00314 TCut baseline = "GetChannelByID(-2)->baseline.found_baseline";
00315 TCut p0start = "GetPulse(0)->start_time < 0.1 && GetPulse(0)->start_time > -0.1";
00316 TCut status = "event.status==0";
00317 return energy_min + energy_max + saturated + s1length + baseline + p0start+status;
00318 }
00319
00320 TCut GetTwoPulseCuts()
00321 {
00322 TCut drift="event.drift_time>20";
00323 TCut s2 = "event.s2_full>10";
00324 TCut t95="GetPulse(1).t95>10 && GetPulse(1).t95<30";
00325 TCut valid = "event.s1s2_fixed_valid";
00326 return GetStandardCuts()+drift+s2+t95+valid;
00327 }
00328
00329 TCut GetOnePulseCuts(bool onlyone)
00330 {
00331 TCut base = GetStandardCuts()+"event.s1_fixed_valid";
00332 if(onlyone)
00333 base += "GetChannelByID(-2)->npulses == 1";
00334 return base;
00335 }
00336
00337 TCanvas* TwoPulsePlots(TTree* Events, bool queryfit, TCut cuts,TCanvas* c)
00338 {
00339 TCut all_cuts=cuts+GetTwoPulseCuts();
00340 c->Clear();
00341 c->Divide(3,2);
00342
00343 EventData* evt=0;
00344 Events->SetBranchAddress("event",&evt);
00345 Events->GetEntry(0);
00346 if(evt){
00347 int first_run = evt->run_id;
00348 stringstream cantitle;
00349 cantitle<<"Run "<<first_run;
00350 Events->GetEntry(Events->GetEntries()-1);
00351 if(evt->run_id != first_run)
00352 cantitle<<" - Run "<<evt->run_id;
00353 c->SetTitle(cantitle.str().c_str());
00354 }
00355 bool plotlog = true;
00356
00357 c->cd(1);
00358 if(plotlog){
00359 Events->Draw("log(event.s2_full/event.s1_full) : drift_time",
00360 all_cuts+"event.f90_full < 0.5","colz");
00361 }
00362 else{
00363 Events->Draw("(event.s2_full/event.s1_full) : drift_time",
00364 all_cuts+"event.f90_full < 0.5","colz");
00365 }
00366 TH1* htemp = (TH1*)gROOT->FindObject("htemp");
00367 double tau = 1000000.;
00368 if(htemp){
00369 htemp->SetName("hraw");
00370 htemp->SetTitle("Ln(S2/S1) vs Drift Time");
00371 htemp->GetXaxis()->SetTitle("Drift time [#mus]");
00372 htemp->GetYaxis()->SetTitle("Ln(S2/S1)");
00373
00374 TGraph* pf = (TGraph*)gROOT->FindObject("Graph");
00375 pf->SetName("gscatter");
00376
00377
00378 if(pf){
00379 const char* fitfunc = (plotlog ? "pol1" : "expo");
00380 double fitmin=50, fitmax = 120;
00381 if(queryfit){
00382 gPad->Update();
00383 std::cout<<"Enter '<min> <max>' range to fit lifetime:"<<std::endl;
00384 std::cin>>fitmin>>fitmax;
00385 }
00386 pf->Fit(fitfunc,"q","same",fitmin, fitmax);
00387 TF1* pol1 = pf->GetFunction(fitfunc);
00388 if(pol1){
00389 pol1->SetLineColor(kRed);
00390 pol1->Draw("same");
00391 tau = -1./pol1->GetParameter(1);
00392 TPaveText* pt = new TPaveText(0.1,0.1,0.9,0.3,"NDC");
00393 pt->SetBorderSize(0);
00394 stringstream text;
00395 text<<"Lifetime = "<<(int)tau<<"#pm"
00396 <<(int)(tau*tau*pol1->GetParError(1))
00397 <<" #mus";
00398 pt->AddText(text.str().c_str());
00399 text.str("");
00400 text<<std::setiosflags(std::ios::fixed)<<setprecision(2);
00401 text<<"Intercept = "<<pol1->GetParameter(0)<<"#pm"
00402 <<pol1->GetParError(0);
00403 pt->AddText(text.str().c_str());
00404 pt->Draw();
00405 }
00406 }
00407 }
00408 stringstream alias;
00409 alias<<"exp(event.drift_time/"<<tau<<")*event.s2_full / event.s1_full";
00410 Events->SetAlias("ratio_corrected",alias.str().c_str());
00411
00412 c->cd(2);
00413 Events->Draw("log(ratio_corrected) : drift_time",
00414 all_cuts,"colz");
00415 htemp = (TH1*)gROOT->FindObject("htemp");
00416 if(htemp){
00417 htemp->SetName("hcorrected");
00418 htemp->SetTitle("Ln(S2/S1) Corrected vs Drift Time");
00419 htemp->GetXaxis()->SetTitle("Drift time [#mus]");
00420 htemp->GetYaxis()->SetTitle("Ln(S2/S1) Corrected");
00421
00422 }
00423 c->cd(3);
00424 Events->Draw("log10(ratio_corrected):event.f90_full>>hscatter(100,0,1,100,-3,3)",
00425 all_cuts,"colz");
00426 htemp = (TH1*)gROOT->FindObject("hscatter");
00427 if(htemp){
00428 htemp->SetName("hscatter1");
00429 htemp->SetTitle("Log(S2/S1) vs F90");
00430 htemp->GetXaxis()->SetTitle("F90");
00431 htemp->GetYaxis()->SetTitle("Log10(S2/S1) corrected for drift");
00432 gPad->SetLogz();
00433 }
00434 c->cd(4);
00435 Events->Draw("event.drift_time ",
00436 all_cuts);
00437 htemp = (TH1*)gROOT->FindObject("htemp");
00438 if(htemp){
00439 htemp->SetName("hdt");
00440 htemp->Rebin(2);
00441 htemp->SetTitle("Drift Time");
00442 htemp->GetXaxis()->SetTitle("drift time [#mus]");
00443 }
00444 c->cd(5);
00445 Events->Draw("log10(ratio_corrected)>>hratiolow(100,-3,3)",
00446 "event.f90_full>0 && event.f90_full<0.55"+all_cuts);
00447 htemp = (TH1*)gROOT->FindObject("hratiolow");
00448 if(htemp){
00449 htemp->SetName("hratiolow1");
00450 htemp->SetTitle("Log10(S2/S1) corrected");
00451 htemp->GetXaxis()->SetTitle("Log10(S2/S1) corrected");
00452 }
00453 Events->Draw("log10(ratio_corrected)>>hratiohigh(100,-3,3)",
00454 "event.f90_full>0.55 && event.f90_full<1"+all_cuts,"sames");
00455 htemp = (TH1*)gROOT->FindObject("hratiohigh");
00456 if(htemp){
00457 htemp->SetName("hratiohigh1");
00458 htemp->SetLineColor(kRed);
00459 htemp->SetTitle("F90>0.55");
00460 gPad->SetLogy();
00461 }
00462
00463
00464 c->cd(6);
00465 Events->Draw("event.y : event.x " ,
00466 "event.position_valid" + all_cuts);
00467 htemp = (TH1*)gROOT->FindObject("htemp");
00468 if(htemp){
00469 htemp->SetName("hxy");
00470 htemp->SetTitle("Event Position");
00471 htemp->GetXaxis()->SetTitle("X [cm]");
00472 htemp->GetYaxis()->SetTitle("Y [cm]");
00473 }
00474
00475
00476
00477 c->cd(0);
00478 c->Modified();
00479 c->Update();
00480 return c;
00481
00482 }
00483
00484 TCanvas* OnePulsePlots(TTree* Events, TCut cuts,TCanvas* c)
00485 {
00486 TCut all_cuts = cuts+GetOnePulseCuts();
00487 EventData* evt=0;
00488 Events->SetBranchAddress("event",&evt);
00489 Events->GetEntry(0);
00490 if(evt){
00491 int first_run = evt->run_id;
00492 stringstream cantitle;
00493 cantitle<<"Run "<<first_run;
00494 Events->GetEntry(Events->GetEntries()-1);
00495 if(evt->run_id != first_run)
00496 cantitle<<" - Run "<<evt->run_id;
00497 c->SetTitle(cantitle.str().c_str());
00498 }
00499
00500 c->Divide(2,2);
00501 c->cd(1);
00502 Events->Draw("event.s1_full>>hspec(200,0,4000)", all_cuts);
00503 TH1* htemp = (TH1*)gROOT->FindObject("hspec");
00504 if(htemp){
00505 htemp->SetTitle("Energy Spectrum");
00506 htemp->GetXaxis()->SetTitle("Energy [npe]");
00507 }
00508 c->cd(3);
00509 Events->Draw("event.f90_full:event.s1_full>>hfe(50,0,4000,50,0,1)",
00510 all_cuts, "colz");
00511 htemp = (TH1*)gROOT->FindObject("hfe");
00512 if(htemp){
00513 htemp->SetTitle("f90 vs Energy");
00514 htemp->GetXaxis()->SetTitle("Energy [npe]");
00515 htemp->GetYaxis()->SetTitle("f90");
00516 }
00517 c->cd(4);
00518 Events->Draw("event.f90_full>>hf90(100,0,1)",all_cuts);
00519 htemp = (TH1*)gROOT->FindObject("hf90");
00520 if(htemp){
00521 htemp->SetTitle("f90");
00522 htemp->GetXaxis()->SetTitle("f90");
00523 }
00524 return c;
00525 }
00526
00527 TCanvas* PlotSpeDistributions(TTree* Events, bool normalize)
00528 {
00529 if(!Events) return 0;
00530
00531 EventData* evt = 0;
00532 Events->SetBranchAddress(EventData::GetBranchName(), &evt);
00533 Events->GetEntry(0);
00534
00535
00536
00537
00538
00539 int nchans = (int)Events->GetMaximum("nchans");
00540 TCanvas* can = new TCanvas;
00541 DividePad(can,nchans);
00542 for(int i=0; i<nchans; i++){
00543 can->cd(i+1);
00544 std::stringstream cmd;
00545 cmd<<"channels["<<i<<"].single_pe.integral";
00546 if(normalize)
00547 cmd<<"/channels["<<i<<"].spe_mean>>h"<<i<<"(100,0,3)";
00548 else
00549 cmd<<">>h"<<i<<"(100,0,"<<3*evt->channels[i].spe_mean<<")";
00550 Long64_t entries = Events->Draw(cmd.str().c_str(),"");
00551
00552 gPad->Update();
00553 double x = (normalize ? 1 : evt->channels[i].spe_mean);
00554 double y = gPad->GetY2();
00555 TLine* line = new TLine(x, 0, x, y);
00556 line->SetLineColor(kBlue);
00557 line->Draw();
00558
00559
00560 if(entries)
00561 gPad->SetLogy();
00562
00563
00564 }
00565 can->cd(0);
00566 return can;
00567 }
00568
00569
00570 double ElectronLifetime(TTree* Events, bool newcanvas, bool defaultlimits)
00571 {
00572 if(newcanvas) new TCanvas;
00573 Events->Draw("event.s2_full/event.s1_full : event.drift_time >>hprof",
00574 GetTwoPulseCuts()+"event.f90_full<0.5","prof");
00575 TProfile* hprof = (TProfile*)gROOT->FindObject("hprof");
00576 double min = 50, max = 120;
00577 gPad->Update();
00578
00579 if(!defaultlimits){
00580 std::cout<<"Enter fit limits:"<<std::endl;
00581 std::cin>>min>>max;
00582 }
00583 hprof->Fit("expo","MIQ","",min,max);
00584 TF1* expo = hprof->GetFunction("expo");
00585 double tau = -1./expo->GetParameter(1);
00586
00587
00588
00589 return tau;
00590
00591
00592 }
00593
00594 void SaveHistoToFile(TObject* c)
00595 {
00596 if(!c->InheritsFrom("TH1"))
00597 return;
00598 TH1* h = (TH1*)c;
00599 static const char* filetypes[] = {
00600 "Text files","*.txt",
00601 0,0
00602 };
00603 TGFileInfo fi;
00604 fi.fFileTypes = filetypes;
00605 new TGFileDialog(gClient->GetRoot(),0,kFDSave,&fi);
00606 if(!fi.fFilename)
00607 return;
00608 std::string fname = fi.fFilename;
00609 if(fname.rfind(".txt")==std::string::npos)
00610 fname.append(".txt");
00611 std::cout<<"Saving histogram "<<h->GetName()<<" to file "<<fname<<std::endl;
00612 std::ofstream fout(fname.c_str());
00613 if(fout.is_open()){
00614 fout<<"#X\tY\tYerr\n";
00615 for(int i=1; i<=h->GetNbinsX(); ++i){
00616 fout<<h->GetBinLowEdge(i)<<"\t"
00617 <<h->GetBinContent(i)<<"\t"
00618 <<h->GetBinError(i)
00619 <<endl;
00620 }
00621 }
00622 }
00623
00624 void CustomizeHistogramMenus()
00625 {
00626
00627
00628 TClass* cl = TH1F::Class();
00629 TList* l = cl->GetMenuList();
00630 l->AddFirst(new TClassMenuItem(TClassMenuItem::kPopupUserFunction,cl,
00631 "Save as ASCII","SaveHistoToFile",0,
00632 "TObject*",0));
00633
00634 cl = TH1D::Class();
00635 l = cl->GetMenuList();
00636 l->AddFirst(new TClassMenuItem(TClassMenuItem::kPopupUserFunction,cl,
00637 "Save as ASCII","SaveHistoToFile",0,
00638 "TObject*",0));
00639
00640
00641 }