1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
17 // class to calculate TRD dEdx
24 // lu@physi.uni-heidelberg.de
34 #include "THnSparse.h"
38 #include "TObjArray.h"
40 #include "TStopwatch.h"
43 #include "TTreeStream.h"
46 #include "AliCDBMetaData.h"
47 #include "AliCDBStorage.h"
48 #include "AliESDEvent.h"
49 #include "AliESDfriendTrack.h"
50 #include "AliESDtrack.h"
51 #include "AliTRDcalibDB.h"
52 #include "AliTRDCalROC.h"
53 #include "AliTRDtrackV1.h"
55 #include "AliTRDdEdxBaseUtils.h"
56 #include "AliTRDdEdxReconUtils.h"
57 #include "AliTRDdEdxCalibHistArray.h"
58 #include "AliTRDdEdxCalibUtils.h"
62 AliTRDdEdxCalibHistArray * AliTRDdEdxCalibUtils::fgHistArray = 0x0;
63 TObjArray * AliTRDdEdxCalibUtils::fgObjArray = 0x0;
65 //============================================================
67 //============================================================
68 TObjArray * AliTRDdEdxCalibUtils::GetObjArray()
71 //return fgObjArray, initialized if null
75 fgObjArray = new TObjArray(8);
81 TObjArray * AliTRDdEdxCalibUtils::GetObj(const Bool_t kinvq, const Double_t mag, const Int_t charge)
87 printf("AliTRDdEdxCalibUtils::GetObjArray(kinvq, mag, charge) error fgObjArray null!!\n"); exit(1);
90 return (TObjArray*) fgObjArray->At(AliTRDdEdxCalibHistArray::GetIterator(kinvq, mag, charge));
93 void AliTRDdEdxCalibUtils::DeleteObjArray()
99 fgObjArray->SetOwner();
105 Bool_t AliTRDdEdxCalibUtils::GenerateDefaultOCDB(const TString path)
108 //generate default OCDB object PHQ, do like
109 //AliTRDdEdxCalibUtils::GenerateDefaultPHQOCDB("local://./")
112 TObjArray * arr8 = new TObjArray(8);
115 for(Int_t ii=0; ii<8; ii++){
116 TObjArray * arr1 = new TObjArray(1);
118 TString objn(AliTRDdEdxCalibHistArray::GetNameAt(ii));
119 objn.ReplaceAll("Hist","Obj");
122 const Int_t nbins = AliTRDdEdxBaseUtils::NTRDtimebin();
123 TVectorD * vec = new TVectorD(nbins);
124 for(Int_t jj=0; jj<nbins; jj++){
131 AliCDBMetaData *metaData= new AliCDBMetaData();
132 metaData->SetObjectClassName("TObjArray");
133 metaData->SetResponsible("Raphaelle Bailhache and Xianguo Lu");
135 AliCDBId id1("TRD/Calib/PHQ", 0, 999999999);
136 AliCDBStorage * gStorage = AliCDBManager::Instance()->GetStorage(path);
137 gStorage->Put(arr8, id1, metaData);
145 //============================================================
147 //============================================================
148 void AliTRDdEdxCalibUtils::DeleteHistArray()
157 THnBase * AliTRDdEdxCalibUtils::GetHistAt(const Int_t iter)
162 if(iter<fgHistArray->GetSize())
163 return (THnBase*)fgHistArray->At(iter);
168 void AliTRDdEdxCalibUtils::IniHistArray(TList *list, const Bool_t kNoInv)
171 //initialize calib hist, list should not own the hist, or list->Clear/delete hist should not be called
175 fgHistArray = new AliTRDdEdxCalibHistArray(kNoInv);
176 list->Add(fgHistArray);
179 Bool_t AliTRDdEdxCalibUtils::ReadHistArray(const TString filename, const TString listname)
182 //used in AliTRDPreprocessorOffline
183 //read in calib hist from file, only for PHQ
186 //maybe already open by others... don't close
187 TFile fcalib(filename);
188 TObjArray * array = (TObjArray*)fcalib.Get(listname);
189 const TString histname = AliTRDdEdxCalibHistArray::GetArrayName();
191 AliTRDdEdxCalibHistArray * tmph=0x0;
193 tmph = (AliTRDdEdxCalibHistArray *) array->FindObject(histname);
196 tmph = (AliTRDdEdxCalibHistArray *) fcalib.Get(histname);
199 printf("AliTRDdEdxCalibUtils::ReadCalibHist warning calib hist not found! %s %s %s\n", filename.Data(), listname.Data(), histname.Data());
208 fgHistArray = new AliTRDdEdxCalibHistArray(*tmph);
213 void AliTRDdEdxCalibUtils::FillHist(const Int_t ncls, const TVectorD *arrayQ, const TVectorD *arrayX, THnBase * hcalib, const Double_t scale)
216 //fill calibration hist
218 if(!hcalib){printf("AliTRDdEdxCalibUtils::FillCalibHist errro hcalib null!!\n"); exit(1);}
220 for(Int_t ii=0; ii<ncls; ii++){
221 Double_t dq = (*arrayQ)[ii]/scale;
222 const Double_t qmin = hcalib->GetAxis(1)->GetXmin() +0.5 * hcalib->GetAxis(1)->GetBinWidth(1);
223 const Double_t qmax = hcalib->GetAxis(1)->GetXmax() -0.5 * hcalib->GetAxis(1)->GetBinWidth(1);
230 const Double_t xx = (*arrayX)[ii];
231 const Double_t xmin = hcalib->GetAxis(0)->GetXmin();
232 const Double_t xmax = hcalib->GetAxis(0)->GetXmax();
234 if(xx>=xmax || xx<xmin){
235 printf("AliTRDdEdxCalibUtils::FillCalibHist error x overflow or underflow! %s %15f %15f %15f\n", hcalib->GetName(), xx, xmin, xmax); exit(1);
238 const Double_t var[]={xx, dq};
243 void AliTRDdEdxCalibUtils::FillHist(const AliTRDtrackV1 *trdv1, const Bool_t kinvq, const Double_t mag, const Int_t charge, const Double_t scale)
246 //get cluster Q and fill calib hist, if kinvq = kTRUE, 1/Q is filled
249 printf("AliTRDdEdxCalibUtils::FillHist fgHistArray not initialized!!\n"); exit(1);
252 THnBase * hcalib = fgHistArray->GetHist(kinvq, mag, charge);
254 TVectorD arrayQ(200), arrayX(200);
255 const Int_t ncls = AliTRDdEdxReconUtils::GetArrayClusterQ(kinvq, &arrayQ, &arrayX, trdv1);
256 FillHist(ncls, &arrayQ, &arrayX, hcalib, kinvq ? 1/scale : scale);
258 static Int_t kprint = 100;
260 printf("\nAliTRDdEdxCalibUtils::FillHist summary: \n");
261 printf("\nkinvq= %d;\n", kinvq);
262 for(Int_t iq=0; iq<ncls; iq++){
263 printf("arrayX[%3d] = %15.0f; arrayQ[%3d] = %15f;\n", iq, arrayX[iq], iq, arrayQ[iq]);
270 //============================================================
272 //============================================================
274 Double_t AliTRDdEdxCalibUtils::GetCalibTPCscale(const Int_t tpcncls, const Double_t tpcsig)
277 //the scale used in calibration
280 if(tpcncls < AliTRDdEdxBaseUtils::CalibTPCnclsCut())
290 void AliTRDdEdxCalibUtils::GetPHCountMeanRMS(const TH1D *hnor, TH1D *&hmean)
293 //calculate from the ph calib hist the (mean-3sigma) ph-count in the chamber, save in the TH1D output
295 const Int_t ndet = 540;
296 TObjArray *obj=new TObjArray(ndet);
298 for(Int_t ii=0; ii<ndet; ii++){
299 obj->Add(new TVectorD(AliTRDseedV1::kNtb));
302 //ibin = binlowedge of bin(ibin+1) = the number fills this bin
303 for(Int_t ibin=0; ibin<hnor->GetNbinsX(); ibin++){
304 const Double_t stat = hnor->GetBinContent(ibin+1);
309 const Int_t idet = AliTRDdEdxBaseUtils::ToDetector(ibin);
310 const Int_t itb = AliTRDdEdxBaseUtils::ToTimeBin(ibin);
311 TVectorD *vec=(TVectorD *)obj->At(idet);
315 hmean = new TH1D(Form("%sdetmean", hnor->GetName()), "", hnor->GetNbinsX(), hnor->GetXaxis()->GetXmin(), hnor->GetXaxis()->GetXmax());
316 for(Int_t ibin=0; ibin<hnor->GetNbinsX(); ibin++){
317 const Int_t idet = AliTRDdEdxBaseUtils::ToDetector(ibin);
318 const TVectorD *vec=(TVectorD *)obj->At(idet);
321 for(Int_t ii=0; ii<vec->GetNrows(); ii++){
322 if((*vec)[ii]>EPSILON){
328 const Double_t lowfrac = 0.6;
329 //if there are too many 0's, reject this chamber by settig mean=rms=0
330 if(nonzero> (AliTRDseedV1::kNtb*(1-lowfrac)) ){
331 //only highest (1-lowfrac)*31 timebins are used to estimate the mean and rms! important! otherwise the 0' will make rms very large!
332 mean = AliTRDdEdxBaseUtils::TruncatedMean(AliTRDseedV1::kNtb, vec->GetMatrixArray(), lowfrac, 1);
335 hmean->SetBinContent(ibin+1, mean);
341 void AliTRDdEdxCalibUtils::Output(const TList *lin, Int_t run)
344 //produce calibration objects
348 for(Int_t iter=0; iter<8; iter++){
349 objnames+= AliTRDdEdxCalibHistArray::GetNameAt(iter)+" ";
352 TList * lout = new TList;
355 TTreeSRedirector *calibStream = new TTreeSRedirector(Form("TRDCalibStream_%010d.root", run));
357 const Int_t nh=lin->GetEntries();
358 for(Int_t ii=0; ii<nh; ii++){
359 const THnBase *hh=(THnBase*)lin->At(ii);
360 const TString hname = hh->GetName();
361 if(!objnames.Contains(hname))
364 TObjArray * cobj0 = HistToObj(hh, run, lout, calibStream);
370 //=============================================================
371 //=============================================================
373 TFile *fout=new TFile(Form("TRDCalibObj_%010d.root", run),"recreate");
375 const Int_t nout=lout->GetEntries();
376 for(Int_t ii=0; ii<nout; ii++){
377 const TString oname = lout->At(ii)->GetName();
378 if(oname.Contains("Obj")){
379 TObjArray * cobj = (TObjArray*) lout->At(ii);
380 cobj->Write(oname, TObjArray::kSingleKey);
387 fout=new TFile(Form("TRDCalibList_%010d.root", run),"recreate");
398 http://root.cern.ch/root/html/TH1.html
399 When an histogram is created, a reference to it is automatically added to the list of in-memory objects for the current file or directory. This default behaviour can be changed by:
401 h->SetDirectory(0); for the current histogram h
402 TH1::AddDirectory(kFALSE); sets a global switch disabling the reference
404 When the histogram is deleted, the reference to it is removed from the list of objects in memory. When a file is closed, all histograms in memory associated with this file are automatically deleted.
409 TObjArray* AliTRDdEdxCalibUtils::HistToObj(const THnBase *hh, Int_t run, TList *lout, TTreeSRedirector *calibStream)
412 //produce calibration objects
415 const TString hname = hh->GetName();
416 const Bool_t kinvq = TString(hname(hname.First('Q')+1,1)).Atoi()&4;
418 //----------------------------------------
419 // Define nbin, tag, cobj0
420 //----------------------------------------
421 const Int_t nbin = AliTRDdEdxBaseUtils::NTRDtimebin();
425 tag.ReplaceAll("Hist","Obj");
427 TObjArray * cobj0 = new TObjArray(1);
430 cobj0->Add(new TVectorD(nbin));
432 //----------------------------------------
433 // Define lowFrac, highFrac
434 //----------------------------------------
435 Double_t lowFrac = -999, highFrac = -999;
437 lowFrac = 0.01; highFrac = AliTRDdEdxBaseUtils::Q0Frac();
440 lowFrac = AliTRDdEdxBaseUtils::Q1Frac(); highFrac = 0.99;
443 //----------------------------------------
444 // Get analysis result
445 //----------------------------------------
446 TH1::AddDirectory(kFALSE);//important!
447 TH1D *hnor=0x0, *hmpv=0x0, *hres=0x0, *hwid=0x0, *htrdphmean = 0x0;//if(!lout), these have to be deleted
448 TH2D *hpj = hh->Projection(1,0);
449 AliTRDdEdxBaseUtils::FitSlicesY(hpj, hnor, hmpv, hwid, hres, 0, lowFrac, highFrac);
450 GetPHCountMeanRMS(hnor, htrdphmean);
452 lout->Add(htrdphmean);
463 //----------------------------------------
465 //----------------------------------------
466 TVectorD *countDet=0x0;
467 TObjArray *countSSL=0x0;
470 countDet=new TVectorD(540);
471 countSSL=new TObjArray(90);//SectorStackLayer
472 countSSL->SetOwner();
473 for(Int_t ii=0; ii<90; ii++){
474 countSSL->Add(new TVectorD(6));
478 //----------------------------------------
480 //----------------------------------------
482 //ibin = binlowedge of bin(ibin+1) = the number fills this bin
483 for(Int_t ibin=0; ibin<nbin; ibin++){
484 Double_t gnor = hnor->GetBinContent(ibin+1);
485 Double_t gmpv = hmpv->GetBinContent(ibin+1);
486 Double_t gwid = hwid->GetBinContent(ibin+1);
487 Double_t gres = hres->GetBinContent(ibin+1);
489 //--- set additional cut by kpass
490 Bool_t kpass = kTRUE;
491 Double_t gtrdphmean = -999;
493 gtrdphmean = htrdphmean->GetBinContent(ibin+1);
494 //chamber no statistics (e.g. too many 0's), not usual, not seen in run 143237
495 if(gtrdphmean<EPSILON){
498 if(gnor<AliTRDdEdxBaseUtils::TimeBinCountCut()*gtrdphmean){
503 //--- set calibration constant p0
507 //1)gnor<=3; truncation in hist: (0, 0.6*ntot=1.8 with ntot=3]={1}, in hist entries can pile up so that ntot=2, or 3, and (ntot>nstart && ntot<=nstop) is skipped;
508 //2)TruncatedMean(hist) out of range (only for Q0, not Q1).
510 if(gmpv>EPSILON && kpass){
511 if(tag.Contains("T0")){
517 //printf("outcalibobj%s %d %15.6e\n", tag.Data(), ibin, p0);
520 (*( (TVectorD*)cobj0->At(0) ))[ibin] = p0;
522 //--- save optional record
523 if(p0>EPSILON && countDet && countSSL){
524 const Int_t idet = AliTRDdEdxBaseUtils::ToDetector(ibin);
527 const Int_t isector = AliTRDdEdxBaseUtils::ToSector(ibin);
528 const Int_t istack = AliTRDdEdxBaseUtils::ToStack(ibin);
529 const Int_t ilayer = AliTRDdEdxBaseUtils::ToLayer(ibin);
530 TVectorD * vecsectorstack = (TVectorD*)countSSL->At(istack*18+isector);
531 (*vecsectorstack)[ilayer]=1;
535 (*calibStream)<<tag<<
543 "gtrdphmean="<<gtrdphmean<<
550 //----------------------------------------
552 //----------------------------------------
553 if(countDet && countSSL){
554 TVectorD count2Dstack(90);
555 for(Int_t ii=0; ii<90; ii++){
556 TVectorD * vecsectorstack = (TVectorD*)countSSL->At(ii);
557 const Int_t nlayer = (Int_t)vecsectorstack->Sum();
563 printf("\nAliTRDdEdxCalibUtils::GetCalibObj Summary run: %d name: %s entries: %.0f ndetector: %03.0f n2dstack %02.0f\n\n", run, hname.Data(), hh->GetEntries(), countDet->Sum(), count2Dstack.Sum());
566 //----------------------------------------
568 //----------------------------------------
570 TH1D **hhs[]={&hnor, &hmpv, &hwid, &hres, &htrdphmean};
571 const Int_t nhh=sizeof(hhs)/sizeof(TH1D**);
572 for(Int_t ihh=0; ihh<nhh; ihh++){
581 //----------------------------------------